From 3ad73c2447616b29af150605df326f0bfa9ccfb8 Mon Sep 17 00:00:00 2001 From: "alqahira%ardisson.org" Date: Sat, 24 Jul 2010 21:39:46 +0000 Subject: [PATCH] Bug 535926, async onload blocker. Patch by Olli Pettay , r=bz, sr=sicking, a1.9.0.next=dveditz git-svn-id: svn://10.0.0.236/trunk@260882 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsDocument.cpp | 28 +++++++++++++++++++++++-- mozilla/content/base/src/nsDocument.h | 6 ++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 96fe9e0aa83..05e33152623 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -5717,12 +5717,31 @@ nsDocument::GetLayoutHistoryState() const return state; } +void +nsDocument::AsyncBlockOnload() +{ + while (mAsyncOnloadBlockCount) { + --mAsyncOnloadBlockCount; + BlockOnload(); + } +} + void nsDocument::BlockOnload() { // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup // -- it's not ours. if (mOnloadBlockCount == 0 && mScriptGlobalObject) { + if (!nsContentUtils::IsSafeToRunScript()) { + // Because AddRequest may lead to OnStateChange calls in chrome, + // block onload only when there are no script blockers. + ++mAsyncOnloadBlockCount; + if (mAsyncOnloadBlockCount == 1) { + nsContentUtils::AddScriptRunner( + NS_NEW_RUNNABLE_METHOD(nsDocument, this, AsyncBlockOnload)); + } + return; + } nsCOMPtr loadGroup = GetDocumentLoadGroup(); if (loadGroup) { loadGroup->AddRequest(mOnloadBlocker, nsnull); @@ -5734,7 +5753,7 @@ nsDocument::BlockOnload() void nsDocument::UnblockOnload(PRBool aFireSync) { - if (mOnloadBlockCount == 0) { + if (mOnloadBlockCount == 0 && mAsyncOnloadBlockCount == 0) { NS_NOTREACHED("More UnblockOnload() calls than BlockOnload() calls; dropping call"); return; } @@ -5744,7 +5763,7 @@ nsDocument::UnblockOnload(PRBool aFireSync) // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup // -- it's not ours. if (mOnloadBlockCount == 0 && mScriptGlobalObject) { - if (aFireSync) { + if (aFireSync && mAsyncOnloadBlockCount == 0) { // Increment mOnloadBlockCount, since DoUnblockOnload will decrement it ++mOnloadBlockCount; DoUnblockOnload(); @@ -5793,6 +5812,11 @@ nsDocument::DoUnblockOnload() return; } + if (mAsyncOnloadBlockCount != 0) { + // We need to wait until the async onload block has been handled. + PostUnblockOnloadEvent(); + } + // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup // -- it's not ours. if (mScriptGlobalObject) { diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index b772bd7f3f2..57908d435ea 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -676,6 +676,9 @@ public: virtual nsISupports* GetCurrentContentSink(); + // Only BlockOnload should call this! + void AsyncBlockOnload(); + protected: /** @@ -860,7 +863,10 @@ private: // 2) We haven't had Destroy() called on us yet. nsCOMPtr mLayoutHistoryState; + // Currently active onload blockers PRUint32 mOnloadBlockCount; + // Onload blockers which haven't been activated yet + PRUint32 mAsyncOnloadBlockCount; nsCOMPtr mOnloadBlocker; // A map from unvisited URI hashes to content elements