Skip to content

Commit

Permalink
Bug 621764 - tab-modal prompt in Gmail eventually triggers slow-scrip…
Browse files Browse the repository at this point in the history
…t dialog for nsPrompter.js. r=mrbkap, sr=jst, a=blocker
  • Loading branch information
dolske committed Feb 2, 2011
1 parent b9df73a commit dcd47ce
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 21 deletions.
18 changes: 17 additions & 1 deletion dom/base/nsDOMWindowUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1413,7 +1413,23 @@ nsDOMWindowUtils::EnterModalState()
NS_IMETHODIMP
nsDOMWindowUtils::LeaveModalState()
{
mWindow->LeaveModalState();
mWindow->LeaveModalState(nsnull);
return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::EnterModalStateWithWindow(nsIDOMWindow **aWindow)
{
*aWindow = mWindow->EnterModalState();
NS_IF_ADDREF(*aWindow);
return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::LeaveModalStateWithWindow(nsIDOMWindow *aWindow)
{
NS_ENSURE_ARG_POINTER(aWindow);
mWindow->LeaveModalState(aWindow);
return NS_OK;
}

Expand Down
29 changes: 24 additions & 5 deletions dom/base/nsGlobalWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5063,7 +5063,7 @@ nsGlobalWindow::Print()

EnterModalState();
webBrowserPrint->Print(printSettings, nsnull);
LeaveModalState();
LeaveModalState(nsnull);

PRBool savePrintSettings =
nsContentUtils::GetBoolPref("print.save_print_settings", PR_FALSE);
Expand Down Expand Up @@ -6268,15 +6268,15 @@ nsGlobalWindow::ReallyCloseWindow()
}
}

void
nsIDOMWindow *
nsGlobalWindow::EnterModalState()
{
nsGlobalWindow* topWin = GetTop();

if (!topWin) {
NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");

return;
return nsnull;
}

// If there is an active ESM in this window, clear it. Otherwise, this can
Expand Down Expand Up @@ -6311,9 +6311,20 @@ nsGlobalWindow::EnterModalState()
}
topWin->mModalStateDepth++;

JSContext *cx = nsContentUtils::GetCurrentJSContext();

nsCOMPtr<nsIDOMWindow> callerWin;
nsIScriptContext *scx;
if (cx && (scx = GetScriptContextFromJSContext(cx))) {
scx->EnterModalState();
callerWin = do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
}

if (mContext) {
mContext->EnterModalState();
}

return callerWin;
}

// static
Expand Down Expand Up @@ -6387,7 +6398,7 @@ class nsPendingTimeoutRunner : public nsRunnable
};

void
nsGlobalWindow::LeaveModalState()
nsGlobalWindow::LeaveModalState(nsIDOMWindow *aCallerWin)
{
nsGlobalWindow *topWin = GetTop();

Expand All @@ -6411,6 +6422,14 @@ nsGlobalWindow::LeaveModalState()
}
}

JSContext *cx = nsContentUtils::GetCurrentJSContext();

if (aCallerWin) {
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aCallerWin));
nsIScriptContext *scx = sgo->GetContext();
scx->LeaveModalState();
}

if (mContext) {
mContext->LeaveModalState();
}
Expand Down Expand Up @@ -6762,7 +6781,7 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
GetPrincipal(), // aCalleePrincipal
nsnull, // aJSCallerContext
getter_AddRefs(dlgWin));
LeaveModalState();
LeaveModalState(nsnull);

NS_ENSURE_SUCCESS(rv, rv);

Expand Down
4 changes: 2 additions & 2 deletions dom/base/nsGlobalWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ class nsGlobalWindow : public nsPIDOMWindow,
PRBool aOriginalOpener);
virtual NS_HIDDEN_(void) EnsureSizeUpToDate();

virtual NS_HIDDEN_(void) EnterModalState();
virtual NS_HIDDEN_(void) LeaveModalState();
virtual NS_HIDDEN_(nsIDOMWindow *) EnterModalState();
virtual NS_HIDDEN_(void) LeaveModalState(nsIDOMWindow *aWindow);

