Bug 1313386, part 1 - Clean up the beforeprint/afterprint event dispatching code. r=dholbert

This commit is contained in:
Jonathan Watt
2016-11-01 21:29:30 +00:00
parent 7b84d67178
commit d5fd426cbb
2 changed files with 61 additions and 50 deletions

View File

@@ -148,7 +148,9 @@ static mozilla::LazyLogModule gPrintingLog("printing");
//----------------------------------------------------- //-----------------------------------------------------
class nsDocumentViewer; class nsDocumentViewer;
class nsPrintEventDispatcher; namespace mozilla {
class AutoPrintEventDispatcher;
}
// a small delegate class used to avoid circular references // a small delegate class used to avoid circular references
@@ -247,18 +249,6 @@ public:
// nsIDocumentViewerPrint Printing Methods // nsIDocumentViewerPrint Printing Methods
NS_DECL_NSIDOCUMENTVIEWERPRINT NS_DECL_NSIDOCUMENTVIEWERPRINT
static void DispatchBeforePrint(nsIDocument* aTop)
{
DispatchEventToWindowTree(aTop, NS_LITERAL_STRING("beforeprint"));
}
static void DispatchAfterPrint(nsIDocument* aTop)
{
DispatchEventToWindowTree(aTop, NS_LITERAL_STRING("afterprint"));
}
static void DispatchEventToWindowTree(nsIDocument* aTop,
const nsAString& aEvent);
protected: protected:
virtual ~nsDocumentViewer(); virtual ~nsDocumentViewer();
@@ -397,7 +387,7 @@ protected:
RefPtr<nsPrintEngine> mPrintEngine; RefPtr<nsPrintEngine> mPrintEngine;
float mOriginalPrintPreviewScale; float mOriginalPrintPreviewScale;
float mPrintPreviewZoom; float mPrintPreviewZoom;
nsAutoPtr<nsPrintEventDispatcher> mBeforeAndAfterPrint; nsAutoPtr<AutoPrintEventDispatcher> mAutoBeforeAndAfterPrint;
#endif // NS_PRINT_PREVIEW #endif // NS_PRINT_PREVIEW
#ifdef DEBUG #ifdef DEBUG
@@ -415,21 +405,54 @@ protected:
bool mHidden; bool mHidden;
}; };
class nsPrintEventDispatcher 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: public:
explicit nsPrintEventDispatcher(nsIDocument* aTop) : mTop(aTop) explicit AutoPrintEventDispatcher(nsIDocument* aTop) : mTop(aTop)
{ {
nsDocumentViewer::DispatchBeforePrint(mTop); DispatchEventToWindowTree(mTop, NS_LITERAL_STRING("beforeprint"));
} }
~nsPrintEventDispatcher() ~AutoPrintEventDispatcher()
{ {
nsDocumentViewer::DispatchAfterPrint(mTop); DispatchEventToWindowTree(mTop, NS_LITERAL_STRING("afterprint"));
}
private:
static void DispatchEventToWindowTree(nsIDocument* aDoc,
const nsAString& aEvent)
{
nsCOMArray<nsIDocument> targets;
CollectDocuments(aDoc, &targets);
for (int32_t i = 0; i < targets.Count(); ++i) {
nsIDocument* d = targets[i];
nsContentUtils::DispatchTrustedEvent(d, d->GetWindow(),
aEvent, false, false, nullptr);
}
}
static bool CollectDocuments(nsIDocument* aDocument, void* aData)
{
if (aDocument) {
static_cast<nsCOMArray<nsIDocument>*>(aData)->AppendObject(aDocument);
aDocument->EnumerateSubDocuments(CollectDocuments, aData);
}
return true;
} }
nsCOMPtr<nsIDocument> mTop; nsCOMPtr<nsIDocument> mTop;
}; };
}
class nsDocumentShownDispatcher : public Runnable class nsDocumentShownDispatcher : public Runnable
{ {
public: public:
@@ -1553,7 +1576,8 @@ nsDocumentViewer::Destroy()
return NS_OK; return NS_OK;
} }
} }
mBeforeAndAfterPrint = nullptr; // Dispatch the 'afterprint' event now, if pending:
mAutoBeforeAndAfterPrint = nullptr;
#endif #endif
// Don't let the document get unloaded while we are printing. // Don't let the document get unloaded while we are printing.
@@ -3784,8 +3808,9 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
return rv; return rv;
} }
nsAutoPtr<nsPrintEventDispatcher> beforeAndAfterPrint( // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
new nsPrintEventDispatcher(mDocument)); nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint(
new AutoPrintEventDispatcher(mDocument));
NS_ENSURE_STATE(!GetIsPrinting()); NS_ENSURE_STATE(!GetIsPrinting());
// If we are hosting a full-page plugin, tell it to print // If we are hosting a full-page plugin, tell it to print
// first. It shows its own native print UI. // first. It shows its own native print UI.
@@ -3814,7 +3839,9 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
} }
} }
if (mPrintEngine->HasPrintCallbackCanvas()) { if (mPrintEngine->HasPrintCallbackCanvas()) {
mBeforeAndAfterPrint = beforeAndAfterPrint; // Postpone the 'afterprint' event until after the mozPrintCallback
// callbacks have been called:
mAutoBeforeAndAfterPrint = autoBeforeAndAfterPrint;
} }
dom::Element* root = mDocument->GetRootElement(); dom::Element* root = mDocument->GetRootElement();
if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) { if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) {
@@ -3863,8 +3890,9 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
nsCOMPtr<nsIDocument> doc = window->GetDoc(); nsCOMPtr<nsIDocument> doc = window->GetDoc();
NS_ENSURE_STATE(doc); NS_ENSURE_STATE(doc);
nsAutoPtr<nsPrintEventDispatcher> beforeAndAfterPrint( // Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
new nsPrintEventDispatcher(doc)); nsAutoPtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint(
new AutoPrintEventDispatcher(doc));
NS_ENSURE_STATE(!GetIsPrinting()); NS_ENSURE_STATE(!GetIsPrinting());
// beforeprint event may have caused ContentViewer to be shutdown. // beforeprint event may have caused ContentViewer to be shutdown.
NS_ENSURE_STATE(mContainer); NS_ENSURE_STATE(mContainer);
@@ -3889,7 +3917,9 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
} }
} }
if (mPrintEngine->HasPrintCallbackCanvas()) { if (mPrintEngine->HasPrintCallbackCanvas()) {
mBeforeAndAfterPrint = beforeAndAfterPrint; // Postpone the 'afterprint' event until after the mozPrintCallback
// callbacks have been called:
mAutoBeforeAndAfterPrint = autoBeforeAndAfterPrint;
} }
dom::Element* root = doc->GetRootElement(); dom::Element* root = doc->GetRootElement();
if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) { if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) {
@@ -4234,28 +4264,6 @@ nsDocumentViewer::ShouldAttachToTopLevel()
return false; return false;
} }
bool CollectDocuments(nsIDocument* aDocument, void* aData)
{
if (aDocument) {
static_cast<nsCOMArray<nsIDocument>*>(aData)->AppendObject(aDocument);
aDocument->EnumerateSubDocuments(CollectDocuments, aData);
}
return true;
}
void
nsDocumentViewer::DispatchEventToWindowTree(nsIDocument* aDoc,
const nsAString& aEvent)
{
nsCOMArray<nsIDocument> targets;
CollectDocuments(aDoc, &targets);
for (int32_t i = 0; i < targets.Count(); ++i) {
nsIDocument* d = targets[i];
nsContentUtils::DispatchTrustedEvent(d, d->GetWindow(),
aEvent, false, false, nullptr);
}
}
//------------------------------------------------------------ //------------------------------------------------------------
// XXX this always returns false for subdocuments // XXX this always returns false for subdocuments
bool bool
@@ -4285,7 +4293,8 @@ nsDocumentViewer::SetIsPrinting(bool aIsPrinting)
} }
if (!aIsPrinting) { if (!aIsPrinting) {
mBeforeAndAfterPrint = nullptr; // Dispatch the 'afterprint' event now, if pending:
mAutoBeforeAndAfterPrint = nullptr;
} }
#endif #endif
} }
@@ -4318,7 +4327,8 @@ nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview)
SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true); SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true);
} }
if (!aIsPrintPreview) { if (!aIsPrintPreview) {
mBeforeAndAfterPrint = nullptr; // Dispatch the 'afterprint' event now, if pending:
mAutoBeforeAndAfterPrint = nullptr;
} }
#endif #endif
if (!aIsPrintPreview) { if (!aIsPrintPreview) {

View File

@@ -2614,6 +2614,7 @@ DocHasPrintCallbackCanvas(nsIDocument* aDoc)
/** /**
* Checks to see if the document this print engine is associated with has any * Checks to see if the document this print engine is associated with has any
* canvases that have a mozPrintCallback. * canvases that have a mozPrintCallback.
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement#Properties
*/ */
bool bool
nsPrintEngine::HasPrintCallbackCanvas() nsPrintEngine::HasPrintCallbackCanvas()