Bug 426646, Using location.replace breaks iframe history, r=bz,sr=jst,a=dsicore

This commit is contained in:
Olli.Pettay@helsinki.fi 2008-04-29 00:18:55 -07:00
parent f09f23be86
commit 8c5cd9f684
8 changed files with 157 additions and 5 deletions

View File

@ -97,8 +97,8 @@ class nsFrameLoader;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0xdd40333d, 0x913c, 0x4909, \
{ 0xb9, 0xe8, 0xf5, 0x45, 0x56, 0x5c, 0xe5, 0x4e } }
{ 0xc81acf0b, 0x2539, 0x47ab, \
{ 0xa6, 0x04, 0x64, 0x04, 0x07, 0x63, 0xc8, 0x3d } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -964,8 +964,10 @@ public:
// In case of failure, the caller must handle the error, for example by
// finalizing frame loader asynchronously.
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0;
// Removes the frame loader of aShell from the initialization list.
virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) = 0;
// Returns true if the frame loader of aShell is in the finalization list.
virtual PRBool FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell) = 0;
protected:
~nsIDocument()
{

View File

@ -3924,6 +3924,20 @@ nsDocument::TryCancelFrameLoaderInitialization(nsIDocShell* aShell)
}
}
PRBool
nsDocument::FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell)
{
if (aShell) {
PRUint32 length = mFinalizableFrameLoaders.Length();
for (PRUint32 i = 0; i < length; ++i) {
if (mFinalizableFrameLoaders[i]->GetExistingDocShell() == aShell) {
return PR_TRUE;
}
}
}
return PR_FALSE;
}
struct DirTable {
const char* mName;
PRUint8 mValue;

View File

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

View File

@ -163,6 +163,9 @@ _TEST_FILES = test_bug5141.html \
test_bug425013.html \
bug426308-redirect.sjs \
test_bug426308.html \
test_bug426646.html \
file_bug426646-1.html \
file_bug426646-2.html \
test_bug429157.html \
test_XHR.html \
file_XHR_pass1.xml \

View File

@ -0,0 +1,32 @@
<html><head>
<title>Bug 426646, Using location.replace breaks iframe history</title>
<script type="text/javascript">
var url1 = "data:text/html;charset=utf-8,1st%20page";
function doe() {
document.body.innerHTML = "<iframe src='about:blank'></iframe>";
document.body.innerHTML += "<iframe src='about:blank'></iframe>";
window.frames[0].frameElement.onload = doe2;
window.frames[0].location.replace(url1);
}
function doe2() {
window.frames[0].location = 'data:text/html;charset=utf-8,2nd%20page';
window.frames[0].frameElement.onload = doe3;
}
function doe3() {
window.frames[0].frameElement.onload = doe4;
history.go(-1);
}
function doe4() {
opener.is(window.frames[0].location, url1, "History.go(-1) didn't work?");
opener.is(window.frames[1].location, "about:blank",
"History.go(-1) didn't work?");
close();
}
</script>
</head>
<body onload="doe();" onunload="opener.nextTest();">
</body></html>

View File

@ -0,0 +1,40 @@
<html><head>
<title>Bug 426646, Using location.replace breaks iframe history</title>
<script type="text/javascript">
var url1 = "data:text/html;charset=utf-8,1st%20page";
var win0 = null;
function doe() {
document.body.innerHTML = "<iframe src='about:blank'></iframe>";
document.body.innerHTML += "<iframe src='about:blank'></iframe>";
win0 = window.frames[0];
win0.frameElement.onload = doe2;
win0.location.replace(url1);
}
function doe2() {
// Add some iframes/docshells. Session history should still work.
var ifr1 = document.createElement("iframe");
document.body.insertBefore(ifr1, document.body.firstChild);
var ifr2 = document.createElement("iframe");
document.body.insertBefore(ifr2, document.body.firstChild);
var ifr3 = document.createElement("iframe");
document.body.insertBefore(ifr3, document.body.firstChild);
win0.frameElement.onload = doe3;
win0.location = 'data:text/html;charset=utf-8,2nd%20page';
}
function doe3() {
win0.frameElement.onload = doe4;
history.go(-1);
}
function doe4() {
opener.is(win0.location, url1, "History.go(-1) didn't work?");
close();
}
</script>
</head>
<body onload="doe();" onunload="opener.nextTest();">
</body></html>

View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=426646
-->
<head>
<title>Test for Bug 426646</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426646">Mozilla Bug 426646</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 426646 **/
var testNumber = 0;
var testCount = 2;
function nextTest() {
if (++testNumber <= testCount) {
window.open("file_bug426646-" + testNumber + ".html", "", "width=100,height=100");
} else {
SimpleTest.finish();
}
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(nextTest);
</script>
</pre>
</body>
</html>

View File

@ -2366,8 +2366,26 @@ nsDocShell::AddChild(nsIDocShellTreeItem * aChild)
// XXX in that case docshell hierarchy and SH hierarchy won't match.
{
nsCOMPtr<nsIDocShell> childDocShell = do_QueryInterface(aChild);
if (childDocShell)
childDocShell->SetChildOffset(mChildList.Count() - 1);
if (childDocShell) {
// If there are frameloaders in the finalization list, reduce
// the offset so that the SH hierarchy is more likely to match the
// docshell hierarchy
nsCOMPtr<nsIDOMDocument> domDoc =
do_GetInterface(GetAsSupports(this));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
PRUint32 offset = mChildList.Count() - 1;
if (doc) {
PRUint32 oldChildCount = offset; // Current child count - 1
for (PRUint32 i = 0; i < oldChildCount; ++i) {
nsCOMPtr<nsIDocShell> child = do_QueryInterface(ChildAt(i));
if (doc->FrameLoaderScheduledToBeFinalized(child)) {
--offset;
}
}
}
childDocShell->SetChildOffset(offset);
}
}
/* Set the child's global history if the parent has one */