virtual NS_HIDDEN_(PRBool) CanClose();
virtual NS_HIDDEN_(nsresult) ForceClose();
Expand Down
4 changes: 2 additions & 2 deletions dom/base/nsPIDOMWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ class nsPIDOMWindow : public nsIDOMWindowInternal
* 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;
virtual nsIDOMWindow *EnterModalState() = 0;
virtual void LeaveModalState(nsIDOMWindow *) = 0;

virtual PRBool CanClose() = 0;
virtual nsresult ForceClose() = 0;
Expand Down
21 changes: 17 additions & 4 deletions dom/interfaces/base/nsIDOMWindowUtils.idl
Original file line number Diff line number Diff line change
Expand Up @@ -768,18 +768,18 @@ interface nsIDOMWindowUtils : nsISupports {
* Put the window into a state where scripts are frozen and events
* suppressed, for use when the window has launched a modal prompt.
*/
void enterModalState();
[noscript] void enterModalState();

/**
* Resume normal window state, where scripts can run and events are
* delivered.
*/
void leaveModalState();
[noscript] void leaveModalState();

/**
* Is the window is in a modal state? [See enterModalState()]
*/
boolean isInModalState();
[noscript] boolean isInModalState();

/**
* Suspend/resume timeouts on this window and its descendant windows.
Expand Down Expand Up @@ -824,7 +824,7 @@ interface nsIDOMWindowUtils : nsISupports {

typedef unsigned long long nsViewID;

[scriptable, uuid(3a0334aa-b9cc-4b32-9b6c-599cd4e40d5b)]
[scriptable, uuid(526d22ab-4997-8666-53f6-38c7f93e77a5)]
interface nsIDOMWindowUtils_MOZILLA_2_0_BRANCH : nsISupports {
/**
* Get the type of the currently focused html input, if any.
Expand All @@ -837,4 +837,17 @@ interface nsIDOMWindowUtils_MOZILLA_2_0_BRANCH : nsISupports {
* element of the document is returned.
*/
nsIDOMElement findElementWithViewId(in nsViewID aId);

/**
* Same as enterModalState, but returns the window associated with the
* current JS context.
*/
nsIDOMWindow enterModalStateWithWindow();

/**
* Same as leaveModalState, but takes a window associated with the active
* context when enterModalStateWithWindow was called. The currently context
* might be different at the moment (see bug 621764).
*/
void leaveModalStateWithWindow(in nsIDOMWindow aWindow);
};
6 changes: 3 additions & 3 deletions dom/tests/mochitest/bugs/test_bug61098.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
// abusive pages.
var winUtils = this.domWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
winUtils.enterModalState();
winUtils.leaveModalState();
.getInterface(Ci.nsIDOMWindowUtils_MOZILLA_2_0_BRANCH);
var w = winUtils.enterModalStateWithWindow();
winUtils.leaveModalStateWithWindow(w);
},

alert: function(aDialogTitle, aText)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ nsAutoWindowStateHelper::~nsAutoWindowStateHelper()
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mWindow));

if (window) {
window->LeaveModalState();
window->LeaveModalState(nsnull);
}

if (mDefaultEnabled) {
Expand Down
6 changes: 3 additions & 3 deletions toolkit/components/prompts/src/nsPrompter.js
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,8 @@ function openTabPrompt(domWin, tabPrompt, args) {
PromptUtils.fireDialogEvent(domWin, "DOMWillOpenModalDialog");

let winUtils = domWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
winUtils.enterModalState();
.getInterface(Ci.nsIDOMWindowUtils_MOZILLA_2_0_BRANCH);
let callerWin = winUtils.enterModalStateWithWindow();

// We provide a callback so the prompt can close itself. We don't want to
// wait for this event loop to return... Otherwise the presence of other
Expand All @@ -435,7 +435,7 @@ function openTabPrompt(domWin, tabPrompt, args) {
if (newPrompt)
tabPrompt.removePrompt(newPrompt);

winUtils.leaveModalState();
winUtils.leaveModalStateWithWindow(callerWin);

PromptUtils.fireDialogEvent(domWin, "DOMModalDialogClosed");

Expand Down

0 comments on commit dcd47ce

Please sign in to comment.