Bug 430050, cancel frameloader initialization when docshell starts to load a page, r=sicking, sr=jst, a=dsicore

This commit is contained in:
Olli.Pettay@helsinki.fi 2008-04-24 03:33:22 -07:00
parent 84a91c083e
commit 25efede61e
7 changed files with 93 additions and 11 deletions

View File

@ -56,7 +56,7 @@
class nsIContent; class nsIContent;
class nsPresContext; class nsPresContext;
class nsIPresShell; class nsIPresShell;
class nsIDocShell;
class nsIStreamListener; class nsIStreamListener;
class nsIStreamObserver; class nsIStreamObserver;
class nsStyleSet; class nsStyleSet;
@ -97,8 +97,8 @@ class nsFrameLoader;
// IID for the nsIDocument interface // IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \ #define NS_IDOCUMENT_IID \
{ 0x680f5dac, 0x8863, 0x4c80, \ { 0xdd40333d, 0x913c, 0x4909, \
{ 0xbb, 0xe4, 0x21, 0x35, 0xbd, 0x8f, 0x83, 0x9a } } { 0xb9, 0xe8, 0xf5, 0x45, 0x56, 0x5c, 0xe5, 0x4e } }
// Flag for AddStyleSheet(). // Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0) #define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -964,6 +964,8 @@ public:
// In case of failure, the caller must handle the error, for example by // In case of failure, the caller must handle the error, for example by
// finalizing frame loader asynchronously. // finalizing frame loader asynchronously.
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0; virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0;
virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) = 0;
protected: protected:
~nsIDocument() ~nsIDocument()
{ {

View File

@ -3892,16 +3892,17 @@ nsDocument::InitializeFinalizeFrameLoaders()
{ {
NS_ASSERTION(mUpdateNestLevel == 0 && !mDelayFrameLoaderInitialization, NS_ASSERTION(mUpdateNestLevel == 0 && !mDelayFrameLoaderInitialization,
"Wrong time to call InitializeFinalizeFrameLoaders!"); "Wrong time to call InitializeFinalizeFrameLoaders!");
PRUint32 length = mInitializableFrameLoaders.Length(); // Don't use a temporary array for mInitializableFrameLoaders, because
if (length > 0) { // loading a frame may cause some other frameloader to be removed from the
nsTArray<nsRefPtr<nsFrameLoader> > loaders; // array. But be careful to keep the loader alive when starting the load!
mInitializableFrameLoaders.SwapElements(loaders); while (mInitializableFrameLoaders.Length()) {
for (PRUint32 i = 0; i < length; ++i) { nsRefPtr<nsFrameLoader> loader = mInitializableFrameLoaders[0];
loaders[i]->ReallyStartLoading(); mInitializableFrameLoaders.RemoveElementAt(0);
} NS_ASSERTION(loader, "null frameloader in the array?");
loader->ReallyStartLoading();
} }
length = mFinalizableFrameLoaders.Length(); PRUint32 length = mFinalizableFrameLoaders.Length();
if (length > 0) { if (length > 0) {
nsTArray<nsRefPtr<nsFrameLoader> > loaders; nsTArray<nsRefPtr<nsFrameLoader> > loaders;
mFinalizableFrameLoaders.SwapElements(loaders); mFinalizableFrameLoaders.SwapElements(loaders);
@ -3911,6 +3912,18 @@ nsDocument::InitializeFinalizeFrameLoaders()
} }
} }
void
nsDocument::TryCancelFrameLoaderInitialization(nsIDocShell* aShell)
{
PRUint32 length = mInitializableFrameLoaders.Length();
for (PRUint32 i = 0; i < length; ++i) {
if (mInitializableFrameLoaders[i]->GetExistingDocShell() == aShell) {
mInitializableFrameLoaders.RemoveElementAt(i);
return;
}
}
}
struct DirTable { struct DirTable {
const char* mName; const char* mName;
PRUint8 mValue; PRUint8 mValue;

View File

@ -651,6 +651,7 @@ public:
virtual NS_HIDDEN_(nsresult) InitializeFrameLoader(nsFrameLoader* aLoader); virtual NS_HIDDEN_(nsresult) InitializeFrameLoader(nsFrameLoader* aLoader);
virtual NS_HIDDEN_(nsresult) FinalizeFrameLoader(nsFrameLoader* aLoader); virtual NS_HIDDEN_(nsresult) FinalizeFrameLoader(nsFrameLoader* aLoader);
virtual NS_HIDDEN_(void) TryCancelFrameLoaderInitialization(nsIDocShell* aShell);
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDocument, nsIDocument) NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDocument, nsIDocument)

View File

@ -74,6 +74,7 @@ public:
NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI);
nsresult ReallyStartLoading(); nsresult ReallyStartLoading();
void Finalize(); void Finalize();
nsIDocShell* GetExistingDocShell() { return mDocShell; }
private: private:
NS_HIDDEN_(nsresult) EnsureDocShell(); NS_HIDDEN_(nsresult) EnsureDocShell();

View File

@ -49,6 +49,7 @@ _TEST_FILES = \
_CHROME_FILES = \ _CHROME_FILES = \
test_bug421622.xul \ test_bug421622.xul \
test_bug430050.xul \
$(NULL) $(NULL)
libs:: $(_TEST_FILES) libs:: $(_TEST_FILES)

View File

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=430050
-->
<window title="Mozilla Bug 430050"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=430050"
target="_blank">Mozilla Bug 430050</a>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 430050 **/
function endTest() {
ok(document.getElementById('b').contentDocument.documentElement.textContent ==
"succeeded", "Wrong URL loaded!");
SimpleTest.finish();
}
function startTest() {
document.documentElement.addEventListener('DOMAttrModified',
function(evt) {
if (evt.target == evt.currentTarget) {
document.getElementById('b').setAttribute("src",
"data:text/plain,failed");
document.getElementById('b').loadURI('data:text/plain,succeeded',
null,
'UTF-8');
}
}, true);
document.documentElement.setAttribute("foo", "bar");
setTimeout(endTest, 100);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(startTest);
]]></script>
<browser flex="1" id="b"/>
</window>

View File

@ -6884,6 +6884,18 @@ nsDocShell::InternalLoad(nsIURI * aURI,
return rv; return rv;
} }
// If this docshell is owned by a frameloader, make sure to cancel
// possible frameloader initialization before loading a new page.
nsCOMPtr<nsIDocShellTreeItem> parent;
GetParent(getter_AddRefs(parent));
if (parent) {
nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(parent);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (doc) {
doc->TryCancelFrameLoaderInitialization(this);
}
}
if (mFiredUnloadEvent) { if (mFiredUnloadEvent) {
if (IsOKToLoadURI(aURI)) { if (IsOKToLoadURI(aURI)) {
NS_PRECONDITION(!aWindowTarget || !*aWindowTarget, NS_PRECONDITION(!aWindowTarget || !*aWindowTarget,