Fixing bug 61098. Give users a way out of inifinite modal dialog loops. Original patch by Nochum Sossonko. r=jonas@sicking.cc a=beta7+

This commit is contained in:
Johnny Stenback 2010-09-16 18:24:14 -07:00
parent 0a4d13c52b
commit 16a2846c1a
7 changed files with 552 additions and 50 deletions

View File

@ -336,6 +336,7 @@ user_pref("dom.disable_open_during_load", false);
user_pref("dom.max_script_run_time", 0); // no slow script dialogs
user_pref("dom.max_chrome_script_run_time", 0);
user_pref("dom.popup_maximum", -1);
user_pref("dom.successive_dialog_time_limit", 0);
user_pref("signed.applets.codebase_principal_support", true);
user_pref("security.warn_submit_insecure", false);
user_pref("browser.shell.checkDefaultBrowser", false);

View File

@ -690,13 +690,15 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mPendingStorageEventsObsolete(nsnull),
mTimeoutsSuspendDepth(0),
mFocusMethod(0),
mSerial(0)
mSerial(0),
#ifdef DEBUG
, mSetOpenerWindowCalled(PR_FALSE)
mSetOpenerWindowCalled(PR_FALSE),
#endif
, mCleanedUp(PR_FALSE)
, mCallCleanUpAfterModalDialogCloses(PR_FALSE)
, mWindowID(gNextWindowID++)
mCleanedUp(PR_FALSE),
mCallCleanUpAfterModalDialogCloses(PR_FALSE),
mWindowID(gNextWindowID++),
mDialogAbuseCount(0),
mDialogDisabled(PR_FALSE)
{
nsLayoutStatics::AddRef();
@ -2346,6 +2348,105 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
return NS_OK;
}
bool
nsGlobalWindow::DialogOpenAttempted()
{
nsGlobalWindow *topWindow = GetTop();
if (!topWindow) {
NS_ERROR("DialogOpenAttempted() called without a top window?");
return false;
}
topWindow = topWindow->GetCurrentInnerWindowInternal();
if (!topWindow ||
topWindow->mLastDialogQuitTime.IsNull() ||
nsContentUtils::IsCallerTrustedForCapability("UniversalXPConnect")) {
return false;
}
TimeDuration dialogDuration(TimeStamp::Now() -
topWindow->mLastDialogQuitTime);
if (dialogDuration.ToSeconds() <
nsContentUtils::GetIntPref("dom.successive_dialog_time_limit",
SUCCESSIVE_DIALOG_TIME_LIMIT)) {
topWindow->mDialogAbuseCount++;
return (topWindow->GetPopupControlState() > openAllowed ||
topWindow->mDialogAbuseCount > MAX_DIALOG_COUNT);
}
topWindow->mDialogAbuseCount = 0;
return false;
}
bool
nsGlobalWindow::AreDialogsBlocked()
{
nsGlobalWindow *topWindow = GetTop();
if (!topWindow) {
NS_ERROR("AreDialogsBlocked() called without a top window?");
return true;
}
topWindow = topWindow->GetCurrentInnerWindowInternal();
return !topWindow ||
(topWindow->mDialogDisabled &&
(topWindow->GetPopupControlState() > openAllowed ||
topWindow->mDialogAbuseCount >= MAX_DIALOG_COUNT));
}
bool
nsGlobalWindow::ConfirmDialogAllowed()
{
NS_ENSURE_TRUE(mDocShell, false);
nsCOMPtr<nsIPromptService> promptSvc =
do_GetService("@mozilla.org/embedcomp/prompt-service;1");
if (!DialogOpenAttempted() || !promptSvc) {
return true;
}
// Reset popup state while opening a modal dialog, and firing events
// about the dialog, to prevent the current state from being active
// the whole time a modal dialog is open.
nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE);
PRBool disableDialog = PR_FALSE;
nsXPIDLString label, title;
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDialogLabel", label);
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDialogPreventTitle", title);
promptSvc->Confirm(this, title.get(), label.get(), &disableDialog);
if (disableDialog) {
PreventFurtherDialogs();
return false;
}
return true;
}
void
nsGlobalWindow::PreventFurtherDialogs()
{
nsGlobalWindow *topWindow = GetTop();
if (!topWindow) {
NS_ERROR("PreventFurtherDialogs() called without a top window?");
return;
}
topWindow = topWindow->GetCurrentInnerWindowInternal();
if (topWindow)
topWindow->mDialogDisabled = PR_TRUE;
}
nsresult
nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
@ -2673,8 +2774,6 @@ nsGlobalWindow::GetTop(nsIDOMWindow** aTop)
{
FORWARD_TO_OUTER(GetTop, (aTop), NS_ERROR_NOT_INITIALIZED);
nsresult ret = NS_OK;
*aTop = nsnull;
if (mDocShell) {
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
@ -2682,12 +2781,12 @@ nsGlobalWindow::GetTop(nsIDOMWindow** aTop)
docShellAsItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
if (root) {
nsCOMPtr<nsIScriptGlobalObject> globalObject(do_GetInterface(root));
CallQueryInterface(globalObject.get(), aTop);
nsCOMPtr<nsIDOMWindow> top(do_GetInterface(root));
top.swap(*aTop);
}
}
return ret;
return NS_OK;
}
NS_IMETHODIMP
@ -4274,6 +4373,13 @@ nsGlobalWindow::Alert(const nsAString& aString)
{
FORWARD_TO_OUTER(Alert, (aString), NS_ERROR_NOT_INITIALIZED);
if (AreDialogsBlocked())
return NS_ERROR_NOT_AVAILABLE;
// We have to capture this now so as not to get confused with the
// popup state we push next
PRBool shouldEnableDisableDialog = DialogOpenAttempted();
// Reset popup state while opening a modal dialog, and firing events
// about the dialog, to prevent the current state from being active
// the whole time a modal dialog is open.
@ -4299,10 +4405,29 @@ nsGlobalWindow::Alert(const nsAString& aString)
nsContentUtils::StripNullChars(*str, final);
nsresult rv;
nsCOMPtr<nsIPromptService> promptSvc = do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
nsCOMPtr<nsIPromptService> promptSvc =
do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
return promptSvc->Alert(this, title.get(), final.get());
EnterModalState();
if (shouldEnableDisableDialog) {
PRBool disallowDialog = PR_FALSE;
nsXPIDLString label;
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDialogLabel", label);
rv = promptSvc->AlertCheck(this, title.get(), final.get(), label.get(),
&disallowDialog);
if (disallowDialog)
PreventFurtherDialogs();
} else {
rv = promptSvc->Alert(this, title.get(), final.get());
}
LeaveModalState();
return rv;
}
NS_IMETHODIMP
@ -4310,6 +4435,13 @@ nsGlobalWindow::Confirm(const nsAString& aString, PRBool* aReturn)
{
FORWARD_TO_OUTER(Confirm, (aString, aReturn), NS_ERROR_NOT_INITIALIZED);
if (AreDialogsBlocked())
return NS_ERROR_NOT_AVAILABLE;
// We have to capture this now so as not to get confused with the popup state
// we push next
PRBool shouldEnableDisableDialog = DialogOpenAttempted();
// Reset popup state while opening a modal dialog, and firing events
// about the dialog, to prevent the current state from being active
// the whole time a modal dialog is open.
@ -4330,10 +4462,29 @@ nsGlobalWindow::Confirm(const nsAString& aString, PRBool* aReturn)
nsContentUtils::StripNullChars(aString, final);
nsresult rv;
nsCOMPtr<nsIPromptService> promptSvc = do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
nsCOMPtr<nsIPromptService> promptSvc =
do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
return promptSvc->Confirm(this, title.get(), final.get(), aReturn);
EnterModalState();
if (shouldEnableDisableDialog) {
PRBool disallowDialog = PR_FALSE;
nsXPIDLString label;
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDialogLabel", label);
rv = promptSvc->ConfirmCheck(this, title.get(), final.get(), label.get(),
&disallowDialog, aReturn);
if (disallowDialog)
PreventFurtherDialogs();
} else {
rv = promptSvc->Confirm(this, title.get(), final.get(), aReturn);
}
LeaveModalState();
return rv;
}
NS_IMETHODIMP
@ -4342,6 +4493,13 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
{
SetDOMStringToNull(aReturn);
if (AreDialogsBlocked())
return NS_ERROR_NOT_AVAILABLE;
// We have to capture this now so as not to get confused with the popup state
// we push next
PRBool shouldEnableDisableDialog = DialogOpenAttempted();
// Reset popup state while opening a modal dialog, and firing events
// about the dialog, to prevent the current state from being active
// the whole time a modal dialog is open.
@ -4361,15 +4519,32 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
nsContentUtils::StripNullChars(aInitial, fixedInitial);
nsresult rv;
nsCOMPtr<nsIPromptService> promptSvc = do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
nsCOMPtr<nsIPromptService> promptSvc =
do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Pass in the default value, if any.
PRUnichar *inoutValue = ToNewUnicode(fixedInitial);
PRBool disallowDialog = PR_FALSE;
PRBool ok, dummy;
nsXPIDLString label;
if (shouldEnableDisableDialog) {
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDialogLabel", label);
}
EnterModalState();
PRBool ok;
rv = promptSvc->Prompt(this, title.get(), fixedMessage.get(),
&inoutValue, nsnull, &dummy, &ok);
&inoutValue, label.get(), &disallowDialog, &ok);
LeaveModalState();
if (disallowDialog) {
PreventFurtherDialogs();
}
NS_ENSURE_SUCCESS(rv, rv);
nsAdoptingString outValue(inoutValue);
@ -4623,6 +4798,9 @@ nsGlobalWindow::Print()
#ifdef NS_PRINTING
FORWARD_TO_OUTER(Print, (), NS_ERROR_NOT_INITIALIZED);
if (AreDialogsBlocked() || !ConfirmDialogAllowed())
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint;
if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),
getter_AddRefs(webBrowserPrint)))) {
@ -5855,17 +6033,14 @@ nsGlobalWindow::ReallyCloseWindow()
void
nsGlobalWindow::EnterModalState()
{
nsCOMPtr<nsIDOMWindow> top;
GetTop(getter_AddRefs(top));
nsGlobalWindow* topWin = GetTop();
if (!top) {
if (!topWin) {
NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
return;
}
nsGlobalWindow* topWin =
static_cast<nsGlobalWindow*>(static_cast<nsIDOMWindow *>(top.get()));
if (topWin->mModalStateDepth == 0) {
NS_ASSERTION(!mSuspendedDoc, "Shouldn't have mSuspendedDoc here!");
@ -5959,20 +6134,13 @@ private:
void
nsGlobalWindow::LeaveModalState()
{
nsCOMPtr<nsIDOMWindow> top;
GetTop(getter_AddRefs(top));
nsGlobalWindow *topWin = GetTop();
if (!top) {
if (!topWin) {
NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
return;
}
nsGlobalWindow *topWin =
static_cast<nsGlobalWindow *>
(static_cast<nsIDOMWindow *>
(top.get()));
topWin->mModalStateDepth--;
if (topWin->mModalStateDepth == 0) {
@ -5994,23 +6162,25 @@ nsGlobalWindow::LeaveModalState()
if (cx && (scx = GetScriptContextFromJSContext(cx))) {
scx->LeaveModalState();
}
// Remember the time of the last dialog quit.
nsGlobalWindow *inner = topWin->GetCurrentInnerWindowInternal();
if (inner)
inner->mLastDialogQuitTime = TimeStamp::Now();
}
PRBool
nsGlobalWindow::IsInModalState()
{
nsCOMPtr<nsIDOMWindow> top;
GetTop(getter_AddRefs(top));
nsGlobalWindow *topWin = GetTop();
if (!top) {
if (!topWin) {
NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?");
return PR_FALSE;
}
return static_cast<nsGlobalWindow *>
(static_cast<nsIDOMWindow *>
(top.get()))->mModalStateDepth != 0;
return topWin->mModalStateDepth != 0;
}
// static
@ -6316,7 +6486,12 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
{
*aRetVal = nsnull;
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
// Before bringing up the window/dialog, unsuppress painting and flush
// pending reflows.
EnsureReflowFlushAndPaint();
if (AreDialogsBlocked() || !ConfirmDialogAllowed())
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsIDOMWindow> dlgWin;
nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
@ -6325,10 +6500,7 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
options.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
// Before bringing up the window, unsuppress painting and flush
// pending reflows.
EnsureReflowFlushAndPaint();
EnterModalState();
nsresult rv = OpenInternal(aURI, EmptyString(), options,
PR_FALSE, // aDialog
PR_TRUE, // aContentModal
@ -6338,6 +6510,7 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
GetPrincipal(), // aCalleePrincipal
nsnull, // aJSCallerContext
getter_AddRefs(dlgWin));
LeaveModalState();
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -43,6 +43,8 @@
#ifndef nsGlobalWindow_h___
#define nsGlobalWindow_h___
#include "mozilla/XPCOM.h" // for TimeStamp/TimeDuration
// Local Includes
// Helper Classes
#include "nsCOMPtr.h"
@ -109,6 +111,14 @@
#define DEFAULT_HOME_PAGE "www.mozilla.org"
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
// Amount of time allowed between alert/prompt/confirm before enabling
// the stop dialog checkbox.
#define SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
// During click or mousedown events (and others, see nsDOMEvent) we allow modal
// dialogs up to this limit, even if they were disabled.
#define MAX_DIALOG_COUNT 10
class nsIDOMBarProp;
class nsIDocument;
class nsPresContext;
@ -244,6 +254,9 @@ class nsGlobalWindow : public nsPIDOMWindow,
public PRCListStr
{
public:
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
// public methods
nsPIDOMWindow* GetPrivateParent();
// callback for close event
@ -395,6 +408,32 @@ public:
return FromSupports(wrapper->Native());
}
inline nsGlobalWindow *GetTop()
{
nsCOMPtr<nsIDOMWindow> top;
GetTop(getter_AddRefs(top));
if (top)
return static_cast<nsGlobalWindow *>(static_cast<nsIDOMWindow *>(top.get()));
return nsnull;
}
// Call this when a modal dialog is about to be opened. Returns
// true if we've reached the state in this top level window where we
// ask the user if further dialogs should be blocked.
bool DialogOpenAttempted();
// Returns true if dialogs have already been blocked for this
// window.
bool AreDialogsBlocked();
// Ask the user if further dialogs should be blocked. This is used
// in the cases where we have no modifiable UI to show, in that case
// we show a separate dialog when asking this question.
bool ConfirmDialogAllowed();
// Prevent further dialogs in this (top level) window
void PreventFurtherDialogs();
nsIScriptContext *GetContextInternal()
{
if (mOuterWindow) {
@ -864,6 +903,18 @@ protected:
// this window.
PRUint64 mWindowID;
// In the case of a "trusted" dialog (@see PopupControlState), we
// set this counter to ensure a max of MAX_DIALOG_LIMIT
PRUint32 mDialogAbuseCount;
// This holds the time when the last modal dialog was shown, if two
// dialogs are shown within CONCURRENT_DIALOG_TIME_LIMIT the
// checkbox is shown. In the case of ShowModalDialog another Confirm
// dialog will be shown, the result of the checkbox/confirm dialog
// will be stored in mDialogDisabled variable.
TimeStamp mLastDialogQuitTime;
PRPackedBool mDialogDisabled;
friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils;
friend class PostMessageEvent;

View File

@ -123,6 +123,7 @@ _TEST_FILES = \
test_bug585240.html \
test_bug585819.html \
test_bug369306.html \
test_bug61098.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -9,27 +9,31 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=504862
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<body onload="runTest()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=504862">Mozilla Bug 504862</a>
<script class="testbody" type="text/javascript">
/** Test for Bug 504862 **/
SimpleTest.waitForExplicitFinish();
function onMsgRcv(event)
{
is(event.data, "args: undefined", "Unexpected cross origin dialog arguments.");
}
window.addEventListener("message", onMsgRcv, false);
function runTest() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.addEventListener("message", onMsgRcv, false);
var subsequentDlg = "data:text/html,<html><body onload='opener.is(window.dialogArguments, \'my args\', \'subsequent dialog document did not get the right arguments.\'); close();'>";
var subsequentDlg = "data:text/html,<html><body onload='opener.is(window.dialogArguments, \'my args\', \'subsequent dialog document did not get the right arguments.\'); close();'>";
var result = window.showModalDialog("file_bug504862.html", "my args");
is(result, null, "window sees previous dialog documents return value.");
var result = window.showModalDialog("file_bug504862.html", "my args");
is(result, null, "window sees previous dialog documents return value.");
result = window.showModalDialog("http://test1.example.com/tests/dom/tests/mochitest/bugs/file_bug504862.html", "my args");
result = window.showModalDialog("http://test1.example.com/tests/dom/tests/mochitest/bugs/file_bug504862.html", "my args");
is(result, null, "Able to see return value from cross origin dialog.");
is(result, null, "Able to see return value from cross origin dialog.");
SimpleTest.finish();
}
</script>
</pre>

View File

@ -0,0 +1,270 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=61098
-->
<head>
<title>Test for Bug 61098</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/mozprefs.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/mockObjects.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="runtests();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=61098">Mozilla Bug 61098</a>
<p id="display">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="text/javascript">
/** Test for Bug 61098 **/
SimpleTest.waitForExplicitFinish();
var mockPromptServiceRegisterer;
var promptState;
function registerMockPromptService()
{
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
// Override the prompt service with our own so that we can test
// modal dialogs
function MockPromptService()
{
}
MockPromptService.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptService]),
alert: function(aParent, aDialogTitle, aText)
{
promptState = {method: "alert",
parent: aParent,
title: aDialogTitle,
msg: aText
};
},
alertCheck: function(aParent, aDialogTitle, aText, aCheckMsg, aCheckState)
{
promptState = {method: "alertCheck",
parent: aParent,
title: aDialogTitle,
msg: aText,
checkMsg: aCheckMsg,
checkState: aCheckState
};
aCheckState.value = true;
},
confirm: function(aParent, aDialogTitle, aText)
{
promptState = {method: "confirm",
parent: aParent,
title: aDialogTitle,
msg: aText
};
return true;
},
confirmCheck: function(aParent, aDialogTitle, aText, aCheckMsg,
aCheckState)
{
promptState = {method: "confirmCheck",
parent: aParent,
title: aDialogTitle,
msg: aText,
checkMsg: aCheckMsg,
checkState: aCheckState
};
aCheckState.value = true;
return true;
},
confirmEx: function(aParent, aDialogTitle, aText, aButtonFlags,
aButton0Title, aButton1Title, aButton2Title,
aCheckMsg, aCheckState)
{
promptState = {method: "confirmCheck",
parent: aParent,
title: aDialogTitle,
msg: aText,
checkMsg: aCheckMsg,
checkState: aCheckState
};
if (aCheckMsg != null)
aCheckState.value = true;
return 0;
},
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg,
aCheckState)
{
promptState = {method: "prompt",
parent: aParent,
title: aDialogTitle,
msg: aText,
checkMsg: aCheckMsg,
checkState: aCheckState
};
if (aCheckMsg != null)
aCheckState.value = true;
return true;
},
};
mockPromptServiceRegisterer =
new MockObjectRegisterer("@mozilla.org/embedcomp/prompt-service;1",
MockPromptService);
mockPromptServiceRegisterer.register();
};
function enableDialogLoopBlocking()
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
prefs.setIntPref("dom.successive_dialog_time_limit", 3);
}
function resetDialogLoopBlocking()
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
prefs.setIntPref("dom.successive_dialog_time_limit", 0);
}
var expectedState;
function runtests()
{
registerMockPromptService();
enableDialogLoopBlocking();
// Test that alert() works normally and then gets blocked on the
// second call.
w = window.open();
w.alert("alert message 1");
is (promptState.method, "alert", "Wrong prompt method called");
is (promptState.parent, w, "Wrong alert parent");
is (promptState.msg, "alert message 1", "Wrong alert message");
promptState = void(0);
w.alert("alert message 2");
is (promptState.method, "alertCheck", "Wrong prompt method called");
is (promptState.parent, w, "Wrong alert parent");
is (promptState.msg, "alert message 2", "Wrong alert message");
promptState = void(0);
try {
w.alert("alert message 3");
} catch(e) {
is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
}
is (promptState, void(0), "Wrong prompt state after blocked alert()");
w.close();
// Test that confirm() works normally and then gets blocked on the
// second call.
w = window.open();
w.confirm("confirm message 1");
is (promptState.method, "confirm", "Wrong prompt method called");
is (promptState.parent, w, "Wrong confirm parent");
is (promptState.msg, "confirm message 1", "Wrong confirm message");
promptState = void(0);
w.confirm("confirm message 2");
is (promptState.method, "confirmCheck", "Wrong prompt method called");
is (promptState.parent, w, "Wrong confirm parent");
is (promptState.msg, "confirm message 2", "Wrong confirm message");
promptState = void(0);
try {
w.confirm("confirm message 3");
} catch(e) {
is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
}
is (promptState, void(0), "Wrong prompt state after blocked confirm()");
w.close();
// Test that prompt() works normally and then gets blocked on the
// second call.
w = window.open();
w.prompt("prompt message 1");
is (promptState.method, "prompt", "Wrong prompt method called");
is (promptState.parent, w, "Wrong prompt parent");
is (promptState.msg, "prompt message 1", "Wrong prompt message");
is (promptState.checkMsg, null, "Wrong dialog value");
promptState = void(0);
w.prompt("prompt message 2");
is (promptState.method, "prompt", "Wrong prompt method called");
is (promptState.parent, w, "Wrong prompt parent");
is (promptState.msg, "prompt message 2", "Wrong prompt message");
is (promptState.checkMsg, "Prevent this page from creating additional dialogs", "Wrong dialog value");
promptState = void(0);
try {
w.prompt("prompt message 3");
} catch(e) {
is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
}
is (promptState, void(0), "Wrong prompt state after blocked prompt()");
w.close();
// Test that showModalDialog() works normally and then gets blocked
// on the second call.
w = window.open();
w.showModalDialog("data:text/html,%3Cscript>window.close();%3C/script>")
is (promptState, void(0), "Wrong prompt state");
// Test that showModalDialog() works normally and then gets blocked
// on the second call.
try {
w.showModalDialog("data:text/html,%3Cscript>window.close();%3C/script>")
} catch(e) {
is(e.name, "NS_ERROR_NOT_AVAILABLE", "Wrong exception");
}
is (promptState.method, "confirm", "Wrong prompt method called");
is (promptState.parent, w, "Wrong confirm parent");
is (promptState.msg, "Prevent this page from creating additional dialogs",
"Wrong confirm message");
promptState = void(0);
w.close();
resetDialogLoopBlocking();
mockPromptServiceRegisterer.unregister();
SimpleTest.finish();
}
</script>
</body>
</html>

View File

@ -14,6 +14,8 @@ Revert=&Revert
DontSave=&Don't Save
ScriptDlgGenericHeading=[JavaScript Application]
ScriptDlgHeading=The page at %S says:
ScriptDialogLabel=Prevent this page from creating additional dialogs
ScriptDialogPreventTitle=Confirm Dialog Preference
# LOCALIZATION NOTE (EnterLoginForRealm, EnterLoginForProxy):
# %1 is an untrusted string provided by a remote server. It could try to
# take advantage of sentence structure in order to mislead the user (see