Bug 1399787 - Part 15. Detect and handle breakage of the IPC channel. r=jwatt
☠☠ backed out by 2e0485d0998d ☠ ☠
authorcku <cku@mozilla.com>
Mon, 06 Nov 2017 22:12:31 +0800
changeset 395705 2e91a90dfbc34470965de3996dcadee633385f1d
parent 395704 e82ab72f71eee8f1d7e1a0b09df0c619b27850cc
child 395706 fc9776a2605d47643fef7adaad681c54c2265f54
push id33054
push userrgurzau@mozilla.com
push dateFri, 08 Dec 2017 21:57:23 +0000
treeherdermozilla-central@6e2181b6137c [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 15. Detect and handle breakage of the IPC channel. r=jwatt MozReview-Commit-ID: 6VfIbstJ6WN
gfx/thebes/PrintTargetEMF.cpp
gfx/thebes/PrintTargetEMF.h
widget/windows/PDFiumParent.cpp
widget/windows/PDFiumParent.h
--- a/gfx/thebes/PrintTargetEMF.cpp
+++ b/gfx/thebes/PrintTargetEMF.cpp
@@ -17,16 +17,17 @@ 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)
+  , mChannelBroken(false)
 {
 }
 
 PrintTargetEMF::~PrintTargetEMF()
 {
   if (mPDFiumProcess) {
     mPDFiumProcess->Delete(mWaitingForEMFConversion);
   }
@@ -63,36 +64,39 @@ PrintTargetEMF::BeginPrinting(const nsAS
   docinfo.lpszDatatype = nullptr;
   docinfo.fwType = 0;
 
   ::StartDocW(mPrinterDC, &docinfo);
 
   mPDFiumProcess = new PDFiumProcessParent();
   NS_ENSURE_TRUE(mPDFiumProcess->Launch(this), NS_ERROR_FAILURE);
 
+  mChannelBroken = false;
+
   return NS_OK;
 }
 
 nsresult
 PrintTargetEMF::EndPrinting()
 {
+  mPDFiumProcess->GetActor()->EndConversion();
   return (::EndDoc(mPrinterDC) <= 0) ? NS_ERROR_FAILURE : NS_OK;
 }
 
 nsresult
 PrintTargetEMF::AbortPrinting()
 {
   return (::AbortDoc(mPrinterDC) <= 0) ? NS_ERROR_FAILURE : NS_OK;
 }
 
 nsresult
 PrintTargetEMF::BeginPage()
 {
   MOZ_ASSERT(!mPDFFileForOnePage && !mTargetForCurrentPage);
-
+  NS_ENSURE_TRUE(!mChannelBroken, NS_ERROR_FAILURE);
   NS_ENSURE_TRUE(::StartPage(mPrinterDC) >0, NS_ERROR_FAILURE);
 
   // We create a new file for each page so that we can make sure each new
   // mPDFFileForOnePage contains one single page.
   nsresult rv =
    NS_OpenAnonymousTemporaryNsIFile(getter_AddRefs(mPDFFileForOnePage));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
@@ -107,39 +111,46 @@ PrintTargetEMF::BeginPage()
   mTargetForCurrentPage->BeginPage();
 
   return NS_OK;
 }
 
 nsresult
 PrintTargetEMF::EndPage()
 {
+  NS_ENSURE_TRUE(!mChannelBroken, NS_ERROR_FAILURE);
+
   mTargetForCurrentPage->EndPage();
   mTargetForCurrentPage->EndPrinting();
   mTargetForCurrentPage->Finish();
   mTargetForCurrentPage = nullptr;
 
   PRFileDesc* prfile;
   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,
+  if (!mPDFiumProcess->GetActor()->SendConvertToEMF(descriptor,
                                         ::GetDeviceCaps(mPrinterDC, HORZRES),
-                                        ::GetDeviceCaps(mPrinterDC, VERTRES));
+                                        ::GetDeviceCaps(mPrinterDC, VERTRES)))
+  {
+    return NS_ERROR_FAILURE;
+  }
+
   PR_Close(prfile);
   mWaitingForEMFConversion = true;
 
   return NS_OK;
 }
 
 already_AddRefed<DrawTarget>
 PrintTargetEMF::MakeDrawTarget(const IntSize& aSize,
                                DrawEventRecorder* aRecorder)
 {
+  MOZ_ASSERT(!mChannelBroken);
   return mTargetForCurrentPage->MakeDrawTarget(aSize, aRecorder);
 }
 
 already_AddRefed<DrawTarget>
 PrintTargetEMF::GetReferenceDrawTarget(DrawEventRecorder* aRecorder)
 {
   if (!mRefTarget) {
     auto dummy = MakeUnique<SkNullWStream>();
@@ -157,21 +168,17 @@ void
 PrintTargetEMF::ConvertToEMFDone(const nsresult& aResult,
                                  mozilla::ipc::Shmem&& aEMF)
 {
   MOZ_ASSERT_IF(NS_FAILED(aResult), aEMF.Size<uint8_t>() == 0);
   MOZ_ASSERT(!mChannelBroken, "It is not possible to get conversion callback "
                               "after the channel was broken.");
 
   mWaitingForEMFConversion = false;
-<<<<<<< local
   if (NS_SUCCEEDED(aResult)) {
-=======
-  if (NS_SUCCESSED(aResult)) {
->>>>>>> histedit
     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
@@ -51,26 +51,28 @@ public:
   MakeDrawTarget(const IntSize& aSize,
                  DrawEventRecorder* aRecorder = nullptr) final;
 
   already_AddRefed<DrawTarget>
   GetReferenceDrawTarget(DrawEventRecorder* aRecorder) final;
 
   void ConvertToEMFDone(const nsresult& aResult, mozilla::ipc::Shmem&& aEMF);
   bool IsSyncPagePrinting() const final { return false; }
+  void ChannelIsBroken() { mChannelBroken = true; }
 
 private:
   PrintTargetEMF(HDC aDC, const IntSize& aSize);
   ~PrintTargetEMF() override;
 
   nsString mTitle;
   RefPtr<PrintTargetSkPDF> mTargetForCurrentPage;
   nsCOMPtr<nsIFile>        mPDFFileForOnePage;
   RefPtr<PrintTargetSkPDF> mRefTarget;
   PDFiumProcessParent*     mPDFiumProcess;
   HDC mPrinterDC;
   bool mWaitingForEMFConversion;
+  bool mChannelBroken;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_PRINTTARGETEMF_H */
--- a/widget/windows/PDFiumParent.cpp
+++ b/widget/windows/PDFiumParent.cpp
@@ -24,16 +24,20 @@ PDFiumParent::Init(IPC::Channel* aChanne
 
   AddRef();
   return true;
 }
 
 void
 PDFiumParent::ActorDestroy(ActorDestroyReason aWhy)
 {
+  if (mTarget) {
+    mTarget->ChannelIsBroken();
+  }
+
   if (mConversionDoneCallback) {
     // Since this printing job was aborted, we do not need to report EMF buffer
     // back to mTarget.
     mConversionDoneCallback();
   }
 }
 
 mozilla::ipc::IPCResult
@@ -54,16 +58,22 @@ 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::EndConversion()
+{
+  // The printing job is finished correctly, mTarget is no longer needed.
+  mTarget = nullptr;
+}
+
 void
 PDFiumParent::OnChannelConnected(int32_t pid)
 {
   SetOtherProcessId(pid);
 }
 
 void
 PDFiumParent::DeallocPPDFiumParent()
--- a/widget/windows/PDFiumParent.h
+++ b/widget/windows/PDFiumParent.h
@@ -25,16 +25,17 @@ class PDFiumParent final : public PPDFiu
   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);
+  void EndConversion();
 
   FORWARD_SHMEM_ALLOCATOR_TO(PPDFiumParent)
 private:
   ~PDFiumParent() {}
 
   // PPDFiumParent functions.
   void ActorDestroy(ActorDestroyReason aWhy) override;