Bug 449780. When doing a frameloader swap, clear the bfcache on both docshells, since we can't deal with all those presentations. r+sr=jst

This commit is contained in:
Boris Zbarsky 2009-01-13 14:32:30 -05:00
parent 8a568e773c
commit 9ab3dc1969
7 changed files with 163 additions and 20 deletions

View File

@ -73,6 +73,7 @@
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "nsISHistory.h"
#include "nsISHistoryInternal.h"
#include "nsIURI.h"
#include "nsIURL.h"
@ -494,7 +495,6 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
nsCOMPtr<nsIDocShellTreeItem> ourRootTreeItem, otherRootTreeItem;
ourTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(ourRootTreeItem));
otherTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(otherRootTreeItem));
if (ourRootTreeItem != ourTreeItem || otherRootTreeItem != otherTreeItem) {
nsCOMPtr<nsIWebNavigation> ourRootWebnav =
do_QueryInterface(ourRootTreeItem);
nsCOMPtr<nsIWebNavigation> otherRootWebnav =
@ -509,10 +509,10 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
ourRootWebnav->GetSessionHistory(getter_AddRefs(ourHistory));
otherRootWebnav->GetSessionHistory(getter_AddRefs(otherHistory));
if (ourHistory || otherHistory) {
if ((ourRootTreeItem != ourTreeItem || otherRootTreeItem != otherTreeItem) &&
(ourHistory || otherHistory)) {
return NS_ERROR_NOT_IMPLEMENTED;
}
}
// Also make sure that the two docshells are the same type. Otherwise
// swapping is certainly not safe.
@ -524,7 +524,7 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
return NS_ERROR_NOT_IMPLEMENTED;
}
// One more twist here. Setting up the right treeowners in a heterogenous
// One more twist here. Setting up the right treeowners in a heterogeneous
// tree is a bit of a pain. So make sure that if ourType is not
// nsIDocShellTreeItem::typeContent then all of our descendants are the same
// type as us.
@ -692,6 +692,18 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
aFirstToSwap.swap(aSecondToSwap);
// Drop any cached content viewers in the two session histories.
nsCOMPtr<nsISHistoryInternal> ourInternalHistory =
do_QueryInterface(ourHistory);
nsCOMPtr<nsISHistoryInternal> otherInternalHistory =
do_QueryInterface(otherHistory);
if (ourInternalHistory) {
ourInternalHistory->EvictAllContentViewers();
}
if (otherInternalHistory) {
otherInternalHistory->EvictAllContentViewers();
}
// We shouldn't have changed frames, but be really careful about it
if (ourFrame == ourShell->GetPrimaryFrameFor(ourContent) &&
otherFrame == otherShell->GetPrimaryFrameFor(otherContent)) {

View File

@ -52,7 +52,7 @@ interface nsIDocShell;
#define NS_SHISTORY_INTERNAL_CONTRACTID "@mozilla.org/browser/shistory-internal;1"
%}
[scriptable, uuid(9c47c121-1c6e-4d8f-b904-3ac968116e88)]
[scriptable, uuid(7ca0fd71-437c-48ad-985d-11ce9e2429b4)]
interface nsISHistoryInternal: nsISupports
{
/**
@ -105,4 +105,9 @@ interface nsISHistoryInternal: nsISupports
* that has timed out.
*/
void evictExpiredContentViewerForEntry(in nsISHEntry aEntry);
/**
* Evict all the content viewers in this session history
*/
void evictAllContentViewers();
};

View File

