Bug 1414834 - re-land print IPC changes from bug 1319423; r?bobowen draft
authorAlex Gaynor <agaynor@mozilla.com>
Fri, 03 Nov 2017 14:37:15 -0400
changeset 707029 d84dd81e7ecbdbae17182e78ae7cc5af68b9375d
parent 707028 bdb599143009e2facf0306169f729e679729d493
child 742848 16e79023c584fb2a256df6e4da29207140bfab7a
push id92012
push userbmo:agaynor@mozilla.com
push dateMon, 04 Dec 2017 19:40:31 +0000
reviewersbobowen
bugs1414834, 1319423
milestone59.0a1
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
layout/printing/DrawEventRecorder.cpp
layout/printing/DrawEventRecorder.h
layout/printing/ipc/PRemotePrintJob.ipdl
layout/printing/ipc/RemotePrintJobChild.cpp
layout/printing/ipc/RemotePrintJobChild.h
layout/printing/ipc/RemotePrintJobParent.cpp
layout/printing/ipc/RemotePrintJobParent.h
layout/printing/nsPagePrintTimer.cpp
widget/nsDeviceContextSpecProxy.cpp
widget/nsDeviceContextSpecProxy.h
--- 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