diff --git a/testing/marionette/evaluate.js b/testing/marionette/evaluate.js index 2e66430b759e..38a80eb39450 100644 --- a/testing/marionette/evaluate.js +++ b/testing/marionette/evaluate.js @@ -113,7 +113,7 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) { if (opts.async) { sb[CALLBACK] = sb[COMPLETE]; } - sb[ARGUMENTS] = Cu.cloneInto(args, sb, {wrapReflectors: true}); + sb[ARGUMENTS] = sandbox.cloneInto(args, sb); // callback function made private // so that introspection is possible @@ -138,20 +138,18 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) { // see bug 1128760 for more details if (opts.debug) { sb.window.onerror = (msg, url, line) => { - let err = new JavaScriptError(`${msg} at: ${url} line: ${line}`); + let err = new JavaScriptError(`${msg} at ${url}:${line}`); reject(err); }; } // timeout and unload handlers - scriptTimeoutID = setTimeout( - timeoutHandler, opts.timeout || DEFAULT_TIMEOUT); - sb.window.addEventListener("unload", unloadHandler); + scriptTimeoutID = setTimeout(timeoutHandler, opts.timeout || DEFAULT_TIMEOUT); + sb.window.onunload = sandbox.cloneInto(unloadHandler, sb); let res; try { - res = Cu.evalInSandbox( - src, sb, "1.8", opts.filename || "dummy file", 0); + res = Cu.evalInSandbox(src, sb, "1.8", opts.filename || "dummy file", 0); } catch (e) { let err = new JavaScriptError( e, @@ -176,6 +174,18 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) { this.sandbox = {}; +/** + * Provides a safe way to take an object defined in a privileged scope and + * create a structured clone of it in a less-privileged scope. It returns + * a reference to the clone. + * + * Unlike for |Components.utils.cloneInto|, |obj| may contain functions + * and DOM elemnets. + */ +sandbox.cloneInto = function (obj, sb) { + return Cu.cloneInto(obj, sb, {cloneFunctions: true, wrapReflectors: true}); +}; + /** * Augment given sandbox by an adapter that has an {@code exports} * map property, or a normal map, of function names and function diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_execute_script.py b/testing/marionette/harness/marionette_harness/tests/unit/test_execute_script.py index 2d6d97e1f47f..1ef4549d3cff 100644 --- a/testing/marionette/harness/marionette_harness/tests/unit/test_execute_script.py +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_execute_script.py @@ -262,6 +262,17 @@ class TestExecuteContent(MarionetteTestCase): content_timeout_triggered, message="Scheduled setTimeout event was cancelled by call to execute_script") + def test_privileged_code_inspection(self): + # test permission denied on toString of unload event handler + self.marionette.navigate(inline(""" + """)) + self.marionette.execute_script("", sandbox=None) + + # test inspection of arguments + self.marionette.execute_script("__webDriverArguments.toString()") + class TestExecuteChrome(WindowManagerMixin, TestExecuteContent): @@ -337,6 +348,9 @@ class TestExecuteChrome(WindowManagerMixin, TestExecuteContent): def test_window_set_timeout_is_not_cancelled(self): pass + def test_privileged_code_inspection(self): + pass + class TestElementCollections(MarionetteTestCase):