Bug 1308461 - Prevent dispatch of nested or multiple pairs of beforeprint/afterprint events. r=jwatt,dholbert a=jcristau
authorDalmir da Silva <dalmirsilva@hp.com>
Sat, 07 Jan 2017 00:13:56 +0000
changeset 353474 adba84d693a69f2ee1c8dd23493128d6879b2288
parent 353473 1d0d4ed301e0c010b77bfd8f088dfd2c3765dfa8
child 353475 6eca9e254f67364ac11753757f092724e3798534
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt, dholbert, jcristau
bugs1308461
milestone52.0a2
Bug 1308461 - Prevent dispatch of nested or multiple pairs of beforeprint/afterprint events. r=jwatt,dholbert a=jcristau
layout/base/nsDocumentViewer.cpp
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3803,16 +3803,18 @@ nsDocumentViewer::Print(nsIPrintSettings
     if (mPrintEngine) {
       mPrintEngine->FirePrintingErrorEvent(rv);
     }
 
     return rv;
   }
 
   // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
+  MOZ_ASSERT(!mAutoBeforeAndAfterPrint,
+             "We don't want to dispatch nested beforeprint/afterprint");
   nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint(
     new AutoPrintEventDispatcher(mDocument));
   NS_ENSURE_STATE(!GetIsPrinting());
   // If we are hosting a full-page plugin, tell it to print
   // first. It shows its own native print UI.
   nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(mDocument));
   if (pDoc)
     return pDoc->Print();
@@ -3885,18 +3887,27 @@ nsDocumentViewer::PrintPreview(nsIPrintS
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(aChildDOMWin);
   MOZ_ASSERT(window);
   nsCOMPtr<nsIDocument> doc = window->GetDoc();
   NS_ENSURE_STATE(doc);
 
   // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
-  nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint(
-    new AutoPrintEventDispatcher(doc));
+  // XXX Currently[1] when the user switches between portrait and landscape
+  // mode in print preview, we re-enter this function before
+  // mAutoBeforeAndAfterPrint (if set) is cleared to dispatch the 'afterprint'
+  // event.  To avoid sending multiple 'beforeprint'/'afterprint' events we
+  // must avoid creating a new AutoPrintEventDispatcher object here if we
+  // already have one saved in mAutoBeforeAndAfterPrint.
+  // [1] Until PDF.js is removed (though, maybe after that as well).
+  nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint;
+  if (!mAutoBeforeAndAfterPrint) {
+    autoBeforeAndAfterPrint = new AutoPrintEventDispatcher(doc);
+  }
   NS_ENSURE_STATE(!GetIsPrinting());
   // beforeprint event may have caused ContentViewer to be shutdown.
   NS_ENSURE_STATE(mContainer);
   NS_ENSURE_STATE(mDeviceContext);
   if (!mPrintEngine) {
     mPrintEngine = new nsPrintEngine();
 
     rv = mPrintEngine->Initialize(this, mContainer, doc,
@@ -3910,17 +3921,18 @@ nsDocumentViewer::PrintPreview(nsIPrintS
 #endif
                                   );
     if (NS_FAILED(rv)) {
       mPrintEngine->Destroy();
       mPrintEngine = nullptr;
       return rv;
     }
   }
-  if (mPrintEngine->HasPrintCallbackCanvas()) {
+  if (autoBeforeAndAfterPrint &&
+      mPrintEngine->HasPrintCallbackCanvas()) {
     // Postpone the 'afterprint' event until after the mozPrintCallback
     // callbacks have been called:
     mAutoBeforeAndAfterPrint = autoBeforeAndAfterPrint;
   }
   dom::Element* root = doc->GetRootElement();
   if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) {
     PR_PL(("PrintPreview: found mozdisallowselectionprint"));
     mPrintEngine->SetDisallowSelectionPrint(true);