Bug 1051224 - Find a clever way to work around COW restrictions on beta. r=gabor,ochameau
authorBobby Holley <bobbyholley@gmail.com>
Mon, 22 Sep 2014 19:36:56 +0200
changeset 216815 6cdc428e3e62
parent 216814 02eaea5dce76
child 216816 0ae1af037f6e
push id3923
push userbobbyholley@gmail.com
push date2014-09-22 17:37 +0000
treeherdermozilla-beta@0ae1af037f6e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor, ochameau
bugs1051224
milestone33.0
Bug 1051224 - Find a clever way to work around COW restrictions on beta. r=gabor,ochameau
toolkit/devtools/server/actors/webconsole.js
toolkit/devtools/webconsole/utils.js
--- a/toolkit/devtools/server/actors/webconsole.js
+++ b/toolkit/devtools/server/actors/webconsole.js
@@ -908,23 +908,55 @@ WebConsoleActor.prototype =
       makeDebuggeeValue: aDebuggerGlobal.makeDebuggeeValue.bind(aDebuggerGlobal),
       createValueGrip: this.createValueGrip.bind(this),
       sandbox: Object.create(null),
       helperResult: null,
       consoleActor: this,
     };
     JSTermHelpers(helpers);
 
-    // Make sure the helpers can be used during eval.
+    let evalWindow = this.evalWindow;
+    function maybeExport(obj, name) {
+      if (typeof obj[name] != "function") {
+        return;
+      }
+
+      // By default, chrome-implemented functions that are exposed to content
+      // refuse to accept arguments that are cross-origin for the caller. This
+      // is generally the safe thing, but causes problems for certain console
+      // helpers like cd(), where we users sometimes want to pass a cross-origin
+      // window.
+      //
+      // We have a proper way to waive this security check from FF34 onward, but
+      // for FF33 need to do some more tricky circumvention.
+
+      // Create a content function that boxes up its arguments into an Array
+      // and forwards that to chrome, which then uses an xray waiver to access
+      // it. Be careful not to do anything that might hit a standard object
+      // (like .push() or Array.from());
+      let funToExport = obj[name];
+      let boxerSource = "var args = []; \
+                         for (var i = 0; i < arguments.length; ++i) \
+                           args[i] = arguments[i]; \
+                         return arguments.callee.__chromeFun__(args);";
+      let boxer = evalWindow.Function(boxerSource);
+      let unboxer = function(args) { return funToExport.apply(null, Cu.waiveXrays(args)); };
+      Object.defineProperty(Cu.waiveXrays(boxer), '__chromeFun__', { value: unboxer });
+      obj[name] = boxer;
+    }
     for (let name in helpers.sandbox) {
       let desc = Object.getOwnPropertyDescriptor(helpers.sandbox, name);
-      if (desc.get || desc.set) {
-        continue;
+      maybeExport(desc, 'get');
+      maybeExport(desc, 'set');
+      maybeExport(desc, 'value');
+      if (desc.value) {
+        // Make sure the helpers can be used during eval.
+        desc.value = aDebuggerGlobal.makeDebuggeeValue(desc.value);
       }
-      helpers.sandbox[name] = aDebuggerGlobal.makeDebuggeeValue(desc.value);
+      Object.defineProperty(helpers.sandbox, name, desc);
     }
     return helpers;
   },
 
   /**
    * Evaluates a string using the debugger API.
    *
    * To allow the variables view to update properties from the Web Console we
--- a/toolkit/devtools/webconsole/utils.js
+++ b/toolkit/devtools/webconsole/utils.js
@@ -1592,17 +1592,17 @@ function JSTermHelpers(aOwner)
       }
 
       let toolbox = gDevTools.getToolbox(target);
       let node = toolbox && toolbox.selection ? toolbox.selection.node : null;
 
       return node ? aOwner.makeDebuggeeValue(node) : null;
     },
     enumerable: true,
-    configurable: false
+    configurable: true
   });
 
   /**
    * Clears the output of the JSTerm.
    */
   aOwner.sandbox.clear = function JSTH_clear()
   {
     aOwner.helperResult = {