зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1557983. Significantly simplify and fix the 'beforeprint'/'afterprint' dispatching code.
This fixes two issue. First, the code shouldn't be dispatching these events every time it gets a new Print or PrintPreview call. It only needs to dispatch the events to the original document that we're going to clone from. When cloning from existing static clones any changes made by 'beforeprint' will be present in the existing static clone. Second, the code tries to delay the 'afterprint' event until after mozPrintCallback callbacks have been invoked, but those callbacks are invoked in the cloned document, whereas the events are sent to the original document! So there is no reason to do this. Differential Revision: https://phabricator.services.mozilla.com/D34280
This commit is contained in:
Родитель
222d260b21
Коммит
6e34e4dbdf
|
@ -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<nsIWebProgressListener> mCachedPrintWebProgressListner;
|
||||
|
||||
RefPtr<nsPrintJob> mPrintJob;
|
||||
UniquePtr<AutoPrintEventDispatcher> 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<nsCOMPtr<Document>>& 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<nsCOMPtr<Document>> targets;
|
||||
if (mTop) {
|
||||
CollectDocuments(*mTop, targets);
|
||||
}
|
||||
for (nsCOMPtr<Document>& doc : targets) {
|
||||
nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent,
|
||||
CanBubble::eNo, Cancelable::eNo,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<Document> mTop;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDocumentShownDispatcher : public Runnable {
|
||||
public:
|
||||
explicit nsDocumentShownDispatcher(nsCOMPtr<Document> 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<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.
|
||||
|
@ -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<Document> 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<AutoPrintEventDispatcher> autoBeforeAndAfterPrint;
|
||||
if (!mAutoBeforeAndAfterPrint) {
|
||||
autoBeforeAndAfterPrint = MakeUnique<AutoPrintEventDispatcher>(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.
|
||||
|
|
|
@ -168,6 +168,26 @@ static void DumpPrintObjectsTreeLayout(const UniquePtr<nsPrintObject>& aPO,
|
|||
# define DUMP_DOC_TREELAYOUT
|
||||
#endif
|
||||
|
||||
static CallState CollectDocuments(Document& aDoc,
|
||||
nsTArray<nsCOMPtr<Document>>& 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<nsCOMPtr<Document>> targets;
|
||||
CollectDocuments(aDoc, targets);
|
||||
for (nsCOMPtr<Document>& doc : targets) {
|
||||
nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent,
|
||||
CanBubble::eNo, Cancelable::eNo,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
class nsScriptSuppressor {
|
||||
public:
|
||||
explicit nsScriptSuppressor(nsPrintJob* aPrintJob)
|
||||
|
@ -664,6 +684,14 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
|
|||
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<nsPrintObject>();
|
||||
rv = printData->mPrintObject->InitAsRootObject(docShell, aSourceDoc,
|
||||
|
@ -678,6 +706,10 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
|
|||
|
||||
BuildNestedPrintObjects(printData->mPrintObject->mDocument,
|
||||
printData->mPrintObject, &printData->mPrintDocList);
|
||||
|
||||
if (!aSourceDoc->IsStaticDocument()) {
|
||||
DispatchEventToWindowTree(*aSourceDoc, u"afterprint"_ns);
|
||||
}
|
||||
}
|
||||
|
||||
// The nsAutoScriptBlocker above will now have been destroyed, which may
|
||||
|
|
Загрузка…
Ссылка в новой задаче