From 5bfc7706023709df14050a87a4f7fc69d47306f1 Mon Sep 17 00:00:00 2001 From: Asaf Romano Date: Thu, 26 Feb 2009 14:05:42 -0800 Subject: [PATCH] Bug 480149 - DOMLinkAdded and DOMLinkRemoved events for link elements should be dispatched when swapping docshells. r+sr=bz. --- build/wince/tools/Makefile | 120 ++++------------------ content/base/public/nsIDocument.h | 19 +++- content/base/src/nsDocument.cpp | 34 ++++-- content/base/src/nsDocument.h | 4 +- content/base/src/nsFrameLoader.cpp | 12 +-- docshell/test/chrome/bug113934_window.xul | 113 ++++++++++++++------ layout/base/nsDocumentViewer.cpp | 4 +- 7 files changed, 145 insertions(+), 161 deletions(-) diff --git a/build/wince/tools/Makefile b/build/wince/tools/Makefile index 36b8b4402a0..edc2255d889 100644 --- a/build/wince/tools/Makefile +++ b/build/wince/tools/Makefile @@ -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 # -# Contributor(s): -# John Wolfe (wolfe@lobo.us) +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Mozilla Foundation . 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:: \ No newline at end of file diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 719ff57b236..c73e8f52c75 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -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 diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index ac7df06a8f5..98efc9a1251 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -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(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 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(this); + nsEventDispatcher::Dispatch(aDispatchStartTarget, nsnull, &event); + } else { + DispatchEventToWindow(&event); + } mVisible = PR_FALSE; } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 4108096edff..6d0705b4939 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -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); diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 794ffd51e3f..3e074973a9b 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -297,11 +297,11 @@ static void FirePageHideEvent(nsIDocShellTreeItem* aItem, nsIDOMEventTarget* aChromeEventHandler) { - nsPageTransitionEvent event(PR_TRUE, NS_PAGE_HIDE, PR_TRUE); nsCOMPtr doc = do_GetInterface(aItem); - event.target = do_QueryInterface(doc); - nsEventDispatcher::Dispatch(aChromeEventHandler, nsnull, &event); - + nsCOMPtr internalDoc = do_QueryInterface(doc); + NS_ASSERTION(internalDoc, "What happened here?"); + internalDoc->OnPageHide(PR_TRUE, aChromeEventHandler); + PRInt32 childCount = 0; aItem->GetChildCount(&childCount); nsAutoTArray, 8> kids; @@ -344,9 +344,7 @@ FirePageShowEvent(nsIDocShellTreeItem* aItem, nsCOMPtr 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); } } diff --git a/docshell/test/chrome/bug113934_window.xul b/docshell/test/chrome/bug113934_window.xul index 3190370fcb6..5390861041e 100644 --- a/docshell/test/chrome/bug113934_window.xul +++ b/docshell/test/chrome/bug113934_window.xul @@ -41,7 +41,7 @@ /** Test for Bug 113934 **/ var doc1 = "data:text/html,This is a test"; - var doc2 = "data:text/html,This is a second test"; + var doc2 = "data:text/html,This is a second test"; $("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 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); } ]]> diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 2aa5c1ed393..473064a4893 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -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);