Bug 449778. Don't fire pageshow in the new place on viewer swap if it's about to fire anyway. Do fire it in the old spot in that case, though. r+sr=jst

This commit is contained in:
Boris Zbarsky 2008-12-28 10:34:00 -08:00
Родитель fbf7f59473
Коммит a7080c05c8
6 изменённых файлов: 189 добавлений и 17 удалений

Просмотреть файл

@ -97,8 +97,8 @@ class nsFrameLoader;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0x92b19d1c, 0x8f37, 0x4d4b, \
{ 0xa3, 0x42, 0xb5, 0xc6, 0x8b, 0x54, 0xde, 0x6c } }
{ 0x29f7a5d7, 0xb217, 0x4ea2, \
{0x95, 0x40, 0x46, 0x41, 0xb9, 0xf5, 0x99, 0xd9 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -1097,6 +1097,13 @@ public:
*/
virtual void EnumerateExternalResources(nsSubDocEnumFunc aCallback,
void* aData) = 0;
/**
* Return whether the document is currently showing (in the sense of
* OnPageShow() having been called already and OnPageHide() not having been
* called yet.
*/
PRBool IsShowing() { return mIsShowing; }
protected:
~nsIDocument()
@ -1171,6 +1178,9 @@ protected:
// True iff we've ever fired a DOMTitleChanged event for this document
PRPackedBool mHaveFiredTitleChange;
// True iff IsShowing() should be returning true
PRPackedBool mIsShowing;
// The bidi options for this document. What this bitfield means is
// defined in nsBidiUtils.h
PRUint32 mBidiOptions;

Просмотреть файл

@ -7095,6 +7095,10 @@ nsDocument::OnPageShow(PRBool aPersisted)
}
}
// Set mIsShowing before firing events, in case those event handlers
// move us around.
mIsShowing = PR_TRUE;
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, aPersisted);
DispatchEventToWindow(&event);
}
@ -7121,6 +7125,10 @@ nsDocument::OnPageHide(PRBool aPersisted)
}
}
// Set mIsShowing before firing events, in case those event handlers
// move us around.
mIsShowing = PR_FALSE;
// Now send out a PageHide event.
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_HIDE, aPersisted);
DispatchEventToWindow(&event);

Просмотреть файл

@ -313,9 +313,14 @@ FirePageHideEvent(nsIDocShellTreeItem* aItem,
}
}
// The pageshow event is fired for a given document only if IsShowing() returns
// the same thing as aFireIfShowing. This gives us a way to fire pageshow only
// on documents that are still loading or only on documents that are already
// loaded.
static void
FirePageShowEvent(nsIDocShellTreeItem* aItem,
nsIDOMEventTarget* aChromeEventHandler)
nsIDOMEventTarget* aChromeEventHandler,
PRBool aFireIfShowing)
{
PRInt32 childCount = 0;
aItem->GetChildCount(&childCount);
@ -327,14 +332,18 @@ FirePageShowEvent(nsIDocShellTreeItem* aItem,
for (PRUint32 i = 0; i < kids.Length(); ++i) {
if (kids[i]) {
FirePageShowEvent(kids[i], aChromeEventHandler);
FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing);
}
}
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, PR_TRUE);
nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(aItem);
event.target = do_QueryInterface(doc);
nsEventDispatcher::Dispatch(aChromeEventHandler, nsnull, &event);
nsCOMPtr<nsIDocument> internalDoc = do_QueryInterface(doc);
NS_ASSERTION(internalDoc, "What happened here?");
if (internalDoc->IsShowing() == aFireIfShowing) {
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, PR_TRUE);
event.target = do_QueryInterface(doc);
nsEventDispatcher::Dispatch(aChromeEventHandler, nsnull, &event);
}
}
static void
@ -609,8 +618,11 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
}
mInSwap = aOther->mInSwap = PR_TRUE;
// Fire pagehide events. Note that we do NOT fire these in the normal way,
// but just fire them on the chrome event handlers.
// Fire pageshow events on still-loading pages, and then fire pagehide
// events. Note that we do NOT fire these in the normal way, but just fire
// them on the chrome event handlers.
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_FALSE);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_FALSE);
FirePageHideEvent(ourTreeItem, ourChromeEventHandler);
FirePageHideEvent(otherTreeItem, otherChromeEventHandler);
@ -618,8 +630,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
nsIFrame* otherFrame = otherShell->GetPrimaryFrameFor(otherContent);
if (!ourFrame || !otherFrame) {
mInSwap = aOther->mInSwap = PR_FALSE;
FirePageShowEvent(ourTreeItem, ourChromeEventHandler);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler);
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_TRUE);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_TRUE);
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -627,8 +639,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
CallQueryInterface(ourFrame, &ourFrameFrame);
if (!ourFrameFrame) {
mInSwap = aOther->mInSwap = PR_FALSE;
FirePageShowEvent(ourTreeItem, ourChromeEventHandler);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler);
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_TRUE);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_TRUE);
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -636,8 +648,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
if (NS_FAILED(rv)) {
mInSwap = aOther->mInSwap = PR_FALSE;
FirePageShowEvent(ourTreeItem, ourChromeEventHandler);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler);
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_TRUE);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_TRUE);
return rv;
}
@ -690,8 +702,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
ourParentDocument->FlushPendingNotifications(Flush_Layout);
otherParentDocument->FlushPendingNotifications(Flush_Layout);
FirePageShowEvent(ourTreeItem, otherChromeEventHandler);
FirePageShowEvent(otherTreeItem, ourChromeEventHandler);
FirePageShowEvent(ourTreeItem, otherChromeEventHandler, PR_TRUE);
FirePageShowEvent(otherTreeItem, ourChromeEventHandler, PR_TRUE);
mInSwap = aOther->mInSwap = PR_FALSE;
return NS_OK;

Просмотреть файл

@ -69,6 +69,8 @@ _TEST_FILES = \
test_bug396519.xul \
bug396519_window.xul \
test_bug428288.html \
test_bug449778.xul \
bug449778_window.xul \
test_bug454235.xul \
bug454235-subframe.xul \
test_bug456980.xul \

Просмотреть файл

@ -0,0 +1,107 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window title="Mozilla Bug 449778" 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 449778 **/
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>";
var doc3 = "data:text/html,<html><body>This is a <script>var evt = document.createEvent('Events'); evt.initEvent('testEvt', true, true); document.dispatchEvent(evt);</script>third test</body></html>";
$("f1").setAttribute("src", doc1);
$("f2").setAttribute("src", doc2);
function doTheTest() {
var strs = { "f1": "", "f2" : "" };
function attachListener(node, type) {
var listener = function(e) {
if (strs[node.id]) strs[node.id] += " ";
strs[node.id] += node.id + ".page" + type;
}
node.addEventListener("page" + type, listener, false);
listener.detach = function() {
node.removeEventListener("page" + type, listener, false);
}
return listener;
}
var l1 = attachListener($("f1"), "show");
var l2 = attachListener($("f1"), "hide");
var l3 = attachListener($("f2"), "show");
var l4 = attachListener($("f2"), "hide");
$("f1").swapDocShells($("f2"));
is(strs["f1"], "f1.pagehide f1.pageshow",
"Expected hide then show on first loaded page");
is(strs["f2"], "f2.pagehide f2.pageshow",
"Expected hide then show on second loaded page");
function listener2() {
$("f2").removeEventListener("testEvt", listener2, false);
strs = { "f1": "", "f2" : "" };
$("f1").swapDocShells($("f2"));
is(strs["f1"], "f1.pagehide",
"Expected hide on already-loaded page, then nothing");
is(strs["f2"], "f2.pageshow f2.pagehide f2.pageshow",
"Expected show on still-loading page, then hide on it, then show " +
"on already-loaded page");
strs = { "f1": "", "f2" : "" };
$("f1").addEventListener("pageshow", listener3, false);
}
function listener3() {
$("f1").removeEventListener("pageshow", listener3, false);
is(strs["f1"], "f1.pageshow",
"Expected show as our page finishes loading");
is(strs["f2"], "", "Expected no more events here.");
l1.detach();
l2.detach();
l3.detach();
l4.detach();
window.close();
SimpleTest.finish();
}
$("f2").addEventListener("testEvt", listener2, false, true);
$("f2").setAttribute("src", doc3);
}
]]></script>
</window>

Просмотреть файл

@ -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=449778
-->
<window title="Mozilla Bug 449778"
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=449778"
target="_blank">Mozilla Bug 396519</a>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
window.open("bug449778_window.xul", "bug449778",
"chrome,width=800,height=800");
});
]]></script>
</window>