зеркало из https://github.com/mozilla/gecko-dev.git
Block window.close() calls on a window which just had a popup blocked. This
allows the popup notification to actually be visible to the user. Bug 297980, patch by Joerg Bornemann <jobor@gmx.de>, r=bzbarsky, sr=jst
This commit is contained in:
Родитель
724ccdb167
Коммит
6a2e7a2685
|
@ -355,6 +355,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
|||
mHavePendingClose(PR_FALSE),
|
||||
mHadOriginalOpener(PR_FALSE),
|
||||
mIsPopupSpam(PR_FALSE),
|
||||
mBlockScriptedClosingFlag(PR_FALSE),
|
||||
mFireOfflineStatusChangeEventOnThaw(PR_FALSE),
|
||||
mGlobalObjectOwner(nsnull),
|
||||
mTimeouts(nsnull),
|
||||
|
@ -4316,6 +4317,7 @@ nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
|
|||
PR_FALSE, // aDoJSFixups
|
||||
nsnull, nsnull, // No args
|
||||
GetPrincipal(), // aCalleePrincipal
|
||||
nsnull, // aJSCallerContext
|
||||
_retval);
|
||||
}
|
||||
|
||||
|
@ -4366,6 +4368,7 @@ nsGlobalWindow::Open(nsIDOMWindow **_retval)
|
|||
PR_TRUE, // aDoJSFixups
|
||||
nsnull, nsnull, // No args
|
||||
GetPrincipal(), // aCalleePrincipal
|
||||
cx, // aJSCallerContext
|
||||
_retval);
|
||||
}
|
||||
|
||||
|
@ -4382,6 +4385,7 @@ nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName,
|
|||
PR_FALSE, // aDoJSFixups
|
||||
nsnull, aExtraArgument, // Arguments
|
||||
GetPrincipal(), // aCalleePrincipal
|
||||
nsnull, // aJSCallerContext
|
||||
_retval);
|
||||
}
|
||||
|
||||
|
@ -4440,6 +4444,7 @@ nsGlobalWindow::OpenDialog(nsIDOMWindow** _retval)
|
|||
PR_FALSE, // aDoJSFixups
|
||||
argvArray, nsnull, // Arguments
|
||||
GetPrincipal(), // aCalleePrincipal
|
||||
cx, // aJSCallerContext
|
||||
_retval);
|
||||
}
|
||||
|
||||
|
@ -4491,6 +4496,14 @@ nsGlobalWindow::Close()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mBlockScriptedClosingFlag)
|
||||
{
|
||||
// A script's popup has been blocked and we don't want
|
||||
// the window to be closed directly after this event,
|
||||
// so the user can see that there was a blocked popup.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Don't allow scripts from content to close windows
|
||||
// that were not opened by script
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -5941,6 +5954,15 @@ nsGlobalWindow::GetParentInternal()
|
|||
return parentInternal;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsGlobalWindow::CloseBlockScriptTerminationFunc(nsISupports *aRef)
|
||||
{
|
||||
nsGlobalWindow* pwin = NS_STATIC_CAST(nsGlobalWindow*,
|
||||
NS_STATIC_CAST(nsPIDOMWindow*, aRef));
|
||||
pwin->mBlockScriptedClosingFlag = PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
||||
const nsAString& aOptions, PRBool aDialog,
|
||||
|
@ -5948,12 +5970,13 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
nsIArray *argv,
|
||||
nsISupports *aExtraArgument,
|
||||
nsIPrincipal *aCalleePrincipal,
|
||||
JSContext *aJSCallerContext,
|
||||
nsIDOMWindow **aReturn)
|
||||
{
|
||||
FORWARD_TO_OUTER(OpenInternal, (aUrl, aName, aOptions, aDialog,
|
||||
aCalledNoScript, aDoJSFixups,
|
||||
argv, aExtraArgument, aCalleePrincipal,
|
||||
aReturn),
|
||||
aJSCallerContext, aReturn),
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -5967,6 +5990,8 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
"Can't pass JS args when called via the noscript methods");
|
||||
NS_PRECONDITION(!aDoJSFixups || !aCalledNoScript,
|
||||
"JS fixups should not be done when called noscript");
|
||||
NS_PRECONDITION(!aJSCallerContext || !aCalledNoScript,
|
||||
"Shouldn't have caller context when called noscript");
|
||||
|
||||
*aReturn = nsnull;
|
||||
|
||||
|
@ -5996,6 +6021,20 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
abuseLevel = CheckForAbusePoint();
|
||||
allowReason = CheckOpenAllow(abuseLevel);
|
||||
if (allowReason == allowNot) {
|
||||
if (aJSCallerContext) {
|
||||
// If script in some other window is doing a window.open on us and
|
||||
// it's being blocked, then it's OK to close us afterwards, probably.
|
||||
// But if we're doing a window.open on ourselves and block the popup,
|
||||
// prevent this window from closing until after this script terminates
|
||||
// so that whatever popup blocker UI the app has will be visible.
|
||||
if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) {
|
||||
mBlockScriptedClosingFlag = PR_TRUE;
|
||||
mContext->SetTerminationFunction(CloseBlockScriptTerminationFunc,
|
||||
NS_STATIC_CAST(nsPIDOMWindow*,
|
||||
this));
|
||||
}
|
||||
}
|
||||
|
||||
FireAbuseEvents(PR_TRUE, PR_FALSE, aUrl, aName, aOptions);
|
||||
return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -333,6 +333,7 @@ public:
|
|||
|
||||
static void ShutDown();
|
||||
static PRBool IsCallerChrome();
|
||||
static void CloseBlockScriptTerminationFunc(nsISupports *aRef);
|
||||
|
||||
friend class WindowStateHolder;
|
||||
|
||||
|
@ -398,6 +399,8 @@ protected:
|
|||
* @param argc The number of arguments in argv.
|
||||
* @param aExtraArgument Another way to pass arguments in. This is mutually
|
||||
* exclusive with the argv/argc approach.
|
||||
* @param aJSCallerContext The calling script's context. This must be nsnull
|
||||
* when aCalledNoScript is true.
|
||||
* @param aReturn [out] The window that was opened, if any.
|
||||
*
|
||||
* @note that the boolean args are const because the function shouldn't be
|
||||
|
@ -413,6 +416,7 @@ protected:
|
|||
nsIArray *argv,
|
||||
nsISupports *aExtraArgument,
|
||||
nsIPrincipal *aCalleePrincipal,
|
||||
JSContext *aJSCallerContext,
|
||||
nsIDOMWindow **aReturn);
|
||||
|
||||
static void CloseWindow(nsISupports* aWindow);
|
||||
|
@ -536,6 +540,9 @@ protected:
|
|||
PRPackedBool mHadOriginalOpener : 1;
|
||||
PRPackedBool mIsPopupSpam : 1;
|
||||
|
||||
// Indicates whether scripts are allowed to close this window.
|
||||
PRPackedBool mBlockScriptedClosingFlag : 1;
|
||||
|
||||
// Track what sorts of events we need to fire when thawed
|
||||
PRPackedBool mFireOfflineStatusChangeEventOnThaw : 1;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче