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
Родитель 78c5ff8572
Коммит a46b3fe9f2
2 изменённых файлов: 20 добавлений и 8 удалений

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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);