From 69b22d9e2871ce4794db64d7b9763828388e5622 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 12 Mar 2012 12:03:38 -0400 Subject: [PATCH] Bug 732564 - Add a before-first-paint event that fires before the first paint of the new document. r=Cwiiis, bz --- layout/base/nsDocumentViewer.cpp | 35 ++++++++++++++++++++++-- mobile/android/chrome/content/browser.js | 6 ++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 2a60c31cbcf..5c2e0a8ea0f 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -506,6 +506,18 @@ public: nsCOMPtr mTop; }; +class nsBeforeFirstPaintDispatcher : public nsRunnable +{ +public: + nsBeforeFirstPaintDispatcher(nsIDocument* aDocument) + : mDocument(aDocument) {} + + NS_IMETHOD Run(); + +private: + nsCOMPtr mDocument; +}; + class nsDocumentShownDispatcher : public nsRunnable { public: @@ -2047,8 +2059,13 @@ DocumentViewerImpl::Show(void) } } - // Notify observers that a new page has been shown. (But not right now; - // running JS at this time is not safe.) + // Notify observers that a new page is about to be drawn. Execute this + // as soon as it is safe to run JS, which is guaranteed to be before we + // go back to the event loop and actually draw the page. + nsContentUtils::AddScriptRunner(new nsBeforeFirstPaintDispatcher(mDocument)); + + // Notify observers that a new page has been shown. This will get run + // from the event loop after we actually draw the page. NS_DispatchToMainThread(new nsDocumentShownDispatcher(mDocument)); return NS_OK; @@ -4370,9 +4387,21 @@ DocumentViewerImpl::SetPrintPreviewPresentation(nsIViewManager* aViewManager, mPresShell = aPresShell; } -// Fires the "document-shown" event so that interested parties (right now, the +// Fires the "before-first-paint" event so that interested parties (right now, the // mobile browser) are aware of it. NS_IMETHODIMP +nsBeforeFirstPaintDispatcher::Run() +{ + nsCOMPtr observerService = + mozilla::services::GetObserverService(); + if (observerService) { + observerService->NotifyObservers(mDocument, "before-first-paint", NULL); + } + return NS_OK; +} + +// Fires the "document-shown" event so that interested parties are aware of it. +NS_IMETHODIMP nsDocumentShownDispatcher::Run() { nsCOMPtr observerService = diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 152285f1f3b..3474f7c977c 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1517,7 +1517,7 @@ Tab.prototype = { this.browser.addEventListener("pagehide", this, true); this.browser.addEventListener("pageshow", this, true); - Services.obs.addObserver(this, "document-shown", false); + Services.obs.addObserver(this, "before-first-paint", false); if (!aParams.delayLoad) { let flags = "flags" in aParams ? aParams.flags : Ci.nsIWebNavigation.LOAD_FLAGS_NONE; @@ -1563,7 +1563,7 @@ Tab.prototype = { this.browser.removeEventListener("pagehide", this, true); this.browser.removeEventListener("pageshow", this, true); - Services.obs.removeObserver(this, "document-shown"); + Services.obs.removeObserver(this, "before-first-paint"); // Make sure the previously selected panel remains selected. The selected panel of a deck is // not stable when panels are removed. @@ -2238,7 +2238,7 @@ Tab.prototype = { observe: function(aSubject, aTopic, aData) { switch (aTopic) { - case "document-shown": + case "before-first-paint": // Is it on the top level? let contentDocument = aSubject; if (contentDocument == this.browser.contentDocument) {