Bug 841312 - Replace the scripted closing unblocker termination function with an runnable. r=bz

The main idea behind this thing seems to be that we don't want script to quickly
close the window before the user has time to read the notification. Given the
fuzziness of the constraint here, I think we can (and maybe even should) unblock
a little bit later in the event loop, rather than immediately after the script
terminates.

Note that, due to modal dialogs and their event loop spinning shenanigans, we
want to do this only when the stack frame is popped.
This commit is contained in:
Bobby Holley 2013-05-21 11:45:56 -06:00
parent 42a70cf2d5
commit 83b50e7905
2 changed files with 20 additions and 8 deletions

View File

@ -9726,15 +9726,25 @@ nsGlobalWindow::GetParentInternal()
return NULL;
}
// static
void
nsGlobalWindow::CloseBlockScriptTerminationFunc(nsISupports *aRef)
nsGlobalWindow::UnblockScriptedClosing()
{
nsGlobalWindow* pwin = static_cast<nsGlobalWindow*>
(static_cast<nsPIDOMWindow*>(aRef));
pwin->mBlockScriptedClosingFlag = false;
mBlockScriptedClosingFlag = false;
}
class AutoUnblockScriptClosing
{
private:
nsRefPtr<nsGlobalWindow> mWin;
public:
AutoUnblockScriptClosing(nsGlobalWindow *aWin) : mWin(aWin) {};
~AutoUnblockScriptClosing()
{
void (nsGlobalWindow::*run)() = &nsGlobalWindow::UnblockScriptedClosing;
NS_DispatchToCurrentThread(NS_NewRunnableMethod(mWin, run));
};
};
nsresult
nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
const nsAString& aOptions, bool aDialog,
@ -9764,6 +9774,8 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
NS_PRECONDITION(!aJSCallerContext || !aCalledNoScript,
"Shouldn't have caller context when called noscript");
mozilla::Maybe<AutoUnblockScriptClosing> closeUnblocker;
// Calls to window.open from script should navigate.
MOZ_ASSERT(aCalledNoScript || aNavigate);
@ -9825,8 +9837,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
// so that whatever popup blocker UI the app has will be visible.
if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) {
mBlockScriptedClosingFlag = true;
mContext->SetTerminationFunction(CloseBlockScriptTerminationFunc,
this);
closeUnblocker.construct(this);
}
}

View File

@ -580,11 +580,12 @@ public:
nsresult Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData);
void UnblockScriptedClosing();
static void Init();
static void ShutDown();
static void CleanupCachedXBLHandlers(nsGlobalWindow* aWindow);
static bool IsCallerChrome();
static void CloseBlockScriptTerminationFunc(nsISupports *aRef);
static void RunPendingTimeoutsRecursive(nsGlobalWindow *aTopWindow,
nsGlobalWindow *aWindow);