зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
888a54c0bd
Коммит
25276ccc75
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче