зеркало из https://github.com/mozilla/gecko-dev.git
Bug 602256: Using history.pushState in a page breaks history tracking for inner frames. r=bz, a=blocks-betaN
This commit is contained in:
Родитель
c633a6c870
Коммит
90729fb263
|
@ -3369,6 +3369,7 @@ nsDocShell::AddChildSHEntry(nsISHEntry * aCloneRef, nsISHEntry * aNewEntry,
|
|||
nsCOMPtr<nsISHEntry> nextEntry;
|
||||
aCloneRef->GetID(&cloneID);
|
||||
rv = CloneAndReplace(currentEntry, this, cloneID, aNewEntry,
|
||||
loadType == LOAD_PUSHSTATE,
|
||||
getter_AddRefs(nextEntry));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
@ -9918,6 +9919,16 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel,
|
|||
|
||||
|
||||
if (root == static_cast<nsIDocShellTreeItem *>(this) && mSessionHistory) {
|
||||
// Bug 629559: Detect if this is an anchor navigation and clone the
|
||||
// session history in that case too
|
||||
if (mLoadType == LOAD_PUSHSTATE) {
|
||||
PRUint32 cloneID;
|
||||
mOSHE->GetID(&cloneID);
|
||||
nsCOMPtr<nsISHEntry> newEntry;
|
||||
CloneAndReplace(mOSHE, this, cloneID, entry, PR_TRUE, getter_AddRefs(newEntry));
|
||||
NS_ASSERTION(entry == newEntry, "The new session history should be in the new entry");
|
||||
}
|
||||
|
||||
// This is the root docshell
|
||||
if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
|
||||
// Replace current entry in session history.
|
||||
|
@ -10131,12 +10142,14 @@ nsDocShell::WalkHistoryEntries(nsISHEntry *aRootEntry,
|
|||
struct NS_STACK_CLASS CloneAndReplaceData
|
||||
{
|
||||
CloneAndReplaceData(PRUint32 aCloneID, nsISHEntry *aReplaceEntry,
|
||||
nsISHEntry *aDestTreeParent)
|
||||
PRBool aCloneChildren, nsISHEntry *aDestTreeParent)
|
||||
: cloneID(aCloneID),
|
||||
cloneChildren(aCloneChildren),
|
||||
replaceEntry(aReplaceEntry),
|
||||
destTreeParent(aDestTreeParent) { }
|
||||
|
||||
PRUint32 cloneID;
|
||||
PRBool cloneChildren;
|
||||
nsISHEntry *replaceEntry;
|
||||
nsISHEntry *destTreeParent;
|
||||
nsCOMPtr<nsISHEntry> resultEntry;
|
||||
|
@ -10166,9 +10179,19 @@ nsDocShell::CloneAndReplaceChild(nsISHEntry *aEntry, nsDocShell *aShell,
|
|||
aEntry->GetID(&srcID);
|
||||
|
||||
if (srcID == cloneID) {
|
||||
// Just replace the entry, and don't walk the children.
|
||||
// Replace the entry
|
||||
dest = replaceEntry;
|
||||
dest->SetIsSubFrame(PR_TRUE);
|
||||
|
||||
if (data->cloneChildren) {
|
||||
// Walk the children
|
||||
CloneAndReplaceData childData(cloneID, replaceEntry,
|
||||
data->cloneChildren, dest);
|
||||
result = WalkHistoryEntries(aEntry, aShell,
|
||||
CloneAndReplaceChild, &childData);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
// Clone the SHEntry...
|
||||
result = aEntry->Clone(getter_AddRefs(dest));
|
||||
|
@ -10179,7 +10202,8 @@ nsDocShell::CloneAndReplaceChild(nsISHEntry *aEntry, nsDocShell *aShell,
|
|||
dest->SetIsSubFrame(PR_TRUE);
|
||||
|
||||
// Walk the children
|
||||
CloneAndReplaceData childData(cloneID, replaceEntry, dest);
|
||||
CloneAndReplaceData childData(cloneID, replaceEntry,
|
||||
data->cloneChildren, dest);
|
||||
result = WalkHistoryEntries(aEntry, aShell,
|
||||
CloneAndReplaceChild, &childData);
|
||||
if (NS_FAILED(result))
|
||||
|
@ -10201,12 +10225,13 @@ nsDocShell::CloneAndReplace(nsISHEntry *aSrcEntry,
|
|||
nsDocShell *aSrcShell,
|
||||
PRUint32 aCloneID,
|
||||
nsISHEntry *aReplaceEntry,
|
||||
PRBool aCloneChildren,
|
||||
nsISHEntry **aResultEntry)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResultEntry);
|
||||
NS_ENSURE_TRUE(aReplaceEntry, NS_ERROR_FAILURE);
|
||||
|
||||
CloneAndReplaceData data(aCloneID, aReplaceEntry, nsnull);
|
||||
CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nsnull);
|
||||
nsresult rv = CloneAndReplaceChild(aSrcEntry, aSrcShell, 0, &data);
|
||||
|
||||
data.resultEntry.swap(*aResultEntry);
|
||||
|
|
|
@ -383,10 +383,13 @@ protected:
|
|||
// |aReplaceEntry|. |aSrcShell| is a (possibly null) docshell which
|
||||
// corresponds to |aSrcEntry| via its mLSHE or mOHE pointers, and will
|
||||
// have that pointer updated to point to the cloned history entry.
|
||||
// If aCloneChildren is true then the children of the entry with id
|
||||
// |aCloneID| will be cloned into |aReplaceEntry|.
|
||||
static nsresult CloneAndReplace(nsISHEntry *aSrcEntry,
|
||||
nsDocShell *aSrcShell,
|
||||
PRUint32 aCloneID,
|
||||
nsISHEntry *aReplaceEntry,
|
||||
PRBool aCloneChildren,
|
||||
nsISHEntry **aDestEntry);
|
||||
|
||||
// Child-walking callback for CloneAndReplace
|
||||
|
|
|
@ -144,6 +144,7 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
|
|||
, mParent(other.mParent)
|
||||
, mViewerBounds(0, 0, 0, 0)
|
||||
, mOwner(other.mOwner)
|
||||
, mStateData(other.mStateData)
|
||||
, mDocShellID(other.mDocShellID)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk
|
|||
_TEST_FILES = \
|
||||
497633.html \
|
||||
489127.html \
|
||||
historyframes.html \
|
||||
test_497898.html \
|
||||
test_bug504220.html \
|
||||
test_consoleAPI.html \
|
||||
|
@ -62,6 +63,8 @@ _TEST_FILES = \
|
|||
test_nodesFromRect.html \
|
||||
test_frameElementWrapping.html \
|
||||
file_frameElementWrapping.html \
|
||||
test_framedhistoryframes.html \
|
||||
test_windowedhistoryframes.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=602256
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 602256</title>
|
||||
</head>
|
||||
<body onload="SimpleTest.executeSoon(run_test)">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602256">Mozilla Bug 602256</a>
|
||||
<div id="content">
|
||||
<iframe id="iframe" src="data:text/html,<p%20id='text'>Start</p>"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 602256 **/
|
||||
|
||||
var testWin = window.opener ? window.opener : window.parent;
|
||||
|
||||
var SimpleTest = testWin.SimpleTest;
|
||||
function is() { testWin.is.apply(testWin, arguments); }
|
||||
|
||||
var gFrame = null;
|
||||
|
||||
var gState = null;
|
||||
|
||||
window.addEventListener("popstate", function(aEvent) {
|
||||
gState = aEvent.state;
|
||||
}, false);
|
||||
|
||||
function waitForLoad(aCallback) {
|
||||
function listener() {
|
||||
gFrame.removeEventListener("load", listener, false);
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
}
|
||||
|
||||
gFrame.addEventListener("load", listener, false);
|
||||
}
|
||||
|
||||
function loadContent(aURL, aCallback) {
|
||||
waitForLoad(aCallback);
|
||||
|
||||
gFrame.src = aURL;
|
||||
}
|
||||
|
||||
function getURL() {
|
||||
return gFrame.contentDocument.documentURI;
|
||||
}
|
||||
|
||||
function getContent() {
|
||||
return gFrame.contentDocument.getElementById("text").textContent;
|
||||
}
|
||||
|
||||
var START = "data:text/html,<p%20id='text'>Start</p>";
|
||||
var URL1 = "data:text/html,<p%20id='text'>Test1</p>";
|
||||
var URL2 = "data:text/html,<p%20id='text'>Test2</p>";
|
||||
|
||||
function run_test() {
|
||||
window.history.pushState("START", window.location);
|
||||
|
||||
gFrame = document.getElementById("iframe");
|
||||
|
||||
test_basic_inner_navigation();
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
testWin.done();
|
||||
}
|
||||
|
||||
function test_basic_inner_navigation() {
|
||||
// Navigate the inner frame a few times
|
||||
loadContent(URL1, function() {
|
||||
is(getURL(), URL1, "URL should be correct");
|
||||
is(getContent(), "Test1", "Page should be correct");
|
||||
|
||||
loadContent(URL2, function() {
|
||||
is(getURL(), URL2, "URL should be correct");
|
||||
is(getContent(), "Test2", "Page should be correct");
|
||||
|
||||
// Test that history is working
|
||||
waitForLoad(function() {
|
||||
is(getURL(), URL1, "URL should be correct");
|
||||
is(getContent(), "Test1", "Page should be correct");
|
||||
|
||||
waitForLoad(function() {
|
||||
is(getURL(), URL2, "URL should be correct");
|
||||
is(getContent(), "Test2", "Page should be correct");
|
||||
|
||||
test_state_navigation();
|
||||
});
|
||||
window.history.forward();
|
||||
});
|
||||
window.history.back();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_state_navigation() {
|
||||
window.history.pushState("STATE1", window.location);
|
||||
|
||||
is(getURL(), URL2, "URL should be correct");
|
||||
is(getContent(), "Test2", "Page should be correct");
|
||||
|
||||
window.history.pushState("STATE2", window.location);
|
||||
|
||||
is(getURL(), URL2, "URL should be correct");
|
||||
is(getContent(), "Test2", "Page should be correct");
|
||||
|
||||
window.history.back();
|
||||
|
||||
is(gState, "STATE1", "State should be correct");
|
||||
is(getURL(), URL2, "URL should be correct");
|
||||
is(getContent(), "Test2", "Page should be correct");
|
||||
|
||||
window.history.forward();
|
||||
|
||||
is(gState, "STATE2", "State should be correct");
|
||||
is(getURL(), URL2, "URL should be correct");
|
||||
is(getContent(), "Test2", "Page should be correct");
|
||||
|
||||
window.history.back();
|
||||
window.history.back();
|
||||
|
||||
is(gState, "START", "State should be correct");
|
||||
is(getURL(), URL2, "URL should be correct");
|
||||
is(getContent(), "Test2", "Page should be correct");
|
||||
|
||||
waitForLoad(function() {
|
||||
is(getURL(), URL1, "URL should be correct");
|
||||
is(getContent(), "Test1", "Page should be correct");
|
||||
|
||||
waitForLoad(function() {
|
||||
is(gState, "START", "State should be correct");
|
||||
is(getURL(), START, "URL should be correct");
|
||||
is(getContent(), "Start", "Page should be correct");
|
||||
|
||||
end_test();
|
||||
});
|
||||
|
||||
window.history.back();
|
||||
|
||||
is(gState, "START", "State should be correct");
|
||||
});
|
||||
|
||||
window.history.back();
|
||||
is(gState, "START", "State should be correct");
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=602256
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 602256</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/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=602256">Mozilla Bug 602256</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe id="iframe" src="historyframes.html"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 602256 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function done() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=602256
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 602256</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/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=602256">Mozilla Bug 602256</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 602256 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function done() {
|
||||
subWin.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var subWin = window.open("historyframes.html", "_blank");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче