Bug 1053271 - Move Sandbox proxy handlers out of XrayWrapper.h. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 06 Jun 2018 11:42:12 +0200
changeset 805267 00275042e5174f27f4a7697326dfd4a2a1c6c854
parent 805266 3cd7e51e9913010024d318fa6b726f335e21c48f
child 805268 509dc862a71ad7fbdcd19a257877085a6b5d21b1
push id112610
push userbmo:gl@mozilla.com
push dateThu, 07 Jun 2018 15:48:24 +0000
reviewersbz
bugs1053271
milestone62.0a1
Bug 1053271 - Move Sandbox proxy handlers out of XrayWrapper.h. r=bz.
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCJSContext.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/wrappers/XrayWrapper.h
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -21,17 +21,16 @@
 #include "nsJSUtils.h"
 #include "nsNetUtil.h"
 #include "NullPrincipal.h"
 #include "ExpandedPrincipal.h"
 #include "WrapperFactory.h"
 #include "xpcprivate.h"
 #include "xpc_make_class.h"
 #include "XPCWrapper.h"
-#include "XrayWrapper.h"
 #include "Crypto.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/CSSBinding.h"
 #include "mozilla/dom/CSSRuleBinding.h"
 #include "mozilla/dom/DirectoryBinding.h"
 #include "mozilla/dom/DOMParserBinding.h"
@@ -504,35 +503,91 @@ NS_IMPL_RELEASE(nsXPCComponents_utils_Sa
 
 // We use the nsIXPScriptable macros to generate lots of stuff for us.
 #define XPC_MAP_CLASSNAME         nsXPCComponents_utils_Sandbox
 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_utils_Sandbox"
 #define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_CALL | \
                        XPC_SCRIPTABLE_WANT_CONSTRUCT)
 #include "xpc_map_end.h" /* This #undef's the above. */
 
-const xpc::SandboxProxyHandler xpc::sandboxProxyHandler;
+class SandboxProxyHandler : public js::Wrapper {
+public:
+    constexpr SandboxProxyHandler() : js::Wrapper(0)
+    {
+    }
+
+    virtual bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
+                                          JS::Handle<jsid> id,
+                                          JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
+
+    // We just forward the high-level methods to the BaseProxyHandler versions
+    // which implement them in terms of lower-level methods.
+    virtual bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+                     bool* bp) const override;
+    virtual bool get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::HandleValue receiver,
+                     JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
+    virtual bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+                     JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
+                     JS::ObjectOpResult& result) const override;
+
+    virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
+                                       JS::Handle<jsid> id,
+                                       JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
+    virtual bool hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+                        bool* bp) const override;
+    virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
+                                              JS::AutoIdVector& props) const override;
+    virtual JSObject* enumerate(JSContext* cx, JS::Handle<JSObject*> proxy) const override;
+};
+
+static const SandboxProxyHandler sandboxProxyHandler;
+
+namespace xpc {
 
 bool
-xpc::IsSandboxPrototypeProxy(JSObject* obj)
+IsSandboxPrototypeProxy(JSObject* obj)
 {
     return js::IsProxy(obj) &&
-           js::GetProxyHandler(obj) == &xpc::sandboxProxyHandler;
+           js::GetProxyHandler(obj) == &sandboxProxyHandler;
+}
+
 }
 
+// A proxy handler that lets us wrap callables and invoke them with
+// the correct this object, while forwarding all other operations down
+// to them directly.
+class SandboxCallableProxyHandler : public js::Wrapper {
+public:
+    constexpr SandboxCallableProxyHandler() : js::Wrapper(0)
+    {
+    }
+
+    virtual bool call(JSContext* cx, JS::Handle<JSObject*> proxy,
+                      const JS::CallArgs& args) const override;
+
+    static const size_t SandboxProxySlot = 0;
+
+    static inline JSObject* getSandboxProxy(JS::Handle<JSObject*> proxy)
+    {
+        return &js::GetProxyReservedSlot(proxy, SandboxProxySlot).toObject();
+    }
+};
+
+static const SandboxCallableProxyHandler sandboxCallableProxyHandler;
+
 bool
-xpc::SandboxCallableProxyHandler::call(JSContext* cx, JS::Handle<JSObject*> proxy,
-                                       const JS::CallArgs& args) const
+SandboxCallableProxyHandler::call(JSContext* cx, JS::Handle<JSObject*> proxy,
+                                  const JS::CallArgs& args) const
 {
     // We forward the call to our underlying callable.
 
     // Get our SandboxProxyHandler proxy.
     RootedObject sandboxProxy(cx, getSandboxProxy(proxy));
     MOZ_ASSERT(js::IsProxy(sandboxProxy) &&
-               js::GetProxyHandler(sandboxProxy) == &xpc::sandboxProxyHandler);
+               js::GetProxyHandler(sandboxProxy) == &sandboxProxyHandler);
 
     // The global of the sandboxProxy is the sandbox global, and the
     // target object is the original proto.
     RootedObject sandboxGlobal(cx,
       js::GetGlobalForObjectCrossCompartment(sandboxProxy));
     MOZ_ASSERT(IsSandbox(sandboxGlobal));
 
     // If our this object is the sandbox global, we call with this set to the
@@ -577,39 +632,36 @@ xpc::SandboxCallableProxyHandler::call(J
     if (thisVal == ObjectValue(*sandboxGlobal)) {
         thisVal = ObjectValue(*js::GetProxyTargetObject(sandboxProxy));
     }
 
     RootedValue func(cx, js::GetProxyPrivate(proxy));
     return JS::Call(cx, thisVal, func, args, args.rval());
 }
 
-const xpc::SandboxCallableProxyHandler xpc::sandboxCallableProxyHandler;
-
 /*
  * Wrap a callable such that if we're called with oldThisObj as the
  * "this" we will instead call it with newThisObj as the this.
  */
 static JSObject*
 WrapCallable(JSContext* cx, HandleObject callable, HandleObject sandboxProtoProxy)
 {
     MOZ_ASSERT(JS::IsCallable(callable));
     // Our proxy is wrapping the callable.  So we need to use the
     // callable as the private.  We put the given sandboxProtoProxy in
     // an extra slot, and our call() hook depends on that.
     MOZ_ASSERT(js::IsProxy(sandboxProtoProxy) &&
-               js::GetProxyHandler(sandboxProtoProxy) ==
-                 &xpc::sandboxProxyHandler);
+               js::GetProxyHandler(sandboxProtoProxy) == &sandboxProxyHandler);
 
     RootedValue priv(cx, ObjectValue(*callable));
     // We want to claim to have the same proto as our wrapped callable, so set
     // ourselves up with a lazy proto.
     js::ProxyOptions options;
     options.setLazyProto(true);
-    JSObject* obj = js::NewProxyObject(cx, &xpc::sandboxCallableProxyHandler,
+    JSObject* obj = js::NewProxyObject(cx, &sandboxCallableProxyHandler,
                                        priv, nullptr, options);
     if (obj) {
         js::SetProxyReservedSlot(obj, SandboxCallableProxyHandler::SandboxProxySlot,
                                  ObjectValue(*sandboxProtoProxy));
     }
 
     return obj;
 }
@@ -644,20 +696,20 @@ IsMaybeWrappedDOMConstructor(JSObject* o
     if (!obj) {
         return false;
     }
 
     return dom::IsDOMConstructor(obj);
 }
 
 bool
-xpc::SandboxProxyHandler::getPropertyDescriptor(JSContext* cx,
-                                                JS::Handle<JSObject*> proxy,
-                                                JS::Handle<jsid> id,
-                                                JS::MutableHandle<PropertyDescriptor> desc) const
+SandboxProxyHandler::getPropertyDescriptor(JSContext* cx,
+                                           JS::Handle<JSObject*> proxy,
+                                           JS::Handle<jsid> id,
+                                           JS::MutableHandle<PropertyDescriptor> desc) const
 {
     JS::RootedObject obj(cx, wrappedObject(proxy));
 
     MOZ_ASSERT(js::GetObjectCompartment(obj) == js::GetObjectCompartment(proxy));
     if (!JS_GetPropertyDescriptorById(cx, obj, id, desc))
         return false;
 
     if (!desc.object())
@@ -683,61 +735,60 @@ xpc::SandboxProxyHandler::getPropertyDes
             desc.value().setObject(*val);
         }
     }
 
     return true;
 }
 
 bool
-xpc::SandboxProxyHandler::getOwnPropertyDescriptor(JSContext* cx,
-                                                   JS::Handle<JSObject*> proxy,
-                                                   JS::Handle<jsid> id,
-                                                   JS::MutableHandle<PropertyDescriptor> desc)
-                                                   const
+SandboxProxyHandler::getOwnPropertyDescriptor(JSContext* cx,
+                                              JS::Handle<JSObject*> proxy,
+                                              JS::Handle<jsid> id,
+                                              JS::MutableHandle<PropertyDescriptor> desc) const
 {
     if (!getPropertyDescriptor(cx, proxy, id, desc))
         return false;
 
     if (desc.object() != wrappedObject(proxy))
         desc.object().set(nullptr);
 
     return true;
 }
 
 /*
  * Reuse the BaseProxyHandler versions of the derived traps that are implemented
  * in terms of the fundamental traps.
  */
 
 bool
-xpc::SandboxProxyHandler::has(JSContext* cx, JS::Handle<JSObject*> proxy,
-                              JS::Handle<jsid> id, bool* bp) const
+SandboxProxyHandler::has(JSContext* cx, JS::Handle<JSObject*> proxy,
+                         JS::Handle<jsid> id, bool* bp) const
 {
     // This uses getPropertyDescriptor for backward compatibility with
     // the old BaseProxyHandler::has implementation.
     Rooted<PropertyDescriptor> desc(cx);
     if (!getPropertyDescriptor(cx, proxy, id, &desc))
         return false;
 
     *bp = !!desc.object();
     return true;
 }
 bool
-xpc::SandboxProxyHandler::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy,
-                                 JS::Handle<jsid> id, bool* bp) const
+SandboxProxyHandler::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy,
+                            JS::Handle<jsid> id, bool* bp) const
 {
     return BaseProxyHandler::hasOwn(cx, proxy, id, bp);
 }
 
 bool
-xpc::SandboxProxyHandler::get(JSContext* cx, JS::Handle<JSObject*> proxy,
-                              JS::Handle<JS::Value> receiver,
-                              JS::Handle<jsid> id,
-                              JS::MutableHandle<Value> vp) const
+SandboxProxyHandler::get(JSContext* cx, JS::Handle<JSObject*> proxy,
+                         JS::Handle<JS::Value> receiver,
+                         JS::Handle<jsid> id,
+                         JS::MutableHandle<Value> vp) const
 {
     // This uses getPropertyDescriptor for backward compatibility with
     // the old BaseProxyHandler::get implementation.
     Rooted<PropertyDescriptor> desc(cx);
     if (!getPropertyDescriptor(cx, proxy, id, &desc))
         return false;
     desc.assertCompleteIfFound();
 
@@ -759,35 +810,35 @@ xpc::SandboxProxyHandler::get(JSContext*
         vp.setUndefined();
         return true;
     }
 
     return Call(cx, receiver, getter, HandleValueArray::empty(), vp);
 }
 
 bool
-xpc::SandboxProxyHandler::set(JSContext* cx, JS::Handle<JSObject*> proxy,
-                              JS::Handle<jsid> id,
-                              JS::Handle<Value> v,
-                              JS::Handle<Value> receiver,
-                              JS::ObjectOpResult& result) const
+SandboxProxyHandler::set(JSContext* cx, JS::Handle<JSObject*> proxy,
+                         JS::Handle<jsid> id,
+                         JS::Handle<Value> v,
+                         JS::Handle<Value> receiver,
+                         JS::ObjectOpResult& result) const
 {
     return BaseProxyHandler::set(cx, proxy, id, v, receiver, result);
 }
 
 bool
-xpc::SandboxProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
-                                                       JS::Handle<JSObject*> proxy,
-                                                       AutoIdVector& props) const
+SandboxProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
+                                                  JS::Handle<JSObject*> proxy,
+                                                  AutoIdVector& props) const
 {
     return BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
 }
 
 JSObject*
-xpc::SandboxProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy) const
+SandboxProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy) const
 {
     return BaseProxyHandler::enumerate(cx, proxy);
 }
 
 bool
 xpc::GlobalProperties::Parse(JSContext* cx, JS::HandleObject obj)
 {
     uint32_t length;
@@ -1109,18 +1160,17 @@ xpc::CreateSandboxObject(JSContext* cx, 
                 useSandboxProxy = IS_WN_CLASS(unwrappedClass) ||
                                   mozilla::dom::IsDOMClass(Jsvalify(unwrappedClass));
             }
 
             if (useSandboxProxy) {
                 // Wrap it up in a proxy that will do the right thing in terms
                 // of this-binding for methods.
                 RootedValue priv(cx, ObjectValue(*options.proto));
-                options.proto = js::NewProxyObject(cx, &xpc::sandboxProxyHandler,
-                                                   priv, nullptr);
+                options.proto = js::NewProxyObject(cx, &sandboxProxyHandler, priv, nullptr);
                 if (!options.proto)
                     return NS_ERROR_OUT_OF_MEMORY;
             }
 
             ok = JS_SplicePrototype(cx, sandbox, options.proto);
             if (!ok)
                 return NS_ERROR_XPC_UNEXPECTED;
         }
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -640,17 +640,17 @@ XPCJSContext::InterruptCallback(JSContex
     RefPtr<nsGlobalWindowInner> win = WindowOrNull(global);
     if (!win && IsSandbox(global)) {
         // If this is a sandbox associated with a DOMWindow via a
         // sandboxPrototype, use that DOMWindow. This supports GreaseMonkey
         // and JetPack content scripts.
         JS::Rooted<JSObject*> proto(cx);
         if (!JS_GetPrototype(cx, global, &proto))
             return false;
-        if (proto && IsSandboxPrototypeProxy(proto) &&
+        if (proto && xpc::IsSandboxPrototypeProxy(proto) &&
             (proto = js::CheckedUnwrap(proto, /* stopAtWindowProxy = */ false)))
         {
             win = WindowGlobalOrNull(proto);
         }
     }
 
     if (!win) {
         NS_WARNING("No active window");
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -8,16 +8,17 @@
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/UniquePtr.h"
 
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "XPCWrapper.h"
 #include "XPCJSMemoryReporter.h"
+#include "XrayWrapper.h"
 #include "WrapperFactory.h"
 #include "mozJSComponentLoader.h"
 #include "nsAutoPtr.h"
 #include "nsNetUtil.h"
 
 #include "nsExceptionHandler.h"
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMemoryReporter.h"
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -460,70 +460,16 @@ class XrayWrapper : public Base {
 #define PermissiveXrayJS xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::JSXrayTraits>
 #define PermissiveXrayOpaque xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::OpaqueXrayTraits>
 
 extern template class PermissiveXrayDOM;
 extern template class SecurityXrayDOM;
 extern template class PermissiveXrayJS;
 extern template class PermissiveXrayOpaque;
 
-class SandboxProxyHandler : public js::Wrapper {
-public:
-    constexpr SandboxProxyHandler() : js::Wrapper(0)
-    {
-    }
-
-    virtual bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
-                                          JS::Handle<jsid> id,
-                                          JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
-
-    // We just forward the high-level methods to the BaseProxyHandler versions
-    // which implement them in terms of lower-level methods.
-    virtual bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
-                     bool* bp) const override;
-    virtual bool get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::HandleValue receiver,
-                     JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
-    virtual bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
-                     JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
-                     JS::ObjectOpResult& result) const override;
-
-    virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
-                                       JS::Handle<jsid> id,
-                                       JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
-    virtual bool hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
-                        bool* bp) const override;
-    virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
-                                              JS::AutoIdVector& props) const override;
-    virtual JSObject* enumerate(JSContext* cx, JS::Handle<JSObject*> proxy) const override;
-};
-
-extern const SandboxProxyHandler sandboxProxyHandler;
-
-// A proxy handler that lets us wrap callables and invoke them with
-// the correct this object, while forwarding all other operations down
-// to them directly.
-class SandboxCallableProxyHandler : public js::Wrapper {
-public:
-    constexpr SandboxCallableProxyHandler() : js::Wrapper(0)
-    {
-    }
-
-    virtual bool call(JSContext* cx, JS::Handle<JSObject*> proxy,
-                      const JS::CallArgs& args) const override;
-
-    static const size_t SandboxProxySlot = 0;
-
-    static inline JSObject* getSandboxProxy(JS::Handle<JSObject*> proxy)
-    {
-        return &js::GetProxyReservedSlot(proxy, SandboxProxySlot).toObject();
-    }
-};
-
-extern const SandboxCallableProxyHandler sandboxCallableProxyHandler;
-
 class AutoSetWrapperNotShadowing;
 
 /*
  * Slots for Xray expando objects.  See comments in XrayWrapper.cpp for details
  * of how these get used; we mostly want the value of JSSLOT_EXPANDO_COUNT here.
  */
 enum ExpandoSlots {
     JSSLOT_EXPANDO_NEXT = 0,