Bug 437361. Propagate exceptions from showModalDialog's guts to script as needed instead of dropping them on the floor. r+sr=bzbarsky

This commit is contained in:
Ben Newman 2008-07-28 22:52:53 -07:00
Родитель d750ddc25d
Коммит 198f21c6c3
5 изменённых файлов: 172 добавлений и 11 удалений

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

@ -6050,24 +6050,26 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
PR_FALSE, // aDialog
PR_TRUE, // aContentModal
PR_TRUE, // aCalledNoScript
PR_FALSE, // aDoJSFixups
PR_TRUE, // aDoJSFixups
nsnull, aArgs, // args
GetPrincipal(), // aCalleePrincipal
nsnull, // aJSCallerContext
getter_AddRefs(dlgWin));
if (NS_FAILED(rv) || !dlgWin)
return NS_OK;
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(dlgWin));
NS_ENSURE_SUCCESS(rv, rv);
if (dlgWin) {
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(dlgWin));
nsPIDOMWindow *inner = win->GetCurrentInnerWindow();
nsPIDOMWindow *inner = win->GetCurrentInnerWindow();
nsCOMPtr<nsIDOMModalContentWindow> dlgInner(do_QueryInterface(inner));
nsCOMPtr<nsIDOMModalContentWindow> dlgInner(do_QueryInterface(inner));
if (dlgInner) {
dlgInner->GetReturnValue(aRetVal);
if (dlgInner) {
dlgInner->GetReturnValue(aRetVal);
}
}
return NS_OK;
}
@ -7292,8 +7294,6 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
"Can't pass in arguments both ways");
NS_PRECONDITION(!aCalledNoScript || (!argv && argc == 0),
"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");

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

@ -79,6 +79,7 @@ _TEST_FILES = \
iframe_bug430276-2.html \
test_bug440572.html \
iframe_bug440572.html \
test_bug437361.html \
$(NULL)
libs:: $(_TEST_FILES)

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

@ -0,0 +1,67 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=437361
-->
<head>
<title>Test for Bug 437361</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/mozprefs.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
/** Test for Bug 437361 **/
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
function testModalDialogBlockedCleanly() {
is(true, pref("dom.disable_open_during_load"), "mozprefs sanity check");
var rv = window.showModalDialog( // should be blocked without exception
"data:text/html,<html><body onload='close(); returnValue = 1;' /></html>");
is(rv, null, "Modal dialog opened unexpectedly.");
}
function testModalDialogAllowed() {
is(false, pref("dom.disable_open_during_load"), "mozprefs sanity check");
var rv = window.showModalDialog( // should not be blocked this time
"data:text/html,<html><body onload='close(); returnValue = 1;' /></html>");
is(rv, 1, "Problem with modal dialog returnValue.");
}
function testOtherExceptionsNotTrapped() {
is(false, pref("dom.disable_open_during_load"), "mozprefs sanity check");
window.showModalDialog('about:config'); // forbidden by SecurityCheckURL
}
function test(disableOpen, exceptionExpected, testFn, errorMsg) {
try {
pref("dom.disable_open_during_load", disableOpen, testFn);
ok(!exceptionExpected, errorMsg);
} catch (_) {
ok(exceptionExpected, errorMsg);
}
}
test(true, false, testModalDialogBlockedCleanly,
"Blocked showModalDialog caused an exception.");
test(false, false, testModalDialogAllowed,
"showModalDialog was blocked even though dom.disable_open_during_load was false.");
test(false, true, testOtherExceptionsNotTrapped,
"Incorrectly suppressed insecure showModalDialog exception.");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=437361">Mozilla Bug 437361</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -69,6 +69,7 @@ _SERV_FILES = \
redirect.js \
$(topsrcdir)/build/pgo/server-locations.txt \
$(topsrcdir)/netwerk/test/httpserver/httpd.js \
mozprefs.js \
$(NULL)

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

@ -0,0 +1,92 @@
(function() {
// NOTE: You *must* also include this line in any test that uses this file:
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
function determinePrefKind(branch, prefName) {
switch (branch.getPrefType(prefName)) {
case branch.PREF_STRING: return "CharPref";
case branch.PREF_INT: return "IntPref";
case branch.PREF_BOOL: return "BoolPref";
default: /* PREF_INVALID */ return "ComplexValue";
}
}
function memoize(fn, obj) {
var cache = {}, sep = '___',
join = Array.prototype.join;
return function() {
var key = join.call(arguments, sep);
if (!(key in cache))
cache[key] = fn.apply(obj, arguments);
return cache[key];
};
}
var makeAccessor = memoize(function(pref) {
var splat = pref.split('.'),
basePref = splat.pop(),
branch, kind;
try {
branch = prefService.getBranch(splat.join('.') + '.')
} catch (e) {
alert("Calling prefService.getBranch failed: " +
"did you read the NOTE in mozprefs.js?");
throw e;
}
kind = determinePrefKind(branch, basePref);
return function(value) {
var oldValue = branch['get' + kind](basePref);
if (arguments.length > 0)
branch['set' + kind](basePref, value);
return oldValue;
};
});
/* function pref(name[, value[, fn[, obj]]])
* -----------------------------------------
* Use cases:
*
* 1. Get the value of the dom.disable_open_during_load preference:
*
* pref('dom.disable_open_during_load')
*
* 2. Set the preference to true, returning the old value:
*
* var oldValue = pref('dom.disable_open_during_load', true);
*
* 3. Set the value of the preference to true just for the duration
* of the specified function's execution:
*
* pref('dom.disable_open_during_load', true, function() {
* window.open(this.getUrl()); // fails if still loading
* }, this); // for convenience, allow binding
*
* Rationale: Unless a great deal of care is taken to catch all
* exceptions and restore original preference values,
* manually setting & restoring preferences can lead
* to unpredictable test behavior. The try-finally
* block below eliminates that risk.
*/
function pref(name, /*optional:*/ value, fn, obj) {
var acc = makeAccessor(name);
switch (arguments.length) {
case 1: return acc();
case 2: return acc(value);
default:
var oldValue = acc(value),
extra_args = [].slice.call(arguments, 4);
try { return fn.apply(obj, extra_args) }
finally { acc(oldValue) } // reset no matter what
}
};
window.pref = pref; // export
})();