LCOV - code coverage report
Current view: top level - js/xpconnect/wrappers - XrayWrapper.h (source / functions) Hit Total Coverage
Test: output.info Lines: 27 88 30.7 %
Date: 2017-07-14 16:53:18 Functions: 9 42 21.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef XrayWrapper_h
       8             : #define XrayWrapper_h
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : 
      12             : #include "WrapperFactory.h"
      13             : 
      14             : #include "jswrapper.h"
      15             : #include "js/Proxy.h"
      16             : 
      17             : // Slot where Xray functions for Web IDL methods store a pointer to
      18             : // the Xray wrapper they're associated with.
      19             : #define XRAY_DOM_FUNCTION_PARENT_WRAPPER_SLOT 0
      20             : // Slot where in debug builds Xray functions for Web IDL methods store
      21             : // a pointer to their themselves, just so we can assert that they're the
      22             : // sort of functions we expect.
      23             : #define XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_SELF 1
      24             : 
      25             : // Xray wrappers re-resolve the original native properties on the native
      26             : // object and always directly access to those properties.
      27             : // Because they work so differently from the rest of the wrapper hierarchy,
      28             : // we pull them out of the Wrapper inheritance hierarchy and create a
      29             : // little world around them.
      30             : 
      31             : class nsIPrincipal;
      32             : class XPCWrappedNative;
      33             : 
      34             : namespace xpc {
      35             : 
      36             : namespace XrayUtils {
      37             : 
      38             : bool IsXPCWNHolderClass(const JSClass* clasp);
      39             : 
      40             : bool CloneExpandoChain(JSContext* cx, JSObject* src, JSObject* dst);
      41             : 
      42             : bool
      43             : IsTransparent(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id);
      44             : 
      45             : JSObject*
      46             : GetNativePropertiesObject(JSContext* cx, JSObject* wrapper);
      47             : 
      48             : bool
      49             : HasNativeProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
      50             :                   bool* hasProp);
      51             : } // namespace XrayUtils
      52             : 
      53             : enum XrayType {
      54             :     XrayForDOMObject,
      55             :     XrayForWrappedNative,
      56             :     XrayForJSObject,
      57             :     XrayForOpaqueObject,
      58             :     NotXray
      59             : };
      60             : 
      61             : class XrayTraits
      62             : {
      63             : public:
      64             :     constexpr XrayTraits() {}
      65             : 
      66        1247 :     static JSObject* getTargetObject(JSObject* wrapper) {
      67        1247 :         JSObject* target = js::UncheckedUnwrap(wrapper, /* stopAtWindowProxy = */ false);
      68        1247 :         if (target)
      69        1247 :             JS::ExposeObjectToActiveJS(target);
      70        1247 :         return target;
      71             :     }
      72             : 
      73             :     virtual bool resolveNativeProperty(JSContext* cx, JS::HandleObject wrapper,
      74             :                                        JS::HandleObject holder, JS::HandleId id,
      75             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) = 0;
      76             :     // NB: resolveOwnProperty may decide whether or not to cache what it finds
      77             :     // on the holder. If the result is not cached, the lookup will happen afresh
      78             :     // for each access, which is the right thing for things like dynamic NodeList
      79             :     // properties.
      80             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper,
      81             :                                     JS::HandleObject target, JS::HandleObject holder,
      82             :                                     JS::HandleId id, JS::MutableHandle<JS::PropertyDescriptor> desc);
      83             : 
      84           0 :     bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
      85             :                  JS::ObjectOpResult& result) {
      86           0 :         return result.succeed();
      87             :     }
      88             : 
      89          11 :     static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance,
      90             :                                 js::ESClass* cls) {
      91          11 :         return baseInstance.getBuiltinClass(cx, wrapper, cls);
      92             :     }
      93             : 
      94           0 :     static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) {
      95           0 :         return baseInstance.className(cx, wrapper);
      96             :     }
      97             : 
      98             :     virtual void preserveWrapper(JSObject* target) = 0;
      99             : 
     100             :     bool getExpandoObject(JSContext* cx, JS::HandleObject target,
     101             :                           JS::HandleObject consumer, JS::MutableHandleObject expandObject);
     102             :     JSObject* ensureExpandoObject(JSContext* cx, JS::HandleObject wrapper,
     103             :                                   JS::HandleObject target);
     104             : 
     105             :     // Slots for holder objects.
     106             :     enum {
     107             :         HOLDER_SLOT_CACHED_PROTO = 0,
     108             :         HOLDER_SHARED_SLOT_COUNT
     109             :     };
     110             : 
     111             :     JSObject* getHolder(JSObject* wrapper);
     112             :     JSObject* ensureHolder(JSContext* cx, JS::HandleObject wrapper);
     113             :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) = 0;
     114             : 
     115             :     JSObject* getExpandoChain(JS::HandleObject obj);
     116             :     bool setExpandoChain(JSContext* cx, JS::HandleObject obj, JS::HandleObject chain);
     117             :     bool cloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject src);
     118             : 
     119             : protected:
     120             :     static const JSClass HolderClass;
     121             : 
     122             :     // Get the JSClass we should use for our expando object.
     123             :     virtual const JSClass* getExpandoClass(JSContext* cx,
     124             :                                            JS::HandleObject target) const;
     125             : 
     126             : private:
     127             :     bool expandoObjectMatchesConsumer(JSContext* cx, JS::HandleObject expandoObject,
     128             :                                       nsIPrincipal* consumerOrigin,
     129             :                                       JS::HandleObject exclusiveGlobal);
     130             :     bool getExpandoObjectInternal(JSContext* cx, JSObject* expandoChain,
     131             :                                   nsIPrincipal* origin, JSObject* exclusiveGlobal,
     132             :                                   JS::MutableHandleObject expandoObject);
     133             :     JSObject* attachExpandoObject(JSContext* cx, JS::HandleObject target,
     134             :                                   nsIPrincipal* origin,
     135             :                                   JS::HandleObject exclusiveGlobal);
     136             : 
     137             :     XrayTraits(XrayTraits&) = delete;
     138             :     const XrayTraits& operator=(XrayTraits&) = delete;
     139             : };
     140             : 
     141             : class XPCWrappedNativeXrayTraits : public XrayTraits
     142             : {
     143             : public:
     144             :     enum {
     145             :         HasPrototype = 0
     146             :     };
     147             : 
     148             :     static const XrayType Type = XrayForWrappedNative;
     149             : 
     150             :     virtual bool resolveNativeProperty(JSContext* cx, JS::HandleObject wrapper,
     151             :                                        JS::HandleObject holder, JS::HandleId id,
     152             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     153             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target,
     154             :                                     JS::HandleObject holder, JS::HandleId id,
     155             :                                     JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     156           0 :     bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
     157             :                         JS::Handle<JS::PropertyDescriptor> desc,
     158             :                         JS::Handle<JS::PropertyDescriptor> existingDesc,
     159             :                         JS::ObjectOpResult& result, bool* defined)
     160             :     {
     161           0 :         *defined = false;
     162           0 :         return true;
     163             :     }
     164             :     virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
     165             :                                 JS::AutoIdVector& props);
     166             :     static bool call(JSContext* cx, JS::HandleObject wrapper,
     167             :                      const JS::CallArgs& args, const js::Wrapper& baseInstance);
     168             :     static bool construct(JSContext* cx, JS::HandleObject wrapper,
     169             :                           const JS::CallArgs& args, const js::Wrapper& baseInstance);
     170             : 
     171             :     static XPCWrappedNative* getWN(JSObject* wrapper);
     172             : 
     173             :     virtual void preserveWrapper(JSObject* target) override;
     174             : 
     175             :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override;
     176             : 
     177             :     static const JSClass HolderClass;
     178             :     static XPCWrappedNativeXrayTraits singleton;
     179             : };
     180             : 
     181             : class DOMXrayTraits : public XrayTraits
     182             : {
     183             : public:
     184             :     constexpr DOMXrayTraits() = default;
     185             : 
     186             :     enum {
     187             :         HasPrototype = 1
     188             :     };
     189             : 
     190             :     static const XrayType Type = XrayForDOMObject;
     191             : 
     192           0 :     virtual bool resolveNativeProperty(JSContext* cx, JS::HandleObject wrapper,
     193             :                                        JS::HandleObject holder, JS::HandleId id,
     194             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) override
     195             :     {
     196             :         // Xrays for DOM binding objects have a prototype chain that consists of
     197             :         // Xrays for the prototypes of the DOM binding object (ignoring changes
     198             :         // in the prototype chain made by script, plugins or XBL). All properties for
     199             :         // these Xrays are really own properties, either of the instance object or
     200             :         // of the prototypes.
     201             :         // FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=1072482
     202             :         //       This should really be:
     203             :         // MOZ_CRASH("resolveNativeProperty hook should never be called with HasPrototype = 1");
     204             :         //       but we can't do that yet because XrayUtils::HasNativeProperty calls this.
     205           0 :         return true;
     206             :     }
     207             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target,
     208             :                                     JS::HandleObject holder, JS::HandleId id,
     209             :                                     JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     210             : 
     211             :     bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult& result);
     212             : 
     213             :     bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
     214             :                         JS::Handle<JS::PropertyDescriptor> desc,
     215             :                         JS::Handle<JS::PropertyDescriptor> existingDesc,
     216             :                         JS::ObjectOpResult& result, bool* defined);
     217             :     virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
     218             :                                 JS::AutoIdVector& props);
     219             :     static bool call(JSContext* cx, JS::HandleObject wrapper,
     220             :                      const JS::CallArgs& args, const js::Wrapper& baseInstance);
     221             :     static bool construct(JSContext* cx, JS::HandleObject wrapper,
     222             :                           const JS::CallArgs& args, const js::Wrapper& baseInstance);
     223             : 
     224             :     static bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     225             :                              JS::HandleObject target,
     226             :                              JS::MutableHandleObject protop);
     227             : 
     228             :     virtual void preserveWrapper(JSObject* target) override;
     229             : 
     230             :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override;
     231             : 
     232             :     static DOMXrayTraits singleton;
     233             : 
     234             : protected:
     235             :     virtual const JSClass* getExpandoClass(JSContext* cx,
     236             :                                            JS::HandleObject target) const override;
     237             : };
     238             : 
     239             : class JSXrayTraits : public XrayTraits
     240             : {
     241             : public:
     242             :     enum {
     243             :         HasPrototype = 1
     244             :     };
     245             :     static const XrayType Type = XrayForJSObject;
     246             : 
     247           0 :     virtual bool resolveNativeProperty(JSContext* cx, JS::HandleObject wrapper,
     248             :                                        JS::HandleObject holder, JS::HandleId id,
     249             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) override
     250             :     {
     251           0 :         MOZ_CRASH("resolveNativeProperty hook should never be called with HasPrototype = 1");
     252             :     }
     253             : 
     254             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target,
     255             :                                     JS::HandleObject holder, JS::HandleId id,
     256             :                                     JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     257             : 
     258             :     bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult& result);
     259             : 
     260             :     bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
     261             :                         JS::Handle<JS::PropertyDescriptor> desc,
     262             :                         JS::Handle<JS::PropertyDescriptor> existingDesc,
     263             :                         JS::ObjectOpResult& result, bool* defined);
     264             : 
     265             :     virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
     266             :                                 JS::AutoIdVector& props);
     267             : 
     268           0 :     static bool call(JSContext* cx, JS::HandleObject wrapper,
     269             :                      const JS::CallArgs& args, const js::Wrapper& baseInstance)
     270             :     {
     271           0 :         JSXrayTraits& self = JSXrayTraits::singleton;
     272           0 :         JS::RootedObject holder(cx, self.ensureHolder(cx, wrapper));
     273           0 :         if (self.getProtoKey(holder) == JSProto_Function)
     274           0 :             return baseInstance.call(cx, wrapper, args);
     275             : 
     276           0 :         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
     277           0 :         js::ReportIsNotFunction(cx, v);
     278           0 :         return false;
     279             :     }
     280             : 
     281             :     static bool construct(JSContext* cx, JS::HandleObject wrapper,
     282             :                           const JS::CallArgs& args, const js::Wrapper& baseInstance);
     283             : 
     284           6 :     bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     285             :                       JS::HandleObject target,
     286             :                       JS::MutableHandleObject protop)
     287             :     {
     288          12 :         JS::RootedObject holder(cx, ensureHolder(cx, wrapper));
     289           6 :         JSProtoKey key = getProtoKey(holder);
     290           6 :         if (isPrototype(holder)) {
     291           2 :             JSProtoKey protoKey = js::InheritanceProtoKeyForStandardClass(key);
     292           2 :             if (protoKey == JSProto_Null) {
     293           2 :                 protop.set(nullptr);
     294           2 :                 return true;
     295             :             }
     296           0 :             key = protoKey;
     297             :         }
     298             : 
     299             :         {
     300           8 :             JSAutoCompartment ac(cx, target);
     301           4 :             if (!JS_GetClassPrototype(cx, key, protop))
     302           0 :                 return false;
     303             :         }
     304           4 :         return JS_WrapObject(cx, protop);
     305             :     }
     306             : 
     307           0 :     virtual void preserveWrapper(JSObject* target) override {
     308             :         // In the case of pure JS objects, there is no underlying object, and
     309             :         // the target is the canonical representation of state. If it gets
     310             :         // collected, then expandos and such should be collected too. So there's
     311             :         // nothing to do here.
     312           0 :     }
     313             : 
     314             :     enum {
     315             :         SLOT_PROTOKEY = HOLDER_SHARED_SLOT_COUNT,
     316             :         SLOT_ISPROTOTYPE,
     317             :         SLOT_CONSTRUCTOR_FOR,
     318             :         SLOT_COUNT
     319             :     };
     320             :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override;
     321             : 
     322          87 :     static JSProtoKey getProtoKey(JSObject* holder) {
     323          87 :         int32_t key = js::GetReservedSlot(holder, SLOT_PROTOKEY).toInt32();
     324          87 :         return static_cast<JSProtoKey>(key);
     325             :     }
     326             : 
     327          87 :     static bool isPrototype(JSObject* holder) {
     328          87 :         return js::GetReservedSlot(holder, SLOT_ISPROTOTYPE).toBoolean();
     329             :     }
     330             : 
     331           0 :     static JSProtoKey constructorFor(JSObject* holder) {
     332           0 :         int32_t key = js::GetReservedSlot(holder, SLOT_CONSTRUCTOR_FOR).toInt32();
     333           0 :         return static_cast<JSProtoKey>(key);
     334             :     }
     335             : 
     336             :     // Operates in the wrapper compartment.
     337             :     static bool getOwnPropertyFromWrapperIfSafe(JSContext* cx,
     338             :                                                 JS::HandleObject wrapper,
     339             :                                                 JS::HandleId id,
     340             :                                                 JS::MutableHandle<JS::PropertyDescriptor> desc);
     341             : 
     342             :     // Like the above, but operates in the target compartment.
     343             :     static bool getOwnPropertyFromTargetIfSafe(JSContext* cx,
     344             :                                                JS::HandleObject target,
     345             :                                                JS::HandleObject wrapper,
     346             :                                                JS::HandleId id,
     347             :                                                JS::MutableHandle<JS::PropertyDescriptor> desc);
     348             : 
     349             :     static const JSClass HolderClass;
     350             :     static JSXrayTraits singleton;
     351             : };
     352             : 
     353             : // These traits are used when the target is not Xrayable and we therefore want
     354             : // to make it opaque modulo the usual Xray machinery (like expandos and
     355             : // .wrappedJSObject).
     356             : class OpaqueXrayTraits : public XrayTraits
     357             : {
     358             : public:
     359             :     enum {
     360             :         HasPrototype = 1
     361             :     };
     362             :     static const XrayType Type = XrayForOpaqueObject;
     363             : 
     364           0 :     virtual bool resolveNativeProperty(JSContext* cx, JS::HandleObject wrapper,
     365             :                                        JS::HandleObject holder, JS::HandleId id,
     366             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) override
     367             :     {
     368           0 :         MOZ_CRASH("resolveNativeProperty hook should never be called with HasPrototype = 1");
     369             :     }
     370             : 
     371             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target,
     372             :                                     JS::HandleObject holder, JS::HandleId id,
     373             :                                     JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     374             : 
     375           0 :     bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
     376             :                         JS::Handle<JS::PropertyDescriptor> desc,
     377             :                         JS::Handle<JS::PropertyDescriptor> existingDesc,
     378             :                         JS::ObjectOpResult& result, bool* defined)
     379             :     {
     380           0 :         *defined = false;
     381           0 :         return true;
     382             :     }
     383             : 
     384           0 :     virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
     385             :                                 JS::AutoIdVector& props)
     386             :     {
     387           0 :         return true;
     388             :     }
     389             : 
     390           0 :     static bool call(JSContext* cx, JS::HandleObject wrapper,
     391             :                      const JS::CallArgs& args, const js::Wrapper& baseInstance)
     392             :     {
     393           0 :         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
     394           0 :         js::ReportIsNotFunction(cx, v);
     395           0 :         return false;
     396             :     }
     397             : 
     398           0 :     static bool construct(JSContext* cx, JS::HandleObject wrapper,
     399             :                           const JS::CallArgs& args, const js::Wrapper& baseInstance)
     400             :     {
     401           0 :         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
     402           0 :         js::ReportIsNotFunction(cx, v);
     403           0 :         return false;
     404             :     }
     405             : 
     406           0 :     bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     407             :                       JS::HandleObject target,
     408             :                       JS::MutableHandleObject protop)
     409             :     {
     410             :         // Opaque wrappers just get targetGlobal.Object.prototype as their
     411             :         // prototype. This is preferable to using a null prototype because it
     412             :         // lets things like |toString| and |__proto__| work.
     413             :         {
     414           0 :             JSAutoCompartment ac(cx, target);
     415           0 :             if (!JS_GetClassPrototype(cx, JSProto_Object, protop))
     416           0 :                 return false;
     417             :         }
     418           0 :         return JS_WrapObject(cx, protop);
     419             :     }
     420             : 
     421           0 :     static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance,
     422             :                                 js::ESClass* cls) {
     423           0 :         *cls = js::ESClass::Other;
     424           0 :         return true;
     425             :     }
     426             : 
     427           0 :     static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) {
     428           0 :         return "Opaque";
     429             :     }
     430             : 
     431           0 :     virtual void preserveWrapper(JSObject* target) override { }
     432             : 
     433           0 :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override
     434             :     {
     435           0 :         return JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr);
     436             :     }
     437             : 
     438             :     static OpaqueXrayTraits singleton;
     439             : };
     440             : 
     441             : XrayType GetXrayType(JSObject* obj);
     442             : XrayTraits* GetXrayTraits(JSObject* obj);
     443             : 
     444             : // NB: Base *must* derive from JSProxyHandler
     445             : template <typename Base, typename Traits = XPCWrappedNativeXrayTraits >
     446             : class XrayWrapper : public Base {
     447             :   public:
     448           0 :     constexpr explicit XrayWrapper(unsigned flags)
     449           0 :       : Base(flags | WrapperFactory::IS_XRAY_WRAPPER_FLAG, Traits::HasPrototype)
     450           0 :     { };
     451             : 
     452             :     /* Standard internal methods. */
     453             :     virtual bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     454             :                                           JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
     455             :     virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     456             :                                 JS::Handle<JS::PropertyDescriptor> desc,
     457             :                                 JS::ObjectOpResult& result) const override;
     458             :     virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
     459             :                                  JS::AutoIdVector& props) const override;
     460             :     virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
     461             :                          JS::Handle<jsid> id, JS::ObjectOpResult& result) const override;
     462             :     virtual JSObject* enumerate(JSContext* cx, JS::Handle<JSObject*> wrapper) const override;
     463             :     virtual bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     464             :                               JS::MutableHandleObject protop) const override;
     465             :     virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,
     466             :                               JS::HandleObject proto, JS::ObjectOpResult& result) const override;
     467             :     virtual bool getPrototypeIfOrdinary(JSContext* cx, JS::HandleObject wrapper, bool* isOrdinary,
     468             :                                         JS::MutableHandleObject protop) const override;
     469             :     virtual bool setImmutablePrototype(JSContext* cx, JS::HandleObject wrapper,
     470             :                                        bool* succeeded) const override;
     471             :     virtual bool preventExtensions(JSContext* cx, JS::Handle<JSObject*> wrapper,
     472             :                                    JS::ObjectOpResult& result) const override;
     473             :     virtual bool isExtensible(JSContext* cx, JS::Handle<JSObject*> wrapper, bool* extensible) const override;
     474             :     virtual bool has(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     475             :                      bool* bp) const override;
     476             :     virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::HandleValue receiver,
     477             :                      JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
     478             :     virtual bool set(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     479             :                      JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
     480             :                      JS::ObjectOpResult& result) const override;
     481             :     virtual bool call(JSContext* cx, JS::Handle<JSObject*> wrapper,
     482             :                       const JS::CallArgs& args) const override;
     483             :     virtual bool construct(JSContext* cx, JS::Handle<JSObject*> wrapper,
     484             :                            const JS::CallArgs& args) const override;
     485             : 
     486             :     /* SpiderMonkey extensions. */
     487             :     virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     488             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
     489             :     virtual bool hasOwn(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     490             :                         bool* bp) const override;
     491             :     virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
     492             :                                               JS::AutoIdVector& props) const override;
     493             : 
     494             :     virtual bool getBuiltinClass(JSContext* cx, JS::HandleObject wapper, js::ESClass* cls) const override;
     495             :     virtual const char* className(JSContext* cx, JS::HandleObject proxy) const override;
     496             : 
     497             :     static const XrayWrapper singleton;
     498             : 
     499             :   private:
     500             :     template <bool HasPrototype>
     501             :     typename mozilla::EnableIf<HasPrototype, bool>::Type
     502          52 :         getPrototypeHelper(JSContext* cx, JS::HandleObject wrapper,
     503             :                            JS::HandleObject target, JS::MutableHandleObject protop) const
     504             :     {
     505          52 :         return Traits::singleton.getPrototype(cx, wrapper, target, protop);
     506             :     }
     507             :     template <bool HasPrototype>
     508             :     typename mozilla::EnableIf<!HasPrototype, bool>::Type
     509           0 :         getPrototypeHelper(JSContext* cx, JS::HandleObject wrapper,
     510             :                            JS::HandleObject target, JS::MutableHandleObject protop) const
     511             :     {
     512           0 :         return Base::getPrototype(cx, wrapper, protop);
     513             :     }
     514          52 :     bool getPrototypeHelper(JSContext* cx, JS::HandleObject wrapper,
     515             :                             JS::HandleObject target, JS::MutableHandleObject protop) const
     516             :     {
     517             :         return getPrototypeHelper<Traits::HasPrototype>(cx, wrapper, target,
     518          52 :                                                         protop);
     519             :     }
     520             : 
     521             :   protected:
     522             :     bool getPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper, unsigned flags,
     523             :                          JS::AutoIdVector& props) const;
     524             : };
     525             : 
     526             : #define PermissiveXrayXPCWN xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::XPCWrappedNativeXrayTraits>
     527             : #define SecurityXrayXPCWN xpc::XrayWrapper<js::CrossCompartmentSecurityWrapper, xpc::XPCWrappedNativeXrayTraits>
     528             : #define PermissiveXrayDOM xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::DOMXrayTraits>
     529             : #define SecurityXrayDOM xpc::XrayWrapper<js::CrossCompartmentSecurityWrapper, xpc::DOMXrayTraits>
     530             : #define PermissiveXrayJS xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::JSXrayTraits>
     531             : #define PermissiveXrayOpaque xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::OpaqueXrayTraits>
     532             : 
     533             : extern template class PermissiveXrayXPCWN;
     534             : extern template class SecurityXrayXPCWN;
     535             : extern template class PermissiveXrayDOM;
     536             : extern template class SecurityXrayDOM;
     537             : extern template class PermissiveXrayJS;
     538             : extern template class PermissiveXrayOpaque;
     539             : extern template class PermissiveXrayXPCWN;
     540             : 
     541             : class SandboxProxyHandler : public js::Wrapper {
     542             : public:
     543             :     constexpr SandboxProxyHandler() : js::Wrapper(0)
     544             :     {
     545             :     }
     546             : 
     547             :     virtual bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
     548             :                                           JS::Handle<jsid> id,
     549             :                                           JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
     550             : 
     551             :     // We just forward the high-level methods to the BaseProxyHandler versions
     552             :     // which implement them in terms of lower-level methods.
     553             :     virtual bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
     554             :                      bool* bp) const override;
     555             :     virtual bool get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::HandleValue receiver,
     556             :                      JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
     557             :     virtual bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
     558             :                      JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
     559             :                      JS::ObjectOpResult& result) const override;
     560             : 
     561             :     virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
     562             :                                        JS::Handle<jsid> id,
     563             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
     564             :     virtual bool hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
     565             :                         bool* bp) const override;
     566             :     virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
     567             :                                               JS::AutoIdVector& props) const override;
     568             :     virtual JSObject* enumerate(JSContext* cx, JS::Handle<JSObject*> proxy) const override;
     569             : };
     570             : 
     571             : extern const SandboxProxyHandler sandboxProxyHandler;
     572             : 
     573             : // A proxy handler that lets us wrap callables and invoke them with
     574             : // the correct this object, while forwarding all other operations down
     575             : // to them directly.
     576             : class SandboxCallableProxyHandler : public js::Wrapper {
     577             : public:
     578             :     constexpr SandboxCallableProxyHandler() : js::Wrapper(0)
     579             :     {
     580             :     }
     581             : 
     582             :     virtual bool call(JSContext* cx, JS::Handle<JSObject*> proxy,
     583             :                       const JS::CallArgs& args) const override;
     584             : 
     585             :     static const size_t SandboxProxySlot = 0;
     586             : 
     587           0 :     static inline JSObject* getSandboxProxy(JS::Handle<JSObject*> proxy)
     588             :     {
     589           0 :         return &js::GetProxyReservedSlot(proxy, SandboxProxySlot).toObject();
     590             :     }
     591             : };
     592             : 
     593             : extern const SandboxCallableProxyHandler sandboxCallableProxyHandler;
     594             : 
     595             : class AutoSetWrapperNotShadowing;
     596             : 
     597             : /*
     598             :  * Slots for Xray expando objects.  See comments in XrayWrapper.cpp for details
     599             :  * of how these get used; we mostly want the value of JSSLOT_EXPANDO_COUNT here.
     600             :  */
     601             : enum ExpandoSlots {
     602             :     JSSLOT_EXPANDO_NEXT = 0,
     603             :     JSSLOT_EXPANDO_ORIGIN,
     604             :     JSSLOT_EXPANDO_EXCLUSIVE_GLOBAL,
     605             :     JSSLOT_EXPANDO_PROTOTYPE,
     606             :     JSSLOT_EXPANDO_COUNT
     607             : };
     608             : 
     609             : extern const JSClassOps XrayExpandoObjectClassOps;
     610             : 
     611             : /*
     612             :  * Clear the given slot on all Xray expandos for the given object.
     613             :  *
     614             :  * No-op when called on non-main threads (where Xrays don't exist).
     615             :  */
     616             : void
     617             : ClearXrayExpandoSlots(JSObject* target, size_t slotIndex);
     618             : 
     619             : /*
     620             :  * Ensure the given wrapper has an expando object and return it.  This can
     621             :  * return null on failure.  Will only be called when "wrapper" is an Xray for a
     622             :  * DOM object.
     623             :  */
     624             : JSObject*
     625             : EnsureXrayExpandoObject(JSContext* cx, JS::HandleObject wrapper);
     626             : 
     627             : } // namespace xpc
     628             : 
     629             : #endif

Generated by: LCOV version 1.13