From 70aa75bb283566c1749dbb1fc03994a5c14fbca8 Mon Sep 17 00:00:00 2001 From: "joki%netscape.com" Date: Tue, 15 Feb 2000 22:55:36 +0000 Subject: [PATCH] Fix bug 4167. Fire unload event before all data is gone to allow action during event handlers. r:travis git-svn-id: svn://10.0.0.236/trunk@60953 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/nsWebShell.cpp | 69 ++++++++++++++++++++------- mozilla/webshell/public/nsIWebShell.h | 5 ++ mozilla/webshell/src/nsWebShell.cpp | 69 ++++++++++++++++++++------- 3 files changed, 109 insertions(+), 34 deletions(-) diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index daf3a2395f2..a07aef51587 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -283,6 +283,7 @@ public: NS_IMETHOD EndLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, nsresult aStatus); NS_IMETHOD GetHistoryState(nsISupports** aLayoutHistoryState); NS_IMETHOD SetHistoryState(nsISupports* aLayoutHistoryState); + NS_IMETHOD FireUnloadEvent(void); // nsIWebShellServices NS_IMETHOD LoadDocument(const char* aURL, @@ -387,6 +388,7 @@ protected: nsVoidArray mHistory; PRInt32 mHistoryIndex; + PRBool mFiredUnloadEvent; nsIGlobalHistory* mHistoryService; nsISessionHistory * mSHist; @@ -409,6 +411,7 @@ protected: nsISupports* mHistoryState; // Weak reference. Session history owns this. + nsresult FireUnloadForChildren(); void ReleaseChildren(); NS_IMETHOD DestroyChildren(); nsresult DoLoadURL(nsIURI * aUri, @@ -585,6 +588,7 @@ nsWebShell::nsWebShell() : nsDocShell() mViewSource=PR_FALSE; mHistoryService = nsnull; mHistoryState = nsnull; + mFiredUnloadEvent = PR_FALSE; } nsWebShell::~nsWebShell() @@ -681,6 +685,51 @@ nsWebShell::ReleaseChildren() mChildren.Clear(); } +nsresult +nsWebShell::FireUnloadForChildren() +{ + nsresult rv = NS_OK; + + PRInt32 i, n = mChildren.Count(); + for (i = 0; i < n; i++) { + nsIDocShell* shell = (nsIDocShell*) mChildren.ElementAt(i); + nsCOMPtr webShell(do_QueryInterface(shell)); + rv = webShell->FireUnloadEvent(); + } + + return rv; +} + +NS_IMETHODIMP +nsWebShell::FireUnloadEvent() +{ + nsresult rv = NS_OK; + + if (mScriptGlobal) { + nsIDocumentViewer* docViewer; + if (mContentViewer && NS_SUCCEEDED(mContentViewer->QueryInterface(kIDocumentViewerIID, (void**)&docViewer))) { + nsIPresContext *presContext; + if (NS_SUCCEEDED(docViewer->GetPresContext(presContext))) { + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event; + event.eventStructType = NS_EVENT; + event.message = NS_PAGE_UNLOAD; + rv = mScriptGlobal->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + + NS_RELEASE(presContext); + } + NS_RELEASE(docViewer); + } + } + + //Fire child unloads now while our data is intact. + rv = FireUnloadForChildren(); + + mFiredUnloadEvent = PR_TRUE; + + return rv; +} + NS_IMETHODIMP nsWebShell::DestroyChildren() { @@ -3583,23 +3632,9 @@ NS_IMETHODIMP nsWebShell::Destroy() { nsresult rv = NS_OK; - //Fire unload event before we blow anything away. - if (mScriptGlobal) { - nsIDocumentViewer* docViewer; - if (nsnull != mContentViewer && - NS_OK == mContentViewer->QueryInterface(kIDocumentViewerIID, (void**)&docViewer)) { - nsIPresContext *presContext; - if (NS_OK == docViewer->GetPresContext(presContext)) { - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event; - event.eventStructType = NS_EVENT; - event.message = NS_PAGE_UNLOAD; - rv = mScriptGlobal->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - - NS_RELEASE(presContext); - } - NS_RELEASE(docViewer); - } + if (!mFiredUnloadEvent) { + //Fire unload event before we blow anything away. + rv = FireUnloadEvent(); } // Stop any URLs that are currently being loaded... diff --git a/mozilla/webshell/public/nsIWebShell.h b/mozilla/webshell/public/nsIWebShell.h index e52b81cbd01..45295d8dde4 100644 --- a/mozilla/webshell/public/nsIWebShell.h +++ b/mozilla/webshell/public/nsIWebShell.h @@ -380,6 +380,11 @@ public: */ NS_IMETHOD GetHistoryState(nsISupports** aLayoutHistoryState) = 0; NS_IMETHOD SetHistoryState(nsISupports* aLayoutHistoryState) = 0; + + /** + * Notify children to fire unload events before root data gone + */ + NS_IMETHOD FireUnloadEvent(void) = 0; }; extern "C" NS_WEB nsresult diff --git a/mozilla/webshell/src/nsWebShell.cpp b/mozilla/webshell/src/nsWebShell.cpp index daf3a2395f2..a07aef51587 100644 --- a/mozilla/webshell/src/nsWebShell.cpp +++ b/mozilla/webshell/src/nsWebShell.cpp @@ -283,6 +283,7 @@ public: NS_IMETHOD EndLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, nsresult aStatus); NS_IMETHOD GetHistoryState(nsISupports** aLayoutHistoryState); NS_IMETHOD SetHistoryState(nsISupports* aLayoutHistoryState); + NS_IMETHOD FireUnloadEvent(void); // nsIWebShellServices NS_IMETHOD LoadDocument(const char* aURL, @@ -387,6 +388,7 @@ protected: nsVoidArray mHistory; PRInt32 mHistoryIndex; + PRBool mFiredUnloadEvent; nsIGlobalHistory* mHistoryService; nsISessionHistory * mSHist; @@ -409,6 +411,7 @@ protected: nsISupports* mHistoryState; // Weak reference. Session history owns this. + nsresult FireUnloadForChildren(); void ReleaseChildren(); NS_IMETHOD DestroyChildren(); nsresult DoLoadURL(nsIURI * aUri, @@ -585,6 +588,7 @@ nsWebShell::nsWebShell() : nsDocShell() mViewSource=PR_FALSE; mHistoryService = nsnull; mHistoryState = nsnull; + mFiredUnloadEvent = PR_FALSE; } nsWebShell::~nsWebShell() @@ -681,6 +685,51 @@ nsWebShell::ReleaseChildren() mChildren.Clear(); } +nsresult +nsWebShell::FireUnloadForChildren() +{ + nsresult rv = NS_OK; + + PRInt32 i, n = mChildren.Count(); + for (i = 0; i < n; i++) { + nsIDocShell* shell = (nsIDocShell*) mChildren.ElementAt(i); + nsCOMPtr webShell(do_QueryInterface(shell)); + rv = webShell->FireUnloadEvent(); + } + + return rv; +} + +NS_IMETHODIMP +nsWebShell::FireUnloadEvent() +{ + nsresult rv = NS_OK; + + if (mScriptGlobal) { + nsIDocumentViewer* docViewer; + if (mContentViewer && NS_SUCCEEDED(mContentViewer->QueryInterface(kIDocumentViewerIID, (void**)&docViewer))) { + nsIPresContext *presContext; + if (NS_SUCCEEDED(docViewer->GetPresContext(presContext))) { + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event; + event.eventStructType = NS_EVENT; + event.message = NS_PAGE_UNLOAD; + rv = mScriptGlobal->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + + NS_RELEASE(presContext); + } + NS_RELEASE(docViewer); + } + } + + //Fire child unloads now while our data is intact. + rv = FireUnloadForChildren(); + + mFiredUnloadEvent = PR_TRUE; + + return rv; +} + NS_IMETHODIMP nsWebShell::DestroyChildren() { @@ -3583,23 +3632,9 @@ NS_IMETHODIMP nsWebShell::Destroy() { nsresult rv = NS_OK; - //Fire unload event before we blow anything away. - if (mScriptGlobal) { - nsIDocumentViewer* docViewer; - if (nsnull != mContentViewer && - NS_OK == mContentViewer->QueryInterface(kIDocumentViewerIID, (void**)&docViewer)) { - nsIPresContext *presContext; - if (NS_OK == docViewer->GetPresContext(presContext)) { - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event; - event.eventStructType = NS_EVENT; - event.message = NS_PAGE_UNLOAD; - rv = mScriptGlobal->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - - NS_RELEASE(presContext); - } - NS_RELEASE(docViewer); - } + if (!mFiredUnloadEvent) { + //Fire unload event before we blow anything away. + rv = FireUnloadEvent(); } // Stop any URLs that are currently being loaded...