@ -118,7 +118,7 @@ nsSHistoryObserver::Observe(nsISupports *aSubject, const char *aTopic,
nsSHistory::EvictGlobalContentViewer();
} else if (!strcmp(aTopic, NS_CACHESERVICE_EMPTYCACHE_TOPIC_ID) ||
!strcmp(aTopic, "memory-pressure")) {
nsSHistory::EvictAllContentViewers();
nsSHistory::EvictAllContentViewersGlobally();
}
return NS_OK;
@ -664,6 +664,17 @@ nsSHistory::EvictContentViewers(PRInt32 aPreviousIndex, PRInt32 aIndex)
return NS_OK;
}
NS_IMETHODIMP
nsSHistory::EvictAllContentViewers()
{
// XXXbz we don't actually do a good job of evicting things as we should, so
// we might have viewers quite far from mIndex. So just evict everything.
EvictContentViewersInRange(0, mLength);
return NS_OK;
}
//*****************************************************************************
// nsSHistory: nsIWebNavigation
//*****************************************************************************
@ -1038,7 +1049,7 @@ nsSHistory::EvictExpiredContentViewerForEntry(nsISHEntry *aEntry)
//static
void
nsSHistory::EvictAllContentViewers()
nsSHistory::EvictAllContentViewersGlobally()
{
PRInt32 maxViewers = sHistoryMaxTotalViewers;
sHistoryMaxTotalViewers = 0;

View File

@ -99,10 +99,12 @@ protected:
nsresult PrintHistory();
#endif
// Evict the viewers at indices between aStartIndex and aEndIndex,
// including aStartIndex but not aEndIndex.
void EvictContentViewersInRange(PRInt32 aStartIndex, PRInt32 aEndIndex);
void EvictWindowContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex);
static void EvictGlobalContentViewer();
static void EvictAllContentViewers();
static void EvictAllContentViewersGlobally();
// Calculates a max number of total
// content viewers to cache, based on amount of total memory

View File

@ -71,6 +71,8 @@ _TEST_FILES = \
test_bug428288.html \
test_bug449778.xul \
bug449778_window.xul \
test_bug449780.xul \
bug449780_window.xul \
test_bug454235.xul \
bug454235-subframe.xul \
test_bug456980.xul \

View File

@ -0,0 +1,78 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window title="Mozilla Bug 449780" onload="doTheTest()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<hbox id="parent">
</hbox>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok", "snapshotWindow",
"compareSnapshots", "onerror" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
}
function $(id) {
return document.getElementById(id);
}
function addBrowser(parent, id, width, height) {
var b =
document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
b.setAttribute("type", "content");
b.setAttribute("id", id);
b.setAttribute("width", width);
b.setAttribute("height", height);
$(parent).appendChild(b);
}
addBrowser("parent", "f1", 300, 200);
addBrowser("parent", "f2", 300, 200);
/** Test for Bug 449780 **/
var doc1 = "data:text/html,<html><body>This is a test</body></html>";
var doc2 = "data:text/html,<html><body>This is a second test</body></html>";
function getDOM(id) {
return $(id).contentDocument.documentElement.innerHTML;
}
var tester = (function() {
var origDOM = getDOM("f1");
$("f1").contentDocument.body.textContent = "Modified";
var modifiedDOM = getDOM("f1");
isnot(origDOM, modifiedDOM, "DOM should be different");
$("f1").contentWindow.location.href = doc2;
yield;
$("f1").goBack();
yield;
is(getDOM("f1"), modifiedDOM, "Should have been bfcached");
$("f1").goForward();
yield;
// Ignore the notifications during swap
$("f1").removeEventListener("pageshow", testDriver, false);
$("f1").swapDocShells($("f2"));
$("f2").addEventListener("pageshow", testDriver, false);
$("f2").goBack();
yield;
is(getDOM("f2"), origDOM, "Should have not have been bfcached");
window.close();
SimpleTest.finish();
yield;
})();
function testDriver() {
setTimeout(function() { tester.next() }, 0);
}
function doTheTest() {
$("f1").addEventListener("pageshow", testDriver, false);
$("f1").setAttribute("src", doc1);
}
]]></script>
</window>

View File

@ -0,0 +1,33 @@
<?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=449780
-->
<window title="Mozilla Bug 449780"
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>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.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=449780"
target="_blank">Mozilla Bug 396519</a>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
window.open("bug449780_window.xul", "bug449780",
"chrome,width=800,height=800");
});
]]></script>
</window>