From de57879100f9b1dcc30fbe1445e8c2ee984fdcb8 Mon Sep 17 00:00:00 2001 From: "jst%mozilla.jstenback.com" Date: Fri, 14 Jul 2006 01:19:33 +0000 Subject: [PATCH] Fixing bug 334891. Ignore close calls on windows that have a modal dialog parented at them. r=dveditz@cruzio.com, sr=bzbarsky@mit.edu, a=dbaron@mozilla.com git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_BRANCH@202108 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/dom/public/base/nsPIDOMWindow.h | 11 ++- mozilla/dom/src/base/nsGlobalWindow.cpp | 59 ++++++++++++++- mozilla/dom/src/base/nsGlobalWindow.h | 8 +- .../components/windowwatcher/src/nsPrompt.cpp | 73 +++++++++++-------- 4 files changed, 115 insertions(+), 36 deletions(-) diff --git a/mozilla/dom/public/base/nsPIDOMWindow.h b/mozilla/dom/public/base/nsPIDOMWindow.h index 7406696a237..a40c9895b9b 100644 --- a/mozilla/dom/public/base/nsPIDOMWindow.h +++ b/mozilla/dom/public/base/nsPIDOMWindow.h @@ -333,8 +333,8 @@ protected: }; #define NS_PIDOMWINDOW_MOZILLA_1_8_BRANCH_IID \ -{ 0x7bf31d9e, 0xd17b, 0x47dc, \ - { 0xa6, 0xe4, 0x5f, 0xae, 0x29, 0x94, 0xf1, 0x07 } } +{ 0xa9b7f235, 0x4c98, 0x4257, \ + { 0xb1, 0x1a, 0xbe, 0x53, 0x39, 0x69, 0xdf, 0x2a } } class nsPIDOMWindow_MOZILLA_1_8_BRANCH : public nsPIDOMWindow { @@ -357,6 +357,13 @@ public: */ virtual nsresult FireDelayedDOMEvents() = 0; + /** + * Callback for notifying a window about a modal dialog being + * opened/closed with the window as a parent. + */ + virtual void EnterModalState() = 0; + virtual void LeaveModalState() = 0; + protected: nsPIDOMWindow_MOZILLA_1_8_BRANCH(nsPIDOMWindow *aOuterWindow) : nsPIDOMWindow(aOuterWindow) diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 41ee2a5ab59..60baa83efd7 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -315,6 +315,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) mHavePendingClose(PR_FALSE), mHadOriginalOpener(PR_FALSE), mIsPopupSpam(PR_FALSE), + mModalStateDepth(0), mArguments(nsnull), mGlobalObjectOwner(nsnull), mDocShell(nsnull), @@ -4476,9 +4477,10 @@ nsGlobalWindow::Close() { FORWARD_TO_OUTER(Close, (), NS_ERROR_NOT_INITIALIZED); - if (IsFrame() || !mDocShell) { - // window.close() is called on a frame in a frameset, or on a - // window that's already closed. Ignore such calls. + if (IsFrame() || !mDocShell || IsInModalState()) { + // window.close() is called on a frame in a frameset, on a window + // that's already closed, or on a window for which there's + // currently a modal dialog open. Ignore such calls. return NS_OK; } @@ -4680,6 +4682,57 @@ nsGlobalWindow::ReallyCloseWindow() } } +void +nsGlobalWindow::EnterModalState() +{ + nsCOMPtr top; + GetTop(getter_AddRefs(top)); + + if (!top) { + NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?"); + + return; + } + + NS_STATIC_CAST(nsGlobalWindow *, + NS_STATIC_CAST(nsIDOMWindow *, + top.get()))->mModalStateDepth++; +} + +void +nsGlobalWindow::LeaveModalState() +{ + nsCOMPtr top; + GetTop(getter_AddRefs(top)); + + if (!top) { + NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?"); + + return; + } + + NS_STATIC_CAST(nsGlobalWindow *, + NS_STATIC_CAST(nsIDOMWindow *, + top.get()))->mModalStateDepth--; +} + +PRBool +nsGlobalWindow::IsInModalState() +{ + nsCOMPtr top; + GetTop(getter_AddRefs(top)); + + if (!top) { + NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?"); + + return PR_FALSE; + } + + return NS_STATIC_CAST(nsGlobalWindow *, + NS_STATIC_CAST(nsIDOMWindow *, + top.get()))->mModalStateDepth != 0; +} + NS_IMETHODIMP nsGlobalWindow::GetFrameElement(nsIDOMElement** aFrameElement) { diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index 49de38b0127..19a44a900c5 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -244,7 +244,9 @@ public: virtual NS_HIDDEN_(nsresult) FireDelayedDOMEvents(); - + virtual NS_HIDDEN_(void) EnterModalState(); + virtual NS_HIDDEN_(void) LeaveModalState(); + // nsIDOMViewCSS NS_DECL_NSIDOMVIEWCSS @@ -471,6 +473,8 @@ protected: mIsFrozen = PR_FALSE; } + PRBool IsInModalState(); + // When adding new member variables, be careful not to create cycles // through JavaScript. If there is any chance that a member variable // could own objects that are implemented in JavaScript, then those @@ -498,6 +502,8 @@ protected: PRPackedBool mHadOriginalOpener : 1; PRPackedBool mIsPopupSpam : 1; + PRUint32 mModalStateDepth; + nsCOMPtr mContext; nsCOMPtr mOpener; nsCOMPtr mControllers; diff --git a/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp b/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp index a1f44e7c550..36a34835c1e 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp +++ b/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp @@ -130,11 +130,11 @@ nsPrompt::Init() // nsPrompt::nsIPrompt //***************************************************************************** -class nsAutoDOMEventDispatcher +class nsAutoWindowStateHelper { public: - nsAutoDOMEventDispatcher(nsIDOMWindow *aWindow); - ~nsAutoDOMEventDispatcher(); + nsAutoWindowStateHelper(nsIDOMWindow *aWindow); + ~nsAutoWindowStateHelper(); PRBool DefaultEnabled() { @@ -148,21 +148,34 @@ protected: PRBool mDefaultEnabled; }; -nsAutoDOMEventDispatcher::nsAutoDOMEventDispatcher(nsIDOMWindow *aWindow) +nsAutoWindowStateHelper::nsAutoWindowStateHelper(nsIDOMWindow *aWindow) : mWindow(aWindow), mDefaultEnabled(DispatchCustomEvent("DOMWillOpenModalDialog")) { + nsCOMPtr window = + do_QueryInterface(aWindow); + + if (window) { + window->EnterModalState(); + } } -nsAutoDOMEventDispatcher::~nsAutoDOMEventDispatcher() +nsAutoWindowStateHelper::~nsAutoWindowStateHelper() { + nsCOMPtr window = + do_QueryInterface(mWindow); + + if (window) { + window->LeaveModalState(); + } + if (mDefaultEnabled) { DispatchCustomEvent("DOMModalDialogClosed"); } } PRBool -nsAutoDOMEventDispatcher::DispatchCustomEvent(const char *aEventName) +nsAutoWindowStateHelper::DispatchCustomEvent(const char *aEventName) { if (!mWindow) { return PR_TRUE; @@ -208,9 +221,9 @@ NS_IMETHODIMP nsPrompt::Alert(const PRUnichar* dialogTitle, const PRUnichar* text) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -223,9 +236,9 @@ nsPrompt::AlertCheck(const PRUnichar* dialogTitle, const PRUnichar* checkMsg, PRBool *checkValue) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -238,9 +251,9 @@ nsPrompt::Confirm(const PRUnichar* dialogTitle, const PRUnichar* text, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -254,9 +267,9 @@ nsPrompt::ConfirmCheck(const PRUnichar* dialogTitle, PRBool *checkValue, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -275,9 +288,9 @@ nsPrompt::ConfirmEx(const PRUnichar *dialogTitle, PRBool *checkValue, PRInt32 *buttonPressed) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -294,9 +307,9 @@ nsPrompt::Prompt(const PRUnichar *dialogTitle, PRBool *checkValue, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -313,9 +326,9 @@ nsPrompt::PromptUsernameAndPassword(const PRUnichar *dialogTitle, PRBool *checkValue, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -333,9 +346,9 @@ nsPrompt::PromptPassword(const PRUnichar *dialogTitle, PRBool *checkValue, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -351,9 +364,9 @@ nsPrompt::Select(const PRUnichar *dialogTitle, PRInt32 *outSelection, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -376,9 +389,9 @@ nsPrompt::Prompt(const PRUnichar* dialogTitle, PRUnichar* *result, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -404,9 +417,9 @@ nsPrompt::PromptUsernameAndPassword(const PRUnichar* dialogTitle, PRUnichar* *pwd, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; } @@ -424,9 +437,9 @@ nsPrompt::PromptPassword(const PRUnichar* dialogTitle, PRUnichar* *pwd, PRBool *_retval) { - nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + nsAutoWindowStateHelper windowStateHelper(mParent); - if (!autoDOMEventDispatcher.DefaultEnabled()) { + if (!windowStateHelper.DefaultEnabled()) { return NS_OK; }