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 f08441cfbe
commit 2df44b5dfe
7 changed files with 93 additions and 11 deletions

View File

@ -56,7 +56,7 @@
class nsIContent;
class nsPresContext;
class nsIPresShell;
class nsIDocShell;
class nsIStreamListener;
class nsIStreamObserver;
class nsStyleSet;
@ -97,8 +97,8 @@ class nsFrameLoader;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0x680f5dac, 0x8863, 0x4c80, \
{ 0xbb, 0xe4, 0x21, 0x35, 0xbd, 0x8f, 0x83, 0x9a } }
{ 0xdd40333d, 0x913c, 0x4909, \
{ 0xb9, 0xe8, 0xf5, 0x45, 0x56, 0x5c, 0xe5, 0x4e } }
// Flag for AddStyleSheet().
#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
// finalizing frame loader asynchronously.
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0;
virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) = 0;
protected:
~nsIDocument()
{

View File

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

View File

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

View File

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

View File

@ -49,6 +49,7 @@ _TEST_FILES = \
_CHROME_FILES = \
test_bug421622.xul \
test_bug430050.xul \
$(NULL)
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;
}
// 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 (IsOKToLoadURI(aURI)) {
NS_PRECONDITION(!aWindowTarget || !*aWindowTarget,