mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Fixing bug 334891. Prevent window.close() from closing the window if there's a modal dialog parented at the window. r=dveditz@cruzio.com, sr=bzbarsky@mit.edu
This commit is contained in:
parent
dd15a518df
commit
b271739439
@ -400,14 +400,22 @@ public:
|
||||
|
||||
virtual void EnsureSizeUpToDate() = 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:
|
||||
// The nsPIDOMWindow constructor. The aOuterWindow argument should
|
||||
// be null if and only if the created window itself is an outer
|
||||
// window. In all other cases aOuterWindow should be the outer
|
||||
// window for the inner window that is being created.
|
||||
nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
|
||||
: mFrameElement(nsnull), mDocShell(nsnull), mRunningTimeout(nsnull),
|
||||
mMutationBits(0), mIsDocumentLoaded(PR_FALSE),
|
||||
: mFrameElement(nsnull), mDocShell(nsnull), mModalStateDepth(0),
|
||||
mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(PR_FALSE),
|
||||
mIsHandlingResizeEvent(PR_FALSE), mIsInnerWindow(aOuterWindow != nsnull),
|
||||
mInnerWindow(nsnull), mOuterWindow(aOuterWindow)
|
||||
{
|
||||
@ -423,6 +431,8 @@ protected:
|
||||
nsIDOMElement *mFrameElement; // weak
|
||||
nsIDocShell *mDocShell; // Weak Reference
|
||||
|
||||
PRUint32 mModalStateDepth;
|
||||
|
||||
// These variables are only used on inner windows.
|
||||
nsTimeout *mRunningTimeout;
|
||||
|
||||
|
@ -3387,7 +3387,8 @@ nsGlobalWindow::Confirm(const nsAString& aString, PRBool* aReturn)
|
||||
nsAutoString title;
|
||||
MakeScriptDialogTitle(EmptyString(), title);
|
||||
|
||||
return prompter->Confirm(title.get(), PromiseFlatString(aString).get(), aReturn);
|
||||
return prompter->Confirm(title.get(),
|
||||
PromiseFlatString(aString).get(), aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -4427,9 +4428,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;
|
||||
}
|
||||
@ -4605,6 +4607,57 @@ nsGlobalWindow::ReallyCloseWindow()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::EnterModalState()
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> 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<nsIDOMWindow> 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<nsIDOMWindow> 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)
|
||||
{
|
||||
|
@ -266,6 +266,9 @@ public:
|
||||
PRBool aOriginalOpener);
|
||||
virtual NS_HIDDEN_(void) EnsureSizeUpToDate();
|
||||
|
||||
virtual NS_HIDDEN_(void) EnterModalState();
|
||||
virtual NS_HIDDEN_(void) LeaveModalState();
|
||||
|
||||
// nsIDOMViewCSS
|
||||
NS_DECL_NSIDOMVIEWCSS
|
||||
|
||||
@ -505,6 +508,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
|
||||
|
@ -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,32 @@ protected:
|
||||
PRBool mDefaultEnabled;
|
||||
};
|
||||
|
||||
nsAutoDOMEventDispatcher::nsAutoDOMEventDispatcher(nsIDOMWindow *aWindow)
|
||||
nsAutoWindowStateHelper::nsAutoWindowStateHelper(nsIDOMWindow *aWindow)
|
||||
: mWindow(aWindow),
|
||||
mDefaultEnabled(DispatchCustomEvent("DOMWillOpenModalDialog"))
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
|
||||
|
||||
if (window) {
|
||||
window->EnterModalState();
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoDOMEventDispatcher::~nsAutoDOMEventDispatcher()
|
||||
nsAutoWindowStateHelper::~nsAutoWindowStateHelper()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> 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 +219,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 +234,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 +249,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 +265,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 +286,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 +305,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 +324,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 +344,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 +362,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 +387,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 +415,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 +435,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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user