diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 59b8bcfc4386..46cc1399a6e6 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -149,9 +149,6 @@ static mozilla::LazyLogModule gPrintingLog("printing"); //----------------------------------------------------- class nsDocumentViewer; -namespace mozilla { -class AutoPrintEventDispatcher; -} // a small delegate class used to avoid circular references @@ -467,7 +464,6 @@ class nsDocumentViewer final : public nsIContentViewer, nsCOMPtr mCachedPrintWebProgressListner; RefPtr mPrintJob; - UniquePtr mAutoBeforeAndAfterPrint; # endif // NS_PRINT_PREVIEW #endif // NS_PRINTING @@ -481,50 +477,6 @@ class nsDocumentViewer final : public nsIContentViewer, bool mHidden; }; -namespace mozilla { - -/** - * A RAII class for automatic dispatch of the 'beforeprint' and 'afterprint' - * events ('beforeprint' on construction, 'afterprint' on destruction). - * - * https://developer.mozilla.org/en-US/docs/Web/Events/beforeprint - * https://developer.mozilla.org/en-US/docs/Web/Events/afterprint - */ -class AutoPrintEventDispatcher { - public: - explicit AutoPrintEventDispatcher(Document* aTop) : mTop(aTop) { - DispatchEventToWindowTree(u"beforeprint"_ns); - } - ~AutoPrintEventDispatcher() { DispatchEventToWindowTree(u"afterprint"_ns); } - - private: - static CallState CollectDocuments(Document& aDoc, - nsTArray>& aDocs) { - aDocs.AppendElement(&aDoc); - auto recurse = [&aDocs](Document& aSubDoc) { - return CollectDocuments(aSubDoc, aDocs); - }; - aDoc.EnumerateSubDocuments(recurse); - return CallState::Continue; - } - - void DispatchEventToWindowTree(const nsAString& aEvent) { - nsTArray> targets; - if (mTop) { - CollectDocuments(*mTop, targets); - } - for (nsCOMPtr& doc : targets) { - nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent, - CanBubble::eNo, Cancelable::eNo, - nullptr); - } - } - - nsCOMPtr mTop; -}; - -} // namespace mozilla - class nsDocumentShownDispatcher : public Runnable { public: explicit nsDocumentShownDispatcher(nsCOMPtr aDocument) @@ -1660,8 +1612,6 @@ nsDocumentViewer::Destroy() { return NS_OK; } } - // Dispatch the 'afterprint' event now, if pending: - mAutoBeforeAndAfterPrint = nullptr; #endif // We want to make sure to disconnect mBFCachePreventionObserver before we @@ -3205,11 +3155,6 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings, return rv; } - // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched: - MOZ_ASSERT(!mAutoBeforeAndAfterPrint, - "We don't want to dispatch nested beforeprint/afterprint"); - auto autoBeforeAndAfterPrint = - MakeUnique(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. @@ -3233,11 +3178,6 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings, } mPrintJob = printJob; } - if (printJob->HasPrintCallbackCanvas()) { - // Postpone the 'afterprint' event until after the mozPrintCallback - // callbacks have been called: - mAutoBeforeAndAfterPrint = std::move(autoBeforeAndAfterPrint); - } rv = printJob->Print(mDocument, aPrintSettings, aWebProgressListener); if (NS_FAILED(rv)) { OnDonePrinting(); @@ -3273,18 +3213,6 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings, nsCOMPtr doc = window->GetDoc(); NS_ENSURE_STATE(doc); - // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched: - // 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). - UniquePtr autoBeforeAndAfterPrint; - if (!mAutoBeforeAndAfterPrint) { - autoBeforeAndAfterPrint = MakeUnique(doc); - } NS_ENSURE_STATE(!GetIsPrinting()); // beforeprint event may have caused ContentViewer to be shutdown. NS_ENSURE_STATE(mContainer); @@ -3308,11 +3236,6 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings, Telemetry::ScalarAdd(Telemetry::ScalarID::PRINTING_PREVIEW_OPENED, 1); } - if (autoBeforeAndAfterPrint && printJob->HasPrintCallbackCanvas()) { - // Postpone the 'afterprint' event until after the mozPrintCallback - // callbacks have been called: - mAutoBeforeAndAfterPrint = std::move(autoBeforeAndAfterPrint); - } rv = printJob->PrintPreview(doc, aPrintSettings, aWebProgressListener); if (NS_FAILED(rv)) { OnDonePrinting(); @@ -3647,11 +3570,6 @@ void nsDocumentViewer::SetIsPrinting(bool aIsPrinting) { } else { NS_WARNING("Did you close a window before printing?"); } - - if (!aIsPrinting) { - // Dispatch the 'afterprint' event now, if pending: - mAutoBeforeAndAfterPrint = nullptr; - } #endif } @@ -3678,10 +3596,6 @@ void nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview) { if (docShell || !aIsPrintPreview) { SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true); } - if (!aIsPrintPreview) { - // Dispatch the 'afterprint' event now, if pending: - mAutoBeforeAndAfterPrint = nullptr; - } #endif // Protect against pres shell destruction running scripts. diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp index b5cae9d83fbe..6563a7be6215 100644 --- a/layout/printing/nsPrintJob.cpp +++ b/layout/printing/nsPrintJob.cpp @@ -168,6 +168,26 @@ static void DumpPrintObjectsTreeLayout(const UniquePtr& aPO, # define DUMP_DOC_TREELAYOUT #endif +static CallState CollectDocuments(Document& aDoc, + nsTArray>& aDocs) { + aDocs.AppendElement(&aDoc); + auto recurse = [&aDocs](Document& aSubDoc) { + return CollectDocuments(aSubDoc, aDocs); + }; + aDoc.EnumerateSubDocuments(recurse); + return CallState::Continue; +} + +static void DispatchEventToWindowTree(Document& aDoc, const nsAString& aEvent) { + nsTArray> targets; + CollectDocuments(aDoc, targets); + for (nsCOMPtr& doc : targets) { + nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent, + CanBubble::eNo, Cancelable::eNo, + nullptr); + } +} + class nsScriptSuppressor { public: explicit nsScriptSuppressor(nsPrintJob* aPrintJob) @@ -663,6 +683,14 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview, nsCOMPtr docShell(do_QueryReferent(mDocShell, &rv)); NS_ENSURE_SUCCESS(rv, rv); + if (!aSourceDoc->IsStaticDocument()) { + // This is the original document. We must send 'beforeprint' and + // 'afterprint' events to give the document the chance to make changes + // for print output. (Obviously if `aSourceDoc` is a clone, it already + // has these changes.) + DispatchEventToWindowTree(*aSourceDoc, u"beforeprint"_ns); + } + { nsAutoScriptBlocker scriptBlocker; printData->mPrintObject = MakeUnique(); @@ -680,6 +708,10 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview, printData->mPrintObject, &printData->mPrintDocList); } + if (!aSourceDoc->IsStaticDocument()) { + DispatchEventToWindowTree(*aSourceDoc, u"afterprint"_ns); + } + // The nsAutoScriptBlocker above will now have been destroyed, which may // cause our print/print-preview operation to finish. In this case, we // should immediately return an error code so that the root caller knows