Block scripts in subframes if the parent has script blocked in the scriptloader. Fixes bug 383331, r+sr+a=sicking

This commit is contained in:
bzbarsky@mit.edu 2007-09-28 08:15:07 -07:00
Родитель 888a54c0bd
Коммит 25276ccc75
2 изменённых файлов: 54 добавлений и 2 удалений

Просмотреть файл

@ -171,6 +171,12 @@ nsScriptLoader::~nsScriptLoader()
for (PRInt32 i = 0; i < mPendingRequests.Count(); i++) {
mPendingRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
}
// Unblock the kids, in case any of them moved to a different document
// subtree in the meantime and therefore aren't actually going away.
for (PRUint32 j = 0; j < mPendingChildLoaders.Length(); ++j) {
mPendingChildLoaders[j]->RemoveExecuteBlocker();
}
}
NS_IMPL_ISUPPORTS1(nsScriptLoader, nsIStreamLoaderObserver)
@ -636,7 +642,7 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
void
nsScriptLoader::ProcessPendingRequestsAsync()
{
if (mPendingRequests.Count()) {
if (mPendingRequests.Count() || !mPendingChildLoaders.IsEmpty()) {
nsCOMPtr<nsIRunnable> ev = new nsRunnableMethod<nsScriptLoader>(this,
&nsScriptLoader::ProcessPendingRequests);
@ -653,6 +659,33 @@ nsScriptLoader::ProcessPendingRequests()
mPendingRequests.RemoveObjectAt(0);
ProcessRequest(request);
}
while (ReadyToExecuteScripts() && !mPendingChildLoaders.IsEmpty()) {
nsRefPtr<nsScriptLoader> child = mPendingChildLoaders[0];
mPendingChildLoaders.RemoveElementAt(0);
child->RemoveExecuteBlocker();
}
}
PRBool
nsScriptLoader::ReadyToExecuteScripts()
{
// Make sure the SelfReadyToExecuteScripts check is first, so that
// we don't block twice on an ancestor.
if (!SelfReadyToExecuteScripts()) {
return PR_FALSE;
}
for (nsIDocument* doc = mDocument; doc; doc = doc->GetParentDocument()) {
nsScriptLoader* ancestor = doc->ScriptLoader();
if (!ancestor->SelfReadyToExecuteScripts() &&
ancestor->AddPendingChildLoader(this)) {
AddExecuteBlocker();
return PR_FALSE;
}
}
return PR_TRUE;
}

Просмотреть файл

@ -47,6 +47,8 @@
#include "nsIScriptElement.h"
#include "nsIURI.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
#include "nsIDocument.h"
#include "nsIStreamLoader.h"
@ -202,11 +204,26 @@ protected:
*/
virtual void ProcessPendingRequestsAsync();
PRBool ReadyToExecuteScripts()
/**
* If true, the loader is ready to execute scripts, and so are all its
* ancestors. If the loader itself is ready but some ancestor is not, this
* function will add an execute blocker and ask the ancestor to remove it
* once it becomes ready.
*/
PRBool ReadyToExecuteScripts();
/**
* Return whether just this loader is ready to execute scripts.
*/
PRBool SelfReadyToExecuteScripts()
{
return mEnabled && !mBlockerCount;
}
PRBool AddPendingChildLoader(nsScriptLoader* aChild) {
return mPendingChildLoaders.AppendElement(aChild) != nsnull;
}
nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
void FireScriptAvailable(nsresult aResult,
nsScriptLoadRequest* aRequest);
@ -225,6 +242,8 @@ protected:
nsCOMArray<nsIScriptLoaderObserver> mObservers;
nsCOMArray<nsScriptLoadRequest> mPendingRequests;
nsCOMPtr<nsIScriptElement> mCurrentScript;
// XXXbz do we want to cycle-collect these or something? Not sure.
nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
PRUint32 mBlockerCount;
PRPackedBool mEnabled;
PRPackedBool mHadPendingScripts;