Bug 1290966 - Permit introspection into arguments; r?automatedtester
The callback function available to asynchronously evaluated scripts is
defined in a privileged content frame script, and is thus not readable
or introspectable in a sandboxed content script. Attempting this will
yield a "Permission denied to access property" error.
To circumvent this problem we "hide" the callback function by wrapping
it before pushing it on the arguments object that is applied to the
injected script.
This allows introspection into the _immediate_ elements on the arguments
object available to executed scripts.
MozReview-Commit-ID: 9ZigPNYcYpf
--- a/testing/marionette/evaluate.js
+++ b/testing/marionette/evaluate.js
@@ -107,17 +107,20 @@ evaluate.sandbox = function(sb, script,
unloadHandler = () => reject(
new JavaScriptError("Document was unloaded during execution"));
// wrap in function
if (!opts.directInject) {
sb[CALLBACK] = sb[COMPLETE];
sb[ARGUMENTS] = Cu.cloneInto(args, sb, {wrapReflectors: true});
- script = `${ARGUMENTS}.push(${CALLBACK});` +
+ // callback function made private
+ // so that introspection is possible
+ // on the arguments object
+ script = `${ARGUMENTS}.push(rv => ${CALLBACK}(rv));` +
`(function() { ${script} }).apply(null, ${ARGUMENTS})`;
// marionetteScriptFinished is not WebDriver conformant,
// hence it is only exposed to immutable sandboxes
if (opts.sandboxName) {
sb[MARIONETTE_SCRIPT_FINISHED] = sb[CALLBACK];
}
}
--- a/testing/marionette/harness/marionette/tests/unit/test_execute_async_script.py
+++ b/testing/marionette/harness/marionette/tests/unit/test_execute_async_script.py
@@ -106,16 +106,29 @@ marionetteScriptFinished(4);
self.marionette.execute_async_script("global.barfoo = [arguments[0], arguments[1]];"
"marionetteScriptFinished()",
script_args=[42, 23], new_sandbox=False)
self.assertEqual(self.marionette.execute_async_script(
"marionetteScriptFinished(global.barfoo);", new_sandbox=False),
[42, 23])
+ # Functions defined in higher privilege scopes, such as the privileged
+ # content frame script listener.js runs in, cannot be accessed from
+ # content. This tests that it is possible to introspect the objects on
+ # `arguments` without getting permission defined errors. This is made
+ # possible because the last argument is always the callback/complete
+ # function.
+ #
+ # See bug 1290966.
+ def test_introspection_of_arguments(self):
+ self.marionette.execute_async_script(
+ "arguments[0].cheese; __webDriverCallback();",
+ script_args=[], sandbox=None)
+
class TestExecuteAsyncChrome(TestExecuteAsyncContent):
def setUp(self):
super(TestExecuteAsyncChrome, self).setUp()
self.marionette.set_context("chrome")
def test_execute_async_unload(self):
pass