Bug 1414834 - re-land print IPC changes from
bug 1319423; r?bobowen
With this patch print IPC no longer requires the child process to create files.
Instead files are opened by the parent and a file descriptor is sent to the
child. This will allow us to sandbox child processes more aggressively.
MozReview-Commit-ID: GQWTYLV01kj
--- a/layout/printing/DrawEventRecorder.cpp
+++ b/layout/printing/DrawEventRecorder.cpp
@@ -14,22 +14,16 @@ DrawEventRecorderPRFileDesc::RecordEvent
{
WriteElement(mOutputStream, aEvent.GetType());
aEvent.RecordToStream(mOutputStream);
Flush();
}
-DrawEventRecorderPRFileDesc::DrawEventRecorderPRFileDesc(const char* aFilename)
-{
- mOutputStream.Open(aFilename);
- WriteHeader(mOutputStream);
-}
-
DrawEventRecorderPRFileDesc::~DrawEventRecorderPRFileDesc()
{
if (IsOpen()) {
Close();
}
}
void
@@ -40,21 +34,21 @@ DrawEventRecorderPRFileDesc::Flush()
bool
DrawEventRecorderPRFileDesc::IsOpen()
{
return mOutputStream.IsOpen();
}
void
-DrawEventRecorderPRFileDesc::OpenNew(const char* aFilename)
+DrawEventRecorderPRFileDesc::OpenFD(PRFileDesc* aFd)
{
MOZ_ASSERT(!IsOpen());
- mOutputStream.Open(aFilename);
+ mOutputStream.OpenFD(aFd);
WriteHeader(mOutputStream);
}
void
DrawEventRecorderPRFileDesc::Close()
{
MOZ_ASSERT(IsOpen());
--- a/layout/printing/DrawEventRecorder.h
+++ b/layout/printing/DrawEventRecorder.h
@@ -20,19 +20,20 @@ class PRFileDescStream : public mozilla:
// Most writes, as seen in the print IPC use case, are very small (<32 bytes),
// with a small number of very large (>40KB) writes. Writes larger than this
// value are not buffered.
static const size_t kBufferSize = 1024;
public:
PRFileDescStream() : mFd(nullptr), mBuffer(nullptr), mBufferPos(0),
mGood(true) {}
- void Open(const char* aFilename) {
+ void OpenFD(PRFileDesc* aFd)
+ {
MOZ_ASSERT(!IsOpen());
- mFd = PR_Open(aFilename, PR_RDWR | PR_CREATE_FILE, PR_IRUSR | PR_IWUSR);
+ mFd = aFd;
mGood = true;
mBuffer.reset(new uint8_t[kBufferSize]);
mBufferPos = 0;
}
void Close() {
// We need to be API compatible with std::ostream, and so we silently handle
// closes on a closed FD.
@@ -113,32 +114,30 @@ private:
size_t mBufferPos;
bool mGood;
};
class DrawEventRecorderPRFileDesc : public gfx::DrawEventRecorderPrivate
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPRFileDesc, override)
- explicit DrawEventRecorderPRFileDesc(const char* aFilename);
+ explicit DrawEventRecorderPRFileDesc(){};
~DrawEventRecorderPRFileDesc();
void RecordEvent(const gfx::RecordedEvent& aEvent) override;
/**
* Returns whether a recording file is currently open.
*/
bool IsOpen();
/**
- * Opens new file with the provided name. The recorder does NOT forget which
- * objects it has recorded. This can be used with Close, so that a recording
- * can be processed in chunks. The file must not already be open.
+ * Opens the recorder with the provided PRFileDesc *.
*/
- void OpenNew(const char* aFilename);
+ void OpenFD(PRFileDesc* aFd);
/**
* Closes the file so that it can be processed. The recorder does NOT forget
* which objects it has recorded. This can be used with OpenNew, so that a
* recording can be processed in chunks. The file must be open.
*/
void Close();
--- a/layout/printing/ipc/PRemotePrintJob.ipdl
+++ b/layout/printing/ipc/PRemotePrintJob.ipdl
@@ -17,19 +17,19 @@ both:
// Tell either side to abort printing and clean up.
async AbortPrint(nsresult aRv);
parent:
// Initialize the real print device with the given information.
async InitializePrint(nsString aDocumentTitle, nsString aPrintToFile,
int32_t aStartPage, int32_t aEndPage);
- // Translate the stored page recording and play back the events to the real
- // print device.
- async ProcessPage(nsCString aPageFileName);
+ // Translate the page recording writen into |fd| and play back the events to
+ // the real print device.
+ async ProcessPage();
// This informs the real print device that we've finished, so it can trigger
// the actual print.
async FinalizePrint();
// Report a state change to listeners in the parent process.
async StateChange(long aStateFlags,
nsresult aStatus);
@@ -40,19 +40,21 @@ parent:
long aCurTotalProgress,
long aMaxTotalProgress);
// Report a status change to listeners in the parent process.
async StatusChange(nsresult aStatus);
child:
// Inform the child that the print has been initialized in the parent or has
- // failed with result aRv.
- async PrintInitializationResult(nsresult aRv);
+ // failed with result aRv. Includes a file descriptor which the first page
+ // can be written to.
+ async PrintInitializationResult(nsresult aRv, FileDescriptor aFd);
- // Inform the child that the latest page has been processed remotely.
- async PageProcessed();
+ // Inform the child that the latest page has been processed remotely. Includes
+ // a file descriptor which the next page can be written to.
+ async PageProcessed(FileDescriptor aFd);
async __delete__();
};
} // namespace layout
} // namespace mozilla
--- a/layout/printing/ipc/RemotePrintJobChild.cpp
+++ b/layout/printing/ipc/RemotePrintJobChild.cpp
@@ -4,16 +4,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemotePrintJobChild.h"
#include "mozilla/Unused.h"
#include "nsPagePrintTimer.h"
#include "nsPrintEngine.h"
+#include "private/pprio.h"
namespace mozilla {
namespace layout {
NS_IMPL_ISUPPORTS(RemotePrintJobChild,
nsIWebProgressListener)
RemotePrintJobChild::RemotePrintJobChild()
@@ -31,36 +32,58 @@ RemotePrintJobChild::InitializePrint(con
Unused << SendInitializePrint(aDocumentTitle, aPrintToFile, aStartPage,
aEndPage);
mozilla::SpinEventLoopUntil([&]() { return mPrintInitialized; });
return mInitializationResult;
}
mozilla::ipc::IPCResult
-RemotePrintJobChild::RecvPrintInitializationResult(const nsresult& aRv)
+RemotePrintJobChild::RecvPrintInitializationResult(
+ const nsresult& aRv,
+ const mozilla::ipc::FileDescriptor& aFd)
{
mPrintInitialized = true;
mInitializationResult = aRv;
+ if (NS_SUCCEEDED(aRv)) {
+ SetNextPageFD(aFd);
+ }
return IPC_OK();
}
+PRFileDesc*
+RemotePrintJobChild::GetNextPageFD()
+{
+ MOZ_ASSERT(mNextPageFD);
+ PRFileDesc* fd = mNextPageFD;
+ mNextPageFD = nullptr;
+ return fd;
+}
+
void
-RemotePrintJobChild::ProcessPage(const nsCString& aPageFileName)
+RemotePrintJobChild::SetNextPageFD(const mozilla::ipc::FileDescriptor& aFd)
+{
+ auto handle = aFd.ClonePlatformHandle();
+ mNextPageFD = PR_ImportFile(PROsfd(handle.release()));
+}
+
+void
+RemotePrintJobChild::ProcessPage()
{
MOZ_ASSERT(mPagePrintTimer);
mPagePrintTimer->WaitForRemotePrint();
- Unused << SendProcessPage(aPageFileName);
+ Unused << SendProcessPage();
}
mozilla::ipc::IPCResult
-RemotePrintJobChild::RecvPageProcessed()
+RemotePrintJobChild::RecvPageProcessed(const mozilla::ipc::FileDescriptor& aFd)
{
MOZ_ASSERT(mPagePrintTimer);
+ SetNextPageFD(aFd);
mPagePrintTimer->RemotePrintFinished();
return IPC_OK();
}
mozilla::ipc::IPCResult
RemotePrintJobChild::RecvAbortPrint(const nsresult& aRv)
{
--- a/layout/printing/ipc/RemotePrintJobChild.h
+++ b/layout/printing/ipc/RemotePrintJobChild.h
@@ -29,33 +29,39 @@ public:
void ActorDestroy(ActorDestroyReason aWhy) final;
nsresult InitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage);
- mozilla::ipc::IPCResult RecvPrintInitializationResult(const nsresult& aRv) final;
+ mozilla::ipc::IPCResult RecvPrintInitializationResult(
+ const nsresult& aRv,
+ const FileDescriptor& aFd) final;
- void ProcessPage(const nsCString& aPageFileName);
+ void ProcessPage();
- mozilla::ipc::IPCResult RecvPageProcessed() final;
+ mozilla::ipc::IPCResult RecvPageProcessed(const FileDescriptor& aFd) final;
mozilla::ipc::IPCResult RecvAbortPrint(const nsresult& aRv) final;
void SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer);
void SetPrintEngine(nsPrintEngine* aPrintEngine);
+ PRFileDesc* GetNextPageFD();
+
private:
~RemotePrintJobChild() final;
+ void SetNextPageFD(const mozilla::ipc::FileDescriptor& aFd);
bool mPrintInitialized = false;
nsresult mInitializationResult = NS_OK;
RefPtr<nsPagePrintTimer> mPagePrintTimer;
RefPtr<nsPrintEngine> mPrintEngine;
+ PRFileDesc* mNextPageFD = nullptr;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_RemotePrintJobChild_h
--- a/layout/printing/ipc/RemotePrintJobParent.cpp
+++ b/layout/printing/ipc/RemotePrintJobParent.cpp
@@ -14,16 +14,18 @@
#include "nsAppDirectoryServiceDefs.h"
#include "nsComponentManagerUtils.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDeviceContext.h"
#include "nsIDeviceContextSpec.h"
#include "nsIPrintSettings.h"
#include "nsIWebProgressListener.h"
#include "PrintTranslator.h"
+#include "private/pprio.h"
+#include "nsAnonymousTemporaryFile.h"
namespace mozilla {
namespace layout {
RemotePrintJobParent::RemotePrintJobParent(nsIPrintSettings* aPrintSettings)
: mPrintSettings(aPrintSettings)
{
MOZ_COUNT_CTOR(RemotePrintJobParent);
@@ -33,24 +35,31 @@ mozilla::ipc::IPCResult
RemotePrintJobParent::RecvInitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage)
{
nsresult rv = InitializePrintDevice(aDocumentTitle, aPrintToFile, aStartPage,
aEndPage);
if (NS_FAILED(rv)) {
- Unused << SendPrintInitializationResult(rv);
+ Unused << SendPrintInitializationResult(rv, FileDescriptor());
Unused << Send__delete__(this);
return IPC_OK();
}
mPrintTranslator.reset(new PrintTranslator(mPrintDeviceContext));
- Unused << SendPrintInitializationResult(NS_OK);
+ FileDescriptor fd;
+ rv = PrepareNextPageFD(&fd);
+ if (NS_FAILED(rv)) {
+ Unused << SendPrintInitializationResult(rv, FileDescriptor());
+ Unused << Send__delete__(this);
+ return IPC_OK();
+ }
+ Unused << SendPrintInitializationResult(NS_OK, fd);
return IPC_OK();
}
nsresult
RemotePrintJobParent::InitializePrintDevice(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage)
@@ -77,76 +86,75 @@ RemotePrintJobParent::InitializePrintDev
aStartPage, aEndPage);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
+nsresult
+RemotePrintJobParent::PrepareNextPageFD(FileDescriptor* aFd)
+{
+ PRFileDesc* prFd = nullptr;
+ nsresult rv = NS_OpenAnonymousTemporaryFile(&prFd);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ *aFd = FileDescriptor(
+ FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(prFd)));
+ mCurrentPageStream.OpenFD(prFd);
+ return NS_OK;
+}
+
mozilla::ipc::IPCResult
-RemotePrintJobParent::RecvProcessPage(const nsCString& aPageFileName)
+RemotePrintJobParent::RecvProcessPage()
{
- nsresult rv = PrintPage(aPageFileName);
+ if (!mCurrentPageStream.IsOpen()) {
+ Unused << SendAbortPrint(NS_ERROR_FAILURE);
+ return IPC_OK();
+ }
+ mCurrentPageStream.Seek(0, PR_SEEK_SET);
+ nsresult rv = PrintPage(mCurrentPageStream);
+ mCurrentPageStream.Close();
if (NS_FAILED(rv)) {
Unused << SendAbortPrint(rv);
- } else {
- Unused << SendPageProcessed();
+ return IPC_OK();
}
+ FileDescriptor fd;
+ rv = PrepareNextPageFD(&fd);
+ if (NS_FAILED(rv)) {
+ Unused << SendAbortPrint(rv);
+ return IPC_OK();
+ }
+
+ Unused << SendPageProcessed(fd);
return IPC_OK();
}
nsresult
-RemotePrintJobParent::PrintPage(const nsCString& aPageFileName)
+RemotePrintJobParent::PrintPage(PRFileDescStream& aRecording)
{
MOZ_ASSERT(mPrintDeviceContext);
nsresult rv = mPrintDeviceContext->BeginPage();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
-
- nsCOMPtr<nsIFile> recordingFile;
- rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
- getter_AddRefs(recordingFile));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- rv = recordingFile->AppendNative(aPageFileName);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- nsAutoCString recordingPath;
- rv = recordingFile->GetNativePath(recordingPath);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- PRFileDescStream recording;
- recording.Open(recordingPath.get());
- MOZ_ASSERT(recording.IsOpen());
- if (!mPrintTranslator->TranslateRecording(recording)) {
+ if (!mPrintTranslator->TranslateRecording(aRecording)) {
return NS_ERROR_FAILURE;
}
rv = mPrintDeviceContext->EndPage();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
- recording.Close();
- rv = recordingFile->Remove(/* recursive= */ false);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
return NS_OK;
}
mozilla::ipc::IPCResult
RemotePrintJobParent::RecvFinalizePrint()
{
// EndDocument is sometimes called in the child even when BeginDocument has
// not been called. See bug 1223332.
--- a/layout/printing/ipc/RemotePrintJobParent.h
+++ b/layout/printing/ipc/RemotePrintJobParent.h
@@ -3,21 +3,23 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_layout_RemotePrintJobParent_h
#define mozilla_layout_RemotePrintJobParent_h
#include "mozilla/layout/PRemotePrintJobParent.h"
+#include "mozilla/layout/printing/DrawEventRecorder.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/gfx/RecordedEvent.h"
class nsDeviceContext;
class nsIPrintSettings;
class nsIWebProgressListener;
class PrintTranslator;
namespace mozilla {
namespace layout {
@@ -29,17 +31,17 @@ public:
void ActorDestroy(ActorDestroyReason aWhy) final;
mozilla::ipc::IPCResult RecvInitializePrint(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage) final;
- mozilla::ipc::IPCResult RecvProcessPage(const nsCString& aPageFileName) final;
+ mozilla::ipc::IPCResult RecvProcessPage() final;
mozilla::ipc::IPCResult RecvFinalizePrint() final;
mozilla::ipc::IPCResult RecvAbortPrint(const nsresult& aRv) final;
mozilla::ipc::IPCResult RecvStateChange(const long& aStateFlags,
const nsresult& aStatus) final;
@@ -65,20 +67,23 @@ public:
private:
~RemotePrintJobParent() final;
nsresult InitializePrintDevice(const nsString& aDocumentTitle,
const nsString& aPrintToFile,
const int32_t& aStartPage,
const int32_t& aEndPage);
- nsresult PrintPage(const nsCString& aPageFileName);
+ nsresult PrepareNextPageFD(FileDescriptor* aFd);
+
+ nsresult PrintPage(PRFileDescStream& aRecording);
nsCOMPtr<nsIPrintSettings> mPrintSettings;
RefPtr<nsDeviceContext> mPrintDeviceContext;
UniquePtr<PrintTranslator> mPrintTranslator;
nsCOMArray<nsIWebProgressListener> mPrintProgressListeners;
+ PRFileDescStream mCurrentPageStream;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_RemotePrintJobParent_h
--- a/layout/printing/nsPagePrintTimer.cpp
+++ b/layout/printing/nsPagePrintTimer.cpp
@@ -140,17 +140,18 @@ nsPagePrintTimer::Notify(nsITimer *timer
if (mWatchDogCount > WATCH_DOG_MAX_COUNT) {
Fail();
return NS_OK;
}
}
if (mDocViewerPrint) {
bool donePrePrint = true;
- if (mPrintEngine) {
+ // Don't start to pre-print if we're waiting on the parent still.
+ if (mPrintEngine && !mWaitingForRemotePrint) {
donePrePrint = mPrintEngine->PrePrintPage();
}
if (donePrePrint && !mWaitingForRemotePrint) {
StopWatchDogTimer();
// Pass nullptr here since name already was set in constructor.
mDocument->Dispatch(TaskCategory::Other, do_AddRef(this));
} else {
--- a/widget/nsDeviceContextSpecProxy.cpp
+++ b/widget/nsDeviceContextSpecProxy.cpp
@@ -14,16 +14,17 @@
#include "mozilla/RefPtr.h"
#include "mozilla/Unused.h"
#include "nsComponentManagerUtils.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsIPrintSession.h"
#include "nsIPrintSettings.h"
#include "nsIUUIDGenerator.h"
+#include "private/pprio.h"
using mozilla::Unused;
using namespace mozilla;
using namespace mozilla::gfx;
NS_IMPL_ISUPPORTS(nsDeviceContextSpecProxy, nsIDeviceContextSpec)
@@ -60,27 +61,16 @@ nsDeviceContextSpecProxy::Init(nsIWidget
}
rv = mPrintSession->GetRemotePrintJob(getter_AddRefs(mRemotePrintJob));
if (NS_FAILED(rv) || !mRemotePrintJob) {
NS_WARNING("We can't print via the parent without a RemotePrintJobChild.");
return NS_ERROR_FAILURE;
}
- rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
- getter_AddRefs(mRecordingDir));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- mUuidGenerator = do_GetService("@mozilla.org/uuid-generator;1", &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
return NS_OK;
}
already_AddRefed<PrintTarget>
nsDeviceContextSpecProxy::MakePrintTarget()
{
MOZ_ASSERT(mRealDeviceContextSpec);
@@ -138,58 +128,22 @@ nsDeviceContextSpecProxy::GetDPI()
float
nsDeviceContextSpecProxy::GetPrintingScale()
{
MOZ_ASSERT(mRealDeviceContextSpec);
return mRealDeviceContextSpec->GetPrintingScale();
}
-nsresult
-nsDeviceContextSpecProxy::CreateUniqueTempPath(nsACString& aFilePath)
-{
- MOZ_ASSERT(mRecordingDir);
- MOZ_ASSERT(mUuidGenerator);
-
- nsID uuid;
- nsresult rv = mUuidGenerator->GenerateUUIDInPlace(&uuid);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- char uuidChars[NSID_LENGTH];
- uuid.ToProvidedString(uuidChars);
- mRecordingFileName.AssignASCII(uuidChars);
-
- nsCOMPtr<nsIFile> recordingFile;
- rv = mRecordingDir->Clone(getter_AddRefs(recordingFile));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- rv = recordingFile->AppendNative(mRecordingFileName);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- return recordingFile->GetNativePath(aFilePath);
-}
-
NS_IMETHODIMP
nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage, int32_t aEndPage)
{
- nsAutoCString recordingPath;
- nsresult rv = CreateUniqueTempPath(recordingPath);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc(recordingPath.get());
+ mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc();
return mRemotePrintJob->InitializePrint(nsString(aTitle),
nsString(aPrintToFileName),
aStartPage, aEndPage);
}
NS_IMETHODIMP
nsDeviceContextSpecProxy::EndDocument()
{
@@ -202,31 +156,22 @@ nsDeviceContextSpecProxy::AbortDocument(
{
Unused << mRemotePrintJob->SendAbortPrint(NS_OK);
return NS_OK;
}
NS_IMETHODIMP
nsDeviceContextSpecProxy::BeginPage()
{
- // Reopen the file, if necessary, ready for the next page.
- if (!mRecorder->IsOpen()) {
- nsAutoCString recordingPath;
- nsresult rv = CreateUniqueTempPath(recordingPath);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- mRecorder->OpenNew(recordingPath.get());
- }
+ mRecorder->OpenFD(mRemotePrintJob->GetNextPageFD());
return NS_OK;
}
NS_IMETHODIMP
nsDeviceContextSpecProxy::EndPage()
{
// Send the page recording to the parent.
mRecorder->Close();
- mRemotePrintJob->ProcessPage(mRecordingFileName);
+ mRemotePrintJob->ProcessPage();
return NS_OK;
}
--- a/widget/nsDeviceContextSpecProxy.h
+++ b/widget/nsDeviceContextSpecProxy.h
@@ -49,21 +49,16 @@ public:
NS_IMETHOD BeginPage() final;
NS_IMETHOD EndPage() final;
private:
~nsDeviceContextSpecProxy() {}
- nsresult CreateUniqueTempPath(nsACString& aFilePath);
-
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsIPrintSession> mPrintSession;
nsCOMPtr<nsIDeviceContextSpec> mRealDeviceContextSpec;
RefPtr<mozilla::layout::RemotePrintJobChild> mRemotePrintJob;
RefPtr<mozilla::layout::DrawEventRecorderPRFileDesc> mRecorder;
- nsCOMPtr<nsIFile> mRecordingDir;
- nsCOMPtr<nsIUUIDGenerator> mUuidGenerator;
- nsCString mRecordingFileName;
};
#endif // nsDeviceContextSpecProxy_h