From 8c0a4e56f8197f45fbad50af161e765bcf4cead0 Mon Sep 17 00:00:00 2001 From: "jst%mozilla.jstenback.com" Date: Wed, 23 Feb 2005 23:31:37 +0000 Subject: [PATCH] Fixing bug 277574. Make sure all modal dialogs, not just the ones that come from DOM calls, bring the requesting tab to focus. r=dveditz@cruzio.com, sr=darin@meer.net git-svn-id: svn://10.0.0.236/trunk@169699 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/Makefile.in | 1 + mozilla/docshell/base/nsDocShell.cpp | 54 +++-- mozilla/dom/src/base/nsGlobalWindow.cpp | 39 +--- .../components/windowwatcher/src/nsPrompt.cpp | 198 ++++++++++++++++-- .../components/windowwatcher/src/nsPrompt.h | 2 +- 5 files changed, 221 insertions(+), 73 deletions(-) diff --git a/mozilla/docshell/base/Makefile.in b/mozilla/docshell/base/Makefile.in index 4e219746a25..647d4845fbc 100644 --- a/mozilla/docshell/base/Makefile.in +++ b/mozilla/docshell/base/Makefile.in @@ -81,6 +81,7 @@ REQUIRES = xpcom \ composer \ commandhandler \ editor \ + windowwatcher \ $(NULL) SDK_XPIDLSRCS = \ diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index d19fb8f9ee6..90a7d135672 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -111,6 +111,7 @@ #include "nsIPrincipal.h" #include "nsIHistoryEntry.h" #include "nsISHistoryListener.h" +#include "nsIWindowWatcher.h" // Pull in various NS_ERROR_* definitions #include "nsIDNSService.h" @@ -391,15 +392,24 @@ NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink) mContentViewer->GetDOMDocument((nsIDOMDocument **) aSink); return *aSink ? NS_OK : NS_NOINTERFACE; } - else if (aIID.Equals(NS_GET_IID(nsIPrompt))) { - nsCOMPtr prompter(do_GetInterface(mTreeOwner)); - if (prompter) { - *aSink = prompter; - NS_ADDREF((nsISupports *) * aSink); - return NS_OK; - } - else - return NS_NOINTERFACE; + else if (aIID.Equals(NS_GET_IID(nsIPrompt)) && + NS_SUCCEEDED(EnsureScriptEnvironment())) { + nsresult rv; + nsCOMPtr wwatch = + do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr window(do_QueryInterface(mScriptGlobal)); + + // Get the an auth prompter for our window so that the parenting + // of the dialogs works as it should when using tabs. + + nsIPrompt *prompt; + rv = wwatch->GetNewPrompter(window, &prompt); + NS_ENSURE_SUCCESS(rv, rv); + + *aSink = prompt; + return NS_OK; } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) { return NS_SUCCEEDED( @@ -684,10 +694,13 @@ nsDocShell::LoadURI(nsIURI * aURI, // it is possible that a parent's onLoadHandler or even self's onLoadHandler is loading // a new page in this child. Check parent's and self's busy flag and if it is set, // we don't want this onLoadHandler load to get in to session history. - PRUint32 parentBusy=BUSY_FLAGS_NONE, selfBusy = BUSY_FLAGS_NONE; + PRUint32 parentBusy = BUSY_FLAGS_NONE; + PRUint32 selfBusy = BUSY_FLAGS_NONE; parentDS->GetBusyFlags(&parentBusy); GetBusyFlags(&selfBusy); - if (((parentBusy & BUSY_FLAGS_BUSY) || (selfBusy & BUSY_FLAGS_BUSY)) && shEntry) { + if (((parentBusy & BUSY_FLAGS_BUSY) || + (selfBusy & BUSY_FLAGS_BUSY)) && + shEntry) { loadType = LOAD_NORMAL_REPLACE; shEntry = nsnull; } @@ -7369,11 +7382,18 @@ nsDocShell::GetAuthPrompt(PRUint32 aPromptReason, nsIAuthPrompt **aResult) return NS_ERROR_NOT_AVAILABLE; // we're either allowing auth, or it's a proxy request - nsCOMPtr authPrompter(do_GetInterface(mTreeOwner)); - if (!authPrompter) - return NS_ERROR_NOT_AVAILABLE; + nsresult rv; + nsCOMPtr wwatch = + do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); - *aResult = authPrompter; - NS_ADDREF(*aResult); - return NS_OK; + rv = EnsureScriptEnvironment(); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr window(do_QueryInterface(mScriptGlobal)); + + // Get the an auth prompter for our window so that the parenting + // of the dialogs works as it should when using tabs. + + return wwatch->GetNewAuthPrompter(window, aResult); } diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index a72a54006a1..98f2a35d199 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -622,7 +622,7 @@ nsGlobalWindow::SetNewDocument(nsIDOMDocument* aDocument, (!isAboutBlank || (isContentWindow && !isSameOrigin)); } - + if (aRemoveEventListeners && mListenerManager) { mListenerManager->RemoveAllListeners(PR_FALSE); mListenerManager = nsnull; @@ -2390,13 +2390,6 @@ nsGlobalWindow::Alert(const nsAString& aString) // the whole time a modal dialog is open. nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE); - if (!DispatchCustomEvent("DOMWillOpenModalDialog")) { - // Someone chose to prevent the default action for this event, - // if so, don't show the dialog after all... - - return NS_OK; - } - // Special handling for alert(null) in JS for backwards // compatibility. @@ -2420,11 +2413,7 @@ nsGlobalWindow::Alert(const nsAString& aString) // pending reflows. EnsureReflowFlushAndPaint(); - nsresult rv = prompter->Alert(title, PromiseFlatString(*str).get()); - - DispatchCustomEvent("DOMModalDialogClosed"); - - return rv; + return prompter->Alert(title, PromiseFlatString(*str).get()); } NS_IMETHODIMP @@ -2438,13 +2427,6 @@ nsGlobalWindow::Confirm(const nsAString& aString, PRBool* aReturn) // the whole time a modal dialog is open. nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE); - if (!DispatchCustomEvent("DOMWillOpenModalDialog")) { - // Someone chose to prevent the default action for this event, - // if so, don't show the dialog after all... - - return NS_OK; - } - *aReturn = PR_FALSE; // Test whether title needs to prefixed with [script] @@ -2463,12 +2445,7 @@ nsGlobalWindow::Confirm(const nsAString& aString, PRBool* aReturn) // pending reflows. EnsureReflowFlushAndPaint(); - nsresult rv = prompter->Confirm(title, PromiseFlatString(aString).get(), - aReturn); - - DispatchCustomEvent("DOMModalDialogClosed"); - - return rv; + return prompter->Confirm(title, PromiseFlatString(aString).get(), aReturn); } NS_IMETHODIMP @@ -2486,13 +2463,6 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial, // the whole time a modal dialog is open. nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE); - if (!DispatchCustomEvent("DOMWillOpenModalDialog")) { - // Someone chose to prevent the default action for this event, - // if so, don't show the dialog after all... - - return NS_OK; - } - PRBool b; nsXPIDLString uniResult; @@ -2515,9 +2485,6 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial, aSavePassword, PromiseFlatString(aInitial).get(), getter_Copies(uniResult), &b); - - DispatchCustomEvent("DOMModalDialogClosed"); - NS_ENSURE_SUCCESS(rv, rv); if (uniResult && b) { diff --git a/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp b/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp index 0626a316b0b..78e37cb6775 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp +++ b/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -40,6 +40,11 @@ #include "nsPrompt.h" #include "nsReadableUtils.h" #include "nsDependentString.h" +#include "nsIDOMDocument.h" +#include "nsIDOMDocumentEvent.h" +#include "nsIDOMEventTarget.h" +#include "nsIDOMEvent.h" +#include "nsIPrivateDOMEvent.h" nsresult @@ -84,7 +89,8 @@ NS_NewAuthPrompter(nsIAuthPrompt **result, nsIDOMWindow *aParent) *result = prompter; // wrap the base prompt in an nsIAuthPromptWrapper, if available // the impl used here persists prompt data and pre-fills the dialogs - nsCOMPtr siPrompt = do_CreateInstance("@mozilla.org/wallet/single-sign-on-prompt;1"); + nsCOMPtr siPrompt = + do_CreateInstance("@mozilla.org/wallet/single-sign-on-prompt;1"); if (siPrompt) { // then single sign-on is installed rv = siPrompt->SetPromptDialogs(prompter); @@ -113,12 +119,89 @@ nsPrompt::Init() //***************************************************************************** // nsPrompt::nsIPrompt -//***************************************************************************** +//***************************************************************************** + +class nsAutoDOMEventDispatcher +{ +public: + nsAutoDOMEventDispatcher(nsIDOMWindow *aWindow); + ~nsAutoDOMEventDispatcher(); + + PRBool DefaultPrevented() + { + return mDefaultPrevented; + } + +protected: + PRBool DispatchCustomEvent(const char *aEventName); + + nsIDOMWindow *mWindow; + PRBool mDefaultPrevented; +}; + +nsAutoDOMEventDispatcher::nsAutoDOMEventDispatcher(nsIDOMWindow *aWindow) + : mWindow(aWindow), + mDefaultPrevented(DispatchCustomEvent("DOMWillOpenModalDialog")) +{ +} + +nsAutoDOMEventDispatcher::~nsAutoDOMEventDispatcher() +{ + if (!mDefaultPrevented) { + DispatchCustomEvent("DOMModalDialogClosed"); + } +} + +PRBool +nsAutoDOMEventDispatcher::DispatchCustomEvent(const char *aEventName) +{ + if (!mWindow) { + return PR_FALSE; + } + + nsCOMPtr domdoc; + mWindow->GetDocument(getter_AddRefs(domdoc)); + + nsCOMPtr docevent(do_QueryInterface(domdoc)); + nsCOMPtr event; + + // Doesn't this seem backwards? Seems like + // nsEventStateManager::DispatchNewEvent() screws up on the + // logic for its prevent default argument... + PRBool preventDefault = PR_FALSE; + + if (docevent) { + docevent->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event)); + + nsCOMPtr privateEvent(do_QueryInterface(event)); + if (privateEvent) { + event->InitEvent(NS_ConvertASCIItoUTF16(aEventName), PR_TRUE, PR_TRUE); + + privateEvent->SetTrusted(PR_TRUE); + + nsCOMPtr target(do_QueryInterface(mWindow)); + + target->DispatchEvent(event, &preventDefault); + + // DispatchEvent() is buggy, it returns the wrong boolean value. + preventDefault = !preventDefault; + } + } + + return preventDefault; +} + NS_IMETHODIMP nsPrompt::Alert(const PRUnichar* dialogTitle, const PRUnichar* text) { + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + return mPromptService->Alert(mParent, dialogTitle, text); } @@ -128,7 +211,14 @@ nsPrompt::AlertCheck(const PRUnichar* dialogTitle, const PRUnichar* checkMsg, PRBool *checkValue) { - return mPromptService->AlertCheck(mParent, dialogTitle, text, checkMsg, checkValue); + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + + return mPromptService->AlertCheck(mParent, dialogTitle, text, checkMsg, + checkValue); } NS_IMETHODIMP @@ -136,6 +226,12 @@ nsPrompt::Confirm(const PRUnichar* dialogTitle, const PRUnichar* text, PRBool *_retval) { + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + return mPromptService->Confirm(mParent, dialogTitle, text, _retval); } @@ -146,7 +242,14 @@ nsPrompt::ConfirmCheck(const PRUnichar* dialogTitle, PRBool *checkValue, PRBool *_retval) { - return mPromptService->ConfirmCheck(mParent, dialogTitle, text, checkMsg, checkValue, _retval); + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + + return mPromptService->ConfirmCheck(mParent, dialogTitle, text, checkMsg, + checkValue, _retval); } NS_IMETHODIMP @@ -160,8 +263,14 @@ nsPrompt::ConfirmEx(const PRUnichar *dialogTitle, PRBool *checkValue, PRInt32 *buttonPressed) { - return mPromptService->ConfirmEx(mParent, dialogTitle, text, - buttonFlags, button0Title, button1Title, button2Title, + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + + return mPromptService->ConfirmEx(mParent, dialogTitle, text, buttonFlags, + button0Title, button1Title, button2Title, checkMsg, checkValue, buttonPressed); } @@ -173,8 +282,14 @@ nsPrompt::Prompt(const PRUnichar *dialogTitle, PRBool *checkValue, PRBool *_retval) { - return mPromptService->Prompt(mParent, dialogTitle, text, answer, - checkMsg, checkValue, _retval); + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + + return mPromptService->Prompt(mParent, dialogTitle, text, answer, checkMsg, + checkValue, _retval); } NS_IMETHODIMP @@ -186,8 +301,16 @@ nsPrompt::PromptUsernameAndPassword(const PRUnichar *dialogTitle, PRBool *checkValue, PRBool *_retval) { - return mPromptService->PromptUsernameAndPassword(mParent, dialogTitle, text, username, password, - checkMsg, checkValue, _retval); + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + + return mPromptService->PromptUsernameAndPassword(mParent, dialogTitle, text, + username, password, + checkMsg, checkValue, + _retval); } NS_IMETHODIMP @@ -198,6 +321,12 @@ nsPrompt::PromptPassword(const PRUnichar *dialogTitle, PRBool *checkValue, PRBool *_retval) { + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + return mPromptService->PromptPassword(mParent, dialogTitle, text, password, checkMsg, checkValue, _retval); } @@ -210,8 +339,14 @@ nsPrompt::Select(const PRUnichar *dialogTitle, PRInt32 *outSelection, PRBool *_retval) { - return mPromptService->Select(mParent, dialogTitle, inMsg, - inCount, inList, outSelection, _retval); + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + + return mPromptService->Select(mParent, dialogTitle, inMsg, inCount, inList, + outSelection, _retval); } //***************************************************************************** @@ -229,11 +364,23 @@ nsPrompt::Prompt(const PRUnichar* dialogTitle, PRUnichar* *result, PRBool *_retval) { + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + // Ignore passwordRealm and savePassword - if (defaultText) + if (defaultText) { *result = ToNewUnicode(nsDependentString(defaultText)); - return mPromptService->Prompt(mParent, dialogTitle, text, - result, nsnull, nsnull, _retval); + + if (!*result) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + return mPromptService->Prompt(mParent, dialogTitle, text, result, nsnull, + nsnull, _retval); } NS_IMETHODIMP @@ -245,9 +392,16 @@ nsPrompt::PromptUsernameAndPassword(const PRUnichar* dialogTitle, PRUnichar* *pwd, PRBool *_retval) { + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + // Ignore passwordRealm and savePassword return mPromptService->PromptUsernameAndPassword(mParent, dialogTitle, text, - user, pwd, nsnull, nsnull, _retval); + user, pwd, nsnull, nsnull, + _retval); } NS_IMETHODIMP @@ -258,7 +412,13 @@ nsPrompt::PromptPassword(const PRUnichar* dialogTitle, PRUnichar* *pwd, PRBool *_retval) { + nsAutoDOMEventDispatcher autoDOMEventDispatcher(mParent); + + if (autoDOMEventDispatcher.DefaultPrevented()) { + return NS_OK; + } + // Ignore passwordRealm and savePassword - return mPromptService->PromptPassword(mParent, dialogTitle, text, - pwd, nsnull, nsnull, _retval); + return mPromptService->PromptPassword(mParent, dialogTitle, text, pwd, + nsnull, nsnull, _retval); } diff --git a/mozilla/embedding/components/windowwatcher/src/nsPrompt.h b/mozilla/embedding/components/windowwatcher/src/nsPrompt.h index aecb8e06de7..28e32bd5087 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsPrompt.h +++ b/mozilla/embedding/components/windowwatcher/src/nsPrompt.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 *