Skip to content

Commit

Permalink
Bug 437361. Propagate exceptions from showModalDialog's guts to scrip…
Browse files Browse the repository at this point in the history
…t as needed instead of dropping them on the floor. r+sr=bzbarsky
  • Loading branch information
Ben Newman committed Jul 29, 2008
1 parent 18be7b3 commit 83ca35e
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 11 deletions.
22 changes: 11 additions & 11 deletions dom/src/base/nsGlobalWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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");

Expand Down
1 change: 1 addition & 0 deletions dom/tests/mochitest/bugs/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ _TEST_FILES = \
iframe_bug430276-2.html \
test_bug440572.html \
iframe_bug440572.html \
test_bug437361.html \
$(NULL)

libs:: $(_TEST_FILES)
Expand Down
67 changes: 67 additions & 0 deletions dom/tests/mochitest/bugs/test_bug437361.html
Original file line number Diff line number Diff line change
@@ -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>

1 change: 1 addition & 0 deletions testing/mochitest/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ _SERV_FILES = \
redirect.js \
$(topsrcdir)/build/pgo/server-locations.txt \
$(topsrcdir)/netwerk/test/httpserver/httpd.js \
mozprefs.js \
$(NULL)


Expand Down
92 changes: 92 additions & 0 deletions testing/mochitest/mozprefs.js
Original file line number Diff line number Diff line change
@@ -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

})();

0 comments on commit 83ca35e

Please sign in to comment.