Bug 480149 - DOMLinkAdded and DOMLinkRemoved events for link elements should be dispatched when swapping docshells. r+sr=bz.

This commit is contained in:
Asaf Romano 2009-02-26 14:05:42 -08:00
parent e0648db07b
commit 8900bd48d4
7 changed files with 145 additions and 161 deletions

View File

@ -1,4 +1,3 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@ -12,18 +11,19 @@
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla CE Shunt Library.
# The Original Code is Mozilla core build scripts.
#
# The Initial Developer of the Original Code is Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
# The Initial Developer of the Original Code is
# Brad Lassey <blassey@mozilla.com>
#
# Contributor(s):
# John Wolfe (wolfe@lobo.us)
# Portions created by the Initial Developer are Copyright (C) 2005
# the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
@ -35,101 +35,19 @@
#
# ***** END LICENSE BLOCK *****
DEVENV_FLAG=-
CC=cl -O2
MOZCE_DEVENV=vs$(MOZ_MSVCVERSION)
MOZCE_SHUNT_SLN=$(TOPSRCDIR)/build/wince/shunt/build/$(MOZCE_DEVENV)/mozce_shunt_static.sln
MOZCE_PROJECT="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
MOZCE_SHUNT_DLL=../shunt/build/$(MOZCE_DEVENV)/mozce_shunt.dll
MOZCE_TOOLS_DIR=$(TOPSRCDIR)/build/wince/tools
MOZCE_TOOLS_BIN_DIR=$(OBJDIR)/dist/sdk/bin
BUILD_SWITCH=$(DEVENV_FLAG)Build
REBUILD_SWITCH=$(DEVENV_FLAG)Rebuild
CLEAN_SWITCH=$(DEVENV_FLAG)clean
ifeq ($(VCINSTALLDIR),)
$(error Environment variable VCINSTALLDIR not set! Are you using MozillaBuild?)
endif
ifeq ($(WINCE_SDK_DIR),)
$(error Environment variable WINCE_SDK_DIR not set! It must be passed to make if not running from configure)
endif
ifeq ($(MOZ_MSVCVERSION),)
$(error Environment variable MOZ_MSVCVERSION not set! Are you using MozillaBuild?)
endif
CFLAGS += \
-DVC_PATH='"$(subst \,\\,$(VCINSTALLDIR))\\"' \
-DWM_SDK_PATH='"$(subst \,\\,$(WINCE_SDK_DIR))\\"' \
-DMOZCE_DEVENV='"$(MOZCE_DEVENV)"' \
-DTOPSRCDIR='"$(TOPSRCDIR)"' \
$(NULL)
ifneq ($(WINDOWSSDKDIR),)
CFLAGS += -DWIN_SDK_PATH='"$(subst \,\\,$(WINDOWSSDKDIR))"'
else
ifeq ($(SDKDIR),)
$(error Environment variable WINDOWSSDKDIR not set! Are you using MozillaBuild?)
else
CFLAGS += -DWIN_SDK_PATH='"$(subst \,\\,$(SDKDIR))"'
endif
endif
ifdef VPATH
CFLAGS += -DSHUNT_INC='"$(OBJDIR)/dist/include/shunt"'
else
CFLAGS += -DSHUNT_INC='"$(TOPSRCDIR)/build/wince/shunt/include"'
endif
CFLAGS += -DEBUG -Zi
all: libs
libs: output_some_env \
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-as.exe \
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-gcc.exe \
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-lib.exe \
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-link.exe \
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-res.exe
devenv $(MOZCE_SHUNT_SLN) $(BUILD_SWITCH) $(MOZCE_PROJECT)
clean: clobber
DEPTH = ../../..
topsrcdir = ../../..
srcdir = .
VPATH = .
clobber:
rm $(MOZCE_TOOLS_BIN_DIR)/arm-wince-as.exe
rm $(MOZCE_TOOLS_BIN_DIR)/arm-wince-gcc.exe
rm $(MOZCE_TOOLS_BIN_DIR)/arm-wince-lib.exe
rm $(MOZCE_TOOLS_BIN_DIR)/arm-wince-link.exe
rm $(MOZCE_TOOLS_BIN_DIR)/arm-wince-res.exe
devenv $(MOZCE_SHUNT_SLN) $(CLEAN_SWITCH) $(MOZCE_PROJECT)
TOPSRCDIR = $(topsrcdir)
OBJDIR = $(shell cd $(DEPTH); pwd -W)
output_some_env:
@echo FOUND $(MOZCE_DEVENV)
@echo FOUND $(MOZCE_DEVENV): VSINSTALLDIR=$(VSINSTALLDIR) / MINGW32=$(MINGW32) / MSYSTEM=$(MSYSTEM)
@echo FOUND $(MOZCE_DEVENV)
include $(DEPTH)/config/autoconf.mk
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-as.exe: $(MOZCE_TOOLS_DIR)/arm-wince-as.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile
mkdir -p $(MOZCE_TOOLS_BIN_DIR);
$(CC) $(CFLAGS) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-as.c
include $(topsrcdir)/build/wince/tools/Makefile
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-gcc.exe: $(MOZCE_TOOLS_DIR)/arm-wince-gcc.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile
mkdir -p $(MOZCE_TOOLS_BIN_DIR);
$(CC) $(CFLAGS) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-gcc.c
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-lib.exe: $(MOZCE_TOOLS_DIR)/arm-wince-lib.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile
mkdir -p $(MOZCE_TOOLS_BIN_DIR);
$(CC) $(CFLAGS) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-lib.c
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-link.exe: $(MOZCE_TOOLS_DIR)/arm-wince-link.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile
mkdir -p $(MOZCE_TOOLS_BIN_DIR);
$(CC) $(CFLAGS) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-link.c
$(MOZCE_TOOLS_BIN_DIR)/arm-wince-res.exe: $(MOZCE_TOOLS_DIR)/arm-wince-res.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile
mkdir -p $(MOZCE_TOOLS_BIN_DIR);
$(CC) $(CFLAGS) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-res.c
export::
tools::

View File

@ -69,6 +69,7 @@ class nsIViewManager;
class nsIScriptGlobalObject;
class nsPIDOMWindow;
class nsIDOMEvent;
class nsIDOMEventTarget;
class nsIDeviceContext;
class nsIParser;
class nsIDOMNode;
@ -852,9 +853,14 @@ public:
* or to the page's presentation being restored into an existing DOM window.
* This notification fires applicable DOM events to the content window. See
* nsIDOMPageTransitionEvent.idl for a description of the |aPersisted|
* parameter.
* parameter. If aDispatchStartTarget is null, the pageshow event is
* dispatched on the ScriptGlobalObject for this document, otherwise it's
* dispatched on aDispatchStartTarget.
* Note: if aDispatchStartTarget isn't null, the showing state of the
* document won't be altered.
*/
virtual void OnPageShow(PRBool aPersisted) = 0;
virtual void OnPageShow(PRBool aPersisted,
nsIDOMEventTarget* aDispatchStartTarget) = 0;
/**
* Notification that the page has been hidden, for documents which are loaded
@ -862,9 +868,14 @@ public:
* to the document's presentation being saved but removed from an existing
* DOM window. This notification fires applicable DOM events to the content
* window. See nsIDOMPageTransitionEvent.idl for a description of the
* |aPersisted| parameter.
* |aPersisted| parameter. If aDispatchStartTarget is null, the pagehide
* event is dispatched on the ScriptGlobalObject for this document,
* otherwise it's dispatched on aDispatchStartTarget.
* Note: if aDispatchStartTarget isn't null, the showing state of the
* document won't be altered.
*/
virtual void OnPageHide(PRBool aPersisted) = 0;
virtual void OnPageHide(PRBool aPersisted,
nsIDOMEventTarget* aDispatchStartTarget) = 0;
/*
* We record the set of links in the document that are relevant to

View File

@ -7150,7 +7150,7 @@ nsDocument::DispatchEventToWindow(nsEvent *aEvent)
}
void
nsDocument::OnPageShow(PRBool aPersisted)
nsDocument::OnPageShow(PRBool aPersisted, nsIDOMEventTarget* aDispatchStartTarget)
{
mVisible = PR_TRUE;
UpdateLinkMap();
@ -7173,10 +7173,11 @@ nsDocument::OnPageShow(PRBool aPersisted)
}
}
// Set mIsShowing before firing events, in case those event handlers
// move us around.
mIsShowing = PR_TRUE;
// See nsIDocument
if (!aDispatchStartTarget) {
mIsShowing = PR_TRUE;
}
#ifdef MOZ_SMIL
if (mAnimationController) {
mAnimationController->OnPageShow();
@ -7184,11 +7185,16 @@ nsDocument::OnPageShow(PRBool aPersisted)
#endif
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, aPersisted);
DispatchEventToWindow(&event);
if (aDispatchStartTarget) {
event.target = static_cast<nsIDocument*>(this);
nsEventDispatcher::Dispatch(aDispatchStartTarget, nsnull, &event);
} else {
DispatchEventToWindow(&event);
}
}
void
nsDocument::OnPageHide(PRBool aPersisted)
nsDocument::OnPageHide(PRBool aPersisted, nsIDOMEventTarget* aDispatchStartTarget)
{
// Send out notifications that our <link> elements are detached,
// but only if this is not a full unload.
@ -7209,9 +7215,10 @@ nsDocument::OnPageHide(PRBool aPersisted)
}
}
// Set mIsShowing before firing events, in case those event handlers
// move us around.
mIsShowing = PR_FALSE;
// See nsIDocument
if (!aDispatchStartTarget) {
mIsShowing = PR_FALSE;
}
#ifdef MOZ_SMIL
if (mAnimationController) {
@ -7221,7 +7228,12 @@ nsDocument::OnPageHide(PRBool aPersisted)
// Now send out a PageHide event.
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_HIDE, aPersisted);
DispatchEventToWindow(&event);
if (aDispatchStartTarget) {
event.target = static_cast<nsIDocument*>(this);
nsEventDispatcher::Dispatch(aDispatchStartTarget, nsnull, &event);
} else {
DispatchEventToWindow(&event);
}
mVisible = PR_FALSE;
}

View File

@ -804,8 +804,8 @@ public:
nsAString& Standalone);
virtual PRBool IsScriptEnabled();
virtual void OnPageShow(PRBool aPersisted);
virtual void OnPageHide(PRBool aPersisted);
virtual void OnPageShow(PRBool aPersisted, nsIDOMEventTarget* aDispatchStartTarget);
virtual void OnPageHide(PRBool aPersisted, nsIDOMEventTarget* aDispatchStartTarget);
virtual void WillDispatchMutationEvent(nsINode* aTarget);
virtual void MutationEventDispatched(nsINode* aTarget);

View File

@ -297,11 +297,11 @@ static void
FirePageHideEvent(nsIDocShellTreeItem* aItem,
nsIDOMEventTarget* aChromeEventHandler)
{
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_HIDE, 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?");
internalDoc->OnPageHide(PR_TRUE, aChromeEventHandler);
PRInt32 childCount = 0;
aItem->GetChildCount(&childCount);
nsAutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
@ -344,9 +344,7 @@ FirePageShowEvent(nsIDocShellTreeItem* aItem,
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);
internalDoc->OnPageShow(PR_TRUE, aChromeEventHandler);
}
}

View File

@ -41,7 +41,7 @@
/** Test for Bug 113934 **/
var doc1 =
"data:text/html,<html><body onbeforeunload='document.documentElement.textContent = \"\"' onunload='document.documentElement.textContent = \"\"' onpagehide='document.documentElement.textContent = \"\"'>This is a test</body></html>";
var doc2 = "data:text/html,<html><body>This is a second test</body></html>";
var doc2 = "data:text/html,<html><head></head><body>This is a second test</body></html>";
$("f1").setAttribute("src", doc1);
@ -73,42 +73,87 @@
is(getDOM("f1"), dom2star, "Shouldn't have changed the DOM on swap");
is(getDOM("f2"), dom1, "Shouldn't have fired event handlers");
var strs = { "f1": "", "f3" : "" };
function attachListener(node, type) {
var listener = function(e) {
if (strs[node.id]) strs[node.id] += " ";
strs[node.id] += node.id + ".page" + type;
// Test for bug 480149
// The DOMLink* events are dispatched asynchronously, thus I cannot
// just include the <link> element in the initial DOM and swap the
// docshells. Instead, the link element is added now. Then, when the
// first DOMLinkAdded event (which is a result of the actual addition)
// is dispatched, the docshells are swapped and the pageshow and pagehide
// events are tested. Only then, we wait for the DOMLink* events,
// which are a result of swapping the docshells.
var DOMLinkListener = {
_afterFirst: false,
_removedDispatched: false,
_addedDispatched: false,
handleEvent: function(aEvent) {
if (!this._afterFirst) {
is(aEvent.type, "DOMLinkAdded");
var strs = { "f1": "", "f3" : "" };
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($("f3"), "show");
var l4 = attachListener($("f3"), "hide");
$("f1").swapDocShells($("f3"));
// now we have DOMs 2, 1, 2* in the frames
l1.detach();
l2.detach();
l3.detach();
l4.detach();
var s1_new = snapshotWindow($("f1").contentWindow);
var [same, first, second] = compareSnapshots(s1_new, s2, true);
ok(same, "Should reflow on swap", "Expected " + second + " but got " + first);
is(strs["f1"], "f1.pagehide f1.pageshow");
is(strs["f3"], "f3.pagehide f3.pageshow");
this._afterFirst = true;
return;
}
if (aEvent.type == "DOMLinkAdded") {
is(this._addedDispatched, false);
this._addedDispatched = true;
}
else {
is(this._removedDispatched, false);
this._removedDispatched = true;
}
if (this._addedDispatched && this._removedDispatched) {
$("f1").removeEventListener("DOMLinkAdded", this, false);
$("f1").removeEventListener("DOMLinkRemoved", this, false);
$("f3").removeEventListener("DOMLinkAdded", this, false);
$("f3").removeEventListener("DOMLinkRemoved", this, false);
window.close();
SimpleTest.finish();
}
}
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($("f3"), "show");
var l4 = attachListener($("f3"), "hide");
$("f1").addEventListener("DOMLinkAdded", DOMLinkListener, false);
$("f1").addEventListener("DOMLinkRemoved", DOMLinkListener, false);
$("f3").addEventListener("DOMLinkAdded", DOMLinkListener, false);
$("f3").addEventListener("DOMLinkRemoved", DOMLinkListener, false);
$("f1").swapDocShells($("f3"));
// now we have DOMs 2, 1, 2* in the frames
l1.detach();
l2.detach();
l3.detach();
l4.detach();
var s1_new = snapshotWindow($("f1").contentWindow);
var [same, first, second] = compareSnapshots(s1_new, s2, true);
ok(same, "Should reflow on swap", "Expected " + second + " but got " + first);
is(strs["f1"], "f1.pagehide f1.pageshow");
is(strs["f3"], "f3.pagehide f3.pageshow");
window.close();
SimpleTest.finish();
var linkElement = $("f1").contentDocument.createElement("link");
linkElement.setAttribute("rel", "alternate");
linkElement.setAttribute("href", "about:blank");
$("f1").contentDocument.documentElement.firstChild.appendChild(linkElement);
}
]]></script>

View File

@ -1019,7 +1019,7 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
// it was just loaded). Note: mDocument may be null now if the above
// firing of onload caused the document to unload.
if (mDocument)
mDocument->OnPageShow(restoring);
mDocument->OnPageShow(restoring, nsnull);
// Now that the document has loaded, we can tell the presshell
// to unsuppress painting.
@ -1169,7 +1169,7 @@ DocumentViewerImpl::PageHide(PRBool aIsUnload)
return NS_ERROR_NULL_POINTER;
}
mDocument->OnPageHide(!aIsUnload);
mDocument->OnPageHide(!aIsUnload, nsnull);
if (aIsUnload) {
// if Destroy() was called during OnPageHide(), mDocument is nsnull.
NS_ENSURE_STATE(mDocument);