Bug 1399787 - Part 13. Handle AbortDocument. r=jwatt
☠☠ backed out by f0afedbc68cf ☠ ☠
authorcku <cku@mozilla.com>
Sun, 05 Nov 2017 15:34:54 +0800
changeset 449822 8f600ac930ecfa6b064b288f17d7063df2a89247
parent 449821 c478fb75f5cbeb891a3e6cce0716f295b2eec042
child 449823 d875e45f591e3a4d445e0fb5c6970ee3cf963d93
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs1399787
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1399787 - Part 13. Handle AbortDocument. r=jwatt While aborting conversion, we need to make sure there is no coversion task executing in the PDFium process before destroying it. MozReview-Commit-ID: 3Iqhe8KmYv2
gfx/thebes/PrintTargetEMF.cpp
gfx/thebes/PrintTargetEMF.h
widget/windows/PDFiumParent.cpp
widget/windows/PDFiumParent.h
widget/windows/PDFiumProcessParent.cpp
widget/windows/PDFiumProcessParent.h
--- a/gfx/thebes/PrintTargetEMF.cpp
+++ b/gfx/thebes/PrintTargetEMF.cpp
@@ -16,23 +16,24 @@ using mozilla::gfx::DrawTarget;
 using mozilla::ipc::FileDescriptor;
 
 namespace mozilla {
 namespace gfx {
 
 PrintTargetEMF::PrintTargetEMF(HDC aDC, const IntSize& aSize)
   : PrintTarget(/* not using cairo_surface_t */ nullptr, aSize)
   , mPrinterDC(aDC)
+  , mWaitingForEMFConversion(false)
 {
 }
 
 PrintTargetEMF::~PrintTargetEMF()
 {
   if (mPDFiumProcess) {
-    mPDFiumProcess->Delete();
+    mPDFiumProcess->Delete(mWaitingForEMFConversion);
   }
 }
 
 /* static */ already_AddRefed<PrintTargetEMF>
 PrintTargetEMF::CreateOrNull(HDC aDC, const IntSize& aSizeInPoints)
 {
   return do_AddRef(new PrintTargetEMF(aDC, aSizeInPoints));
 }
@@ -120,16 +121,17 @@ PrintTargetEMF::EndPage()
   nsresult rv = mPDFFileForOnePage->OpenNSPRFileDesc(PR_RDONLY, PR_IRWXU,
                                                      &prfile);
   NS_ENSURE_SUCCESS(rv, rv);
   FileDescriptor descriptor(FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(prfile)));
   mPDFiumProcess->GetActor()->SendConvertToEMF(descriptor,
                                         ::GetDeviceCaps(mPrinterDC, HORZRES),
                                         ::GetDeviceCaps(mPrinterDC, VERTRES));
   PR_Close(prfile);
+  mWaitingForEMFConversion = true;
 
   return NS_OK;
 }
 
 already_AddRefed<DrawTarget>
 PrintTargetEMF::MakeDrawTarget(const IntSize& aSize,
                                DrawEventRecorder* aRecorder)
 {
@@ -150,16 +152,18 @@ PrintTargetEMF::GetReferenceDrawTarget(D
 
   return mRefDT.forget();
 }
 
 void
 PrintTargetEMF::ConvertToEMFDone(const nsresult& aResult,
                                  mozilla::ipc::Shmem&& aEMF)
 {
+  mWaitingForEMFConversion = false;
+
   if (::StartPage(mPrinterDC) > 0) {
     mozilla::widget::WindowsEMF emf;
     emf.InitFromFileContents(aEMF.get<BYTE>(), aEMF.Size<BYTE>());
     RECT printRect = {0, 0, ::GetDeviceCaps(mPrinterDC, HORZRES),
                       ::GetDeviceCaps(mPrinterDC, VERTRES)};
     DebugOnly<bool> ret = emf.Playback(mPrinterDC, printRect);
     MOZ_ASSERT(ret);
 
--- a/gfx/thebes/PrintTargetEMF.h
+++ b/gfx/thebes/PrintTargetEMF.h
@@ -62,14 +62,15 @@ private:
   ~PrintTargetEMF() override;
 
   nsString mTitle;
   RefPtr<PrintTargetSkPDF> mTargetForCurrentPage;
   nsCOMPtr<nsIFile>        mPDFFileForOnePage;
   RefPtr<PrintTargetSkPDF> mRefTarget;
   PDFiumProcessParent*     mPDFiumProcess;
   HDC mPrinterDC;
+  bool mWaitingForEMFConversion;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_PRINTTARGETEMF_H */
--- a/widget/windows/PDFiumParent.cpp
+++ b/widget/windows/PDFiumParent.cpp
@@ -24,29 +24,47 @@ PDFiumParent::Init(IPC::Channel* aChanne
 
   AddRef();
   return true;
 }
 
 void
 PDFiumParent::ActorDestroy(ActorDestroyReason aWhy)
 {
+  if (mConversionDoneCallback) {
+    // Since this printing job was aborted, we do not need to report EMF buffer
+    // back to mTarget.
+    mConversionDoneCallback();
+  }
 }
 
 mozilla::ipc::IPCResult
 PDFiumParent::RecvConvertToEMFDone(const nsresult& aResult,
                                    mozilla::ipc::Shmem&& aEMFContents)
 {
   MOZ_ASSERT(aEMFContents.IsReadable());
-  mTarget->ConvertToEMFDone(aResult, Move(aEMFContents));
+
+  if (mTarget) {
+    MOZ_ASSERT(!mConversionDoneCallback);
+    mTarget->ConvertToEMFDone(aResult, Move(aEMFContents));
+  }
 
   return IPC_OK();
 }
 
 void
+PDFiumParent::AbortConversion(ConversionDoneCallback aCallback)
+{
+  // There is no need to report EMF contents back to mTarget since the print
+  // job was aborted, unset mTarget.
+  mTarget = nullptr;
+  mConversionDoneCallback = aCallback;
+}
+
+void
 PDFiumParent::OnChannelConnected(int32_t pid)
 {
   SetOtherProcessId(pid);
 }
 
 void
 PDFiumParent::DeallocPPDFiumParent()
 {
--- a/widget/windows/PDFiumParent.h
+++ b/widget/windows/PDFiumParent.h
@@ -18,32 +18,36 @@ namespace mozilla {
 namespace widget {
 
 class PDFiumParent final : public PPDFiumParent,
                            public mozilla::ipc::IShmemAllocator
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PDFiumParent)
 
   typedef mozilla::gfx::PrintTargetEMF PrintTargetEMF;
+  typedef std::function<void()> ConversionDoneCallback;
 
   explicit PDFiumParent(PrintTargetEMF* aTarget);
 
   bool Init(IPC::Channel* aChannel, base::ProcessId aPid);
 
+  void AbortConversion(ConversionDoneCallback aCallback);
+
   FORWARD_SHMEM_ALLOCATOR_TO(PPDFiumParent)
 private:
   ~PDFiumParent() {}
 
   // PPDFiumParent functions.
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   mozilla::ipc::IPCResult RecvConvertToEMFDone(const nsresult& aResult,
                                                mozilla::ipc::Shmem&& aEMFContents) override;
   void OnChannelConnected(int32_t pid) override;
   void DeallocPPDFiumParent() override;
 
   PrintTargetEMF* mTarget;
+  ConversionDoneCallback mConversionDoneCallback;
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif // PDFIUMPARENT_H_
--- a/widget/windows/PDFiumProcessParent.cpp
+++ b/widget/windows/PDFiumProcessParent.cpp
@@ -44,30 +44,39 @@ PDFiumProcessParent::Launch(PrintTargetE
   // Open the top level protocol for PDFium process.
   MOZ_ASSERT(!mPDFiumParentActor);
   mPDFiumParentActor = new PDFiumParent(aTarget);
   return mPDFiumParentActor->Init(GetChannel(),
                             base::GetProcId(GetChildProcessHandle()));
 }
 
 void
-PDFiumProcessParent::Delete()
+PDFiumProcessParent::Delete(bool aWaitingForEMFConversion)
 {
+  if (aWaitingForEMFConversion) {
+    // Can not kill the PDFium process yet since we are still waiting for a
+    // EMF conversion response.
+    mPDFiumParentActor->AbortConversion([this]() { Delete(false); });
+    mPDFiumParentActor->Close();
+    return;
+  }
+
   // PDFiumProcessParent::Launch is not called, protocol is not created.
   // It is safe to destroy this object on any thread.
   if (!mLaunchThread) {
     delete this;
     return;
   }
 
   if (mLaunchThread == NS_GetCurrentThread()) {
     delete this;
     return;
   }
 
   mLaunchThread->Dispatch(
-    NewNonOwningRunnableMethod("PDFiumProcessParent::Delete",
-                               this,
-                               &PDFiumProcessParent::Delete));
+    NewNonOwningRunnableMethod<bool>("PDFiumProcessParent::Delete",
+                                     this,
+                                     &PDFiumProcessParent::Delete,
+                                     false));
 }
 
 } // namespace widget
 } // namespace mozilla
--- a/widget/windows/PDFiumProcessParent.h
+++ b/widget/windows/PDFiumProcessParent.h
@@ -32,17 +32,17 @@ class PDFiumProcessParent final : public
 public:
   typedef mozilla::gfx::PrintTargetEMF PrintTargetEMF;
 
   PDFiumProcessParent();
   ~PDFiumProcessParent();
 
   bool Launch(PrintTargetEMF* aTarget);
 
-  void Delete();
+  void Delete(bool aWaitingForEMFConversion);
 
   bool CanShutdown() override { return true; }
 
   PDFiumParent* GetActor() const { return mPDFiumParentActor; }
 private:
 
   DISALLOW_COPY_AND_ASSIGN(PDFiumProcessParent);