Bug 1092446 - [e10s] Allow unprivileged scopes to call content-to-chrome CPOWs (r=bholley)
☠☠ backed out by 541dc2f509e2 ☠ ☠
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 04 Nov 2014 17:38:19 -0800
changeset 214041 2dbf8f6bd2aa84cd40137ece81e81d6d2cbb7ea8
parent 214040 f86dbba73d43d8f87eb93a1b218397e0f22a8f53
child 214042 5992aea01affcabf8ffe6faba1cd697b8d612628
push id27771
push userryanvm@gmail.com
push dateWed, 05 Nov 2014 19:04:24 +0000
treeherdermozilla-central@305b4fecce99 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1092446
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1092446 - [e10s] Allow unprivileged scopes to call content-to-chrome CPOWs (r=bholley)
dom/base/test/chrome/cpows_child.js
dom/base/test/chrome/cpows_parent.xul
js/xpconnect/wrappers/WrapperFactory.cpp
--- a/dom/base/test/chrome/cpows_child.js
+++ b/dom/base/test/chrome/cpows_child.js
@@ -82,16 +82,25 @@ function parent_test()
     let result = check_func(10);
     ok(result == 20, "calling function in parent worked");
     return result;
   }
 
   addMessageListener("cpows:from_parent", (msg) => {
     let obj = msg.objects.obj;
     ok(obj.a == 1, "correct value from parent");
+
+    // Test that a CPOW reference to a function in the chrome process
+    // is callable from unprivileged content. Greasemonkey uses this
+    // functionality.
+    let func = msg.objects.func;
+    let sb = Cu.Sandbox('http://www.example.com', {});
+    sb.func = func;
+    ok(sb.eval('func()') == 101, "can call parent's function in child");
+
     done_count++;
     if (done_count == 2)
       sendSyncMessage("cpows:done", {});
   });
   sendSyncMessage("cpows:parent_test", {}, {func: f});
 }
 
 function error_reporting_test() {
--- a/dom/base/test/chrome/cpows_parent.xul
+++ b/dom/base/test/chrome/cpows_parent.xul
@@ -176,18 +176,21 @@
 
       finish();
     }
 
     function recvParentTest(message) {
       let func = message.objects.func;
       let result = func(n => 2*n);
       ok(result == 20, "result == 20");
+      function f() {
+        return 101;
+      }
       let obj = {a:1, __exposedProps__: {"a": "r"}};
-      savedMM.sendAsyncMessage("cpows:from_parent", {}, {obj: obj});
+      savedMM.sendAsyncMessage("cpows:from_parent", {}, {obj: obj, func: f});
     }
 
     // Make sure errors in this file actually hit window.onerror.
     function recvErrorReportingTest(message) {
       throw "Test Error Probe";
     }
 
     let savedElement = null;
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -11,19 +11,21 @@
 #include "AccessCheck.h"
 #include "XPCWrapper.h"
 #include "ChromeObjectWrapper.h"
 #include "WrapperFactory.h"
 
 #include "xpcprivate.h"
 #include "XPCMaps.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "JavaScriptParent.h"
 #include "jsfriendapi.h"
 #include "mozilla/Likely.h"
 #include "nsContentUtils.h"
+#include "nsXULAppAPI.h"
 
 using namespace JS;
 using namespace js;
 using namespace mozilla;
 
 namespace xpc {
 
 // When chrome pulls a naked property across the membrane using
@@ -418,19 +420,22 @@ WrapperFactory::Rewrap(JSContext *cx, Ha
 
     // Let the SpecialPowers scope make its stuff easily accessible to content.
     else if (CompartmentPrivate::Get(origin)->forcePermissiveCOWs) {
         CrashIfNotInAutomation();
         wrapper = &CrossCompartmentWrapper::singleton;
     }
 
     // If this is a chrome function being exposed to content, we need to allow
-    // call (but nothing else).
+    // call (but nothing else). We allow CPOWs that purport to be function's
+    // here, but only in the content process.
     else if (originIsChrome && !targetIsChrome &&
-             IdentifyStandardInstance(obj) == JSProto_Function)
+             (IdentifyStandardInstance(obj) == JSProto_Function ||
+              (jsipc::IsCPOW(obj) && JS::IsCallable(obj) &&
+               XRE_GetProcessType() == GeckoProcessType_Content)))
     {
         wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, OpaqueWithCall>::singleton;
     }
 
     // For Vanilla JSObjects exposed from chrome to content, we use a wrapper
     // that supports __exposedProps__. We'd like to get rid of these eventually,
     // but in their current form they don't cause much trouble.
     else if (originIsChrome && !targetIsChrome &&