| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef jswrapper_h
- #define jswrapper_h
- #include "mozilla/Attributes.h"
- #include "js/Proxy.h"
- namespace js {
- /*
- * Helper for Wrapper::New default options.
- *
- * Callers of Wrapper::New() who wish to specify a prototype for the created
- * Wrapper, *MUST* construct a WrapperOptions with a JSContext.
- */
- class MOZ_STACK_CLASS WrapperOptions : public ProxyOptions {
- public:
- WrapperOptions() : ProxyOptions(false),
- proto_()
- {}
- explicit WrapperOptions(JSContext* cx) : ProxyOptions(false),
- proto_()
- {
- proto_.emplace(cx);
- }
- inline JSObject* proto() const;
- WrapperOptions& setProto(JSObject* protoArg) {
- MOZ_ASSERT(proto_);
- *proto_ = protoArg;
- return *this;
- }
- private:
- mozilla::Maybe<JS::RootedObject> proto_;
- };
- /*
- * A wrapper is a proxy with a target object to which it generally forwards
- * operations, but may restrict access to certain operations or augment those
- * operations in various ways.
- *
- * A wrapper can be "unwrapped" in C++, exposing the underlying object.
- * Callers should be careful to avoid unwrapping security wrappers in the wrong
- * context.
- *
- * Important: If you add a method implementation here, you probably also need
- * to add an override in CrossCompartmentWrapper. If you don't, you risk
- * compartment mismatches. See bug 945826 comment 0.
- */
- class JS_FRIEND_API(Wrapper) : public BaseProxyHandler
- {
- unsigned mFlags;
- public:
- explicit constexpr Wrapper(unsigned aFlags, bool aHasPrototype = false,
- bool aHasSecurityPolicy = false)
- : BaseProxyHandler(&family, aHasPrototype, aHasSecurityPolicy),
- mFlags(aFlags)
- { }
- virtual bool finalizeInBackground(const Value& priv) const override;
- /* Standard internal methods. */
- virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<PropertyDescriptor> desc) const override;
- virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
- Handle<PropertyDescriptor> desc,
- ObjectOpResult& result) const override;
- virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
- AutoIdVector& props) const override;
- virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
- ObjectOpResult& result) const override;
- virtual bool enumerate(JSContext* cx, HandleObject proxy,
- MutableHandleObject objp) const override;
- virtual bool getPrototype(JSContext* cx, HandleObject proxy,
- MutableHandleObject protop) const override;
- virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
- ObjectOpResult& result) const override;
- virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
- MutableHandleObject protop) const override;
- virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
- bool* succeeded) const override;
- virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
- ObjectOpResult& result) const override;
- virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
- virtual bool has(JSContext* cx, HandleObject proxy, HandleId id,
- bool* bp) const override;
- virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
- HandleId id, MutableHandleValue vp) const override;
- virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result) const override;
- virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
- virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
- /* SpiderMonkey extensions. */
- virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<PropertyDescriptor> desc) const override;
- virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
- bool* bp) const override;
- virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
- AutoIdVector& props) const override;
- virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
- const CallArgs& args) const override;
- virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
- bool* bp) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const override;
- virtual bool isArray(JSContext* cx, HandleObject proxy,
- JS::IsArrayAnswer* answer) const override;
- virtual const char* className(JSContext* cx, HandleObject proxy) const override;
- virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
- unsigned indent) const override;
- virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
- RegExpGuard* g) const override;
- virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy,
- MutableHandleValue vp) const override;
- virtual bool isCallable(JSObject* obj) const override;
- virtual bool isConstructor(JSObject* obj) const override;
- virtual JSObject* weakmapKeyDelegate(JSObject* proxy) const override;
- public:
- using BaseProxyHandler::Action;
- enum Flags {
- CROSS_COMPARTMENT = 1 << 0,
- LAST_USED_FLAG = CROSS_COMPARTMENT
- };
- static JSObject* New(JSContext* cx, JSObject* obj, const Wrapper* handler,
- const WrapperOptions& options = WrapperOptions());
- static JSObject* Renew(JSContext* cx, JSObject* existing, JSObject* obj, const Wrapper* handler);
- static const Wrapper* wrapperHandler(JSObject* wrapper);
- static JSObject* wrappedObject(JSObject* wrapper);
- unsigned flags() const {
- return mFlags;
- }
- static const char family;
- static const Wrapper singleton;
- static const Wrapper singletonWithPrototype;
- static JSObject* defaultProto;
- };
- inline JSObject*
- WrapperOptions::proto() const
- {
- return proto_ ? *proto_ : Wrapper::defaultProto;
- }
- /* Base class for all cross compartment wrapper handlers. */
- class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
- {
- public:
- explicit constexpr CrossCompartmentWrapper(unsigned aFlags, bool aHasPrototype = false,
- bool aHasSecurityPolicy = false)
- : Wrapper(CROSS_COMPARTMENT | aFlags, aHasPrototype, aHasSecurityPolicy)
- { }
- /* Standard internal methods. */
- virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<PropertyDescriptor> desc) const override;
- virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<PropertyDescriptor> desc,
- ObjectOpResult& result) const override;
- virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
- AutoIdVector& props) const override;
- virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
- ObjectOpResult& result) const override;
- virtual bool enumerate(JSContext* cx, HandleObject wrapper, MutableHandleObject objp) const override;
- virtual bool getPrototype(JSContext* cx, HandleObject proxy,
- MutableHandleObject protop) const override;
- virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
- ObjectOpResult& result) const override;
- virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
- MutableHandleObject protop) const override;
- virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
- bool* succeeded) const override;
- virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
- ObjectOpResult& result) const override;
- virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
- virtual bool has(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
- virtual bool get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
- HandleId id, MutableHandleValue vp) const override;
- virtual bool set(JSContext* cx, HandleObject wrapper, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result) const override;
- virtual bool call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
- virtual bool construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
- /* SpiderMonkey extensions. */
- virtual bool getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<PropertyDescriptor> desc) const override;
- virtual bool hasOwn(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
- virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
- AutoIdVector& props) const override;
- virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
- const CallArgs& args) const override;
- virtual bool hasInstance(JSContext* cx, HandleObject wrapper, MutableHandleValue v,
- bool* bp) const override;
- virtual const char* className(JSContext* cx, HandleObject proxy) const override;
- virtual JSString* fun_toString(JSContext* cx, HandleObject wrapper,
- unsigned indent) const override;
- virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
- virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
- // Allocate CrossCompartmentWrappers in the nursery.
- virtual bool canNurseryAllocate() const override { return true; }
- static const CrossCompartmentWrapper singleton;
- static const CrossCompartmentWrapper singletonWithPrototype;
- };
- class JS_FRIEND_API(OpaqueCrossCompartmentWrapper) : public CrossCompartmentWrapper
- {
- public:
- explicit constexpr OpaqueCrossCompartmentWrapper() : CrossCompartmentWrapper(0)
- { }
- /* Standard internal methods. */
- virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<PropertyDescriptor> desc) const override;
- virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<PropertyDescriptor> desc,
- ObjectOpResult& result) const override;
- virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
- AutoIdVector& props) const override;
- virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
- ObjectOpResult& result) const override;
- virtual bool enumerate(JSContext* cx, HandleObject wrapper,
- MutableHandleObject objp) const override;
- virtual bool getPrototype(JSContext* cx, HandleObject wrapper,
- MutableHandleObject protop) const override;
- virtual bool setPrototype(JSContext* cx, HandleObject wrapper, HandleObject proto,
- ObjectOpResult& result) const override;
- virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject wrapper, bool* isOrdinary,
- MutableHandleObject protop) const override;
- virtual bool setImmutablePrototype(JSContext* cx, HandleObject wrapper,
- bool* succeeded) const override;
- virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
- ObjectOpResult& result) const override;
- virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
- virtual bool has(JSContext* cx, HandleObject wrapper, HandleId id,
- bool* bp) const override;
- virtual bool get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
- HandleId id, MutableHandleValue vp) const override;
- virtual bool set(JSContext* cx, HandleObject wrapper, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result) const override;
- virtual bool call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
- virtual bool construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
- /* SpiderMonkey extensions. */
- virtual bool getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<PropertyDescriptor> desc) const override;
- virtual bool hasOwn(JSContext* cx, HandleObject wrapper, HandleId id,
- bool* bp) const override;
- virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
- AutoIdVector& props) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override;
- virtual bool isArray(JSContext* cx, HandleObject obj,
- JS::IsArrayAnswer* answer) const override;
- virtual const char* className(JSContext* cx, HandleObject wrapper) const override;
- virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override;
- static const OpaqueCrossCompartmentWrapper singleton;
- };
- /*
- * Base class for security wrappers. A security wrapper is potentially hiding
- * all or part of some wrapped object thus SecurityWrapper defaults to denying
- * access to the wrappee. This is the opposite of Wrapper which tries to be
- * completely transparent.
- *
- * NB: Currently, only a few ProxyHandler operations are overridden to deny
- * access, relying on derived SecurityWrapper to block access when necessary.
- */
- template <class Base>
- class JS_FRIEND_API(SecurityWrapper) : public Base
- {
- public:
- explicit constexpr SecurityWrapper(unsigned flags, bool hasPrototype = false)
- : Base(flags, hasPrototype, /* hasSecurityPolicy = */ true)
- { }
- virtual bool enter(JSContext* cx, HandleObject wrapper, HandleId id, Wrapper::Action act,
- bool* bp) const override;
- virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<PropertyDescriptor> desc,
- ObjectOpResult& result) const override;
- virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
- virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
- ObjectOpResult& result) const override;
- virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
- ObjectOpResult& result) const override;
- virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy, bool* succeeded) const override;
- virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
- const CallArgs& args) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override;
- virtual bool isArray(JSContext* cx, HandleObject wrapper, JS::IsArrayAnswer* answer) const override;
- virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
- virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
- // Allow isCallable and isConstructor. They used to be class-level, and so could not be guarded
- // against.
- virtual bool watch(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
- JS::HandleObject callable) const override;
- virtual bool unwatch(JSContext* cx, JS::HandleObject proxy, JS::HandleId id) const override;
- /*
- * Allow our subclasses to select the superclass behavior they want without
- * needing to specify an exact superclass.
- */
- typedef Base Permissive;
- typedef SecurityWrapper<Base> Restrictive;
- };
- typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
- extern JSObject*
- TransparentObjectWrapper(JSContext* cx, HandleObject existing, HandleObject obj);
- inline bool
- IsWrapper(JSObject* obj)
- {
- return IsProxy(obj) && GetProxyHandler(obj)->family() == &Wrapper::family;
- }
- // Given a JSObject, returns that object stripped of wrappers. If
- // stopAtWindowProxy is true, then this returns the WindowProxy if it was
- // previously wrapped. Otherwise, this returns the first object for
- // which JSObject::isWrapper returns false.
- JS_FRIEND_API(JSObject*)
- UncheckedUnwrap(JSObject* obj, bool stopAtWindowProxy = true, unsigned* flagsp = nullptr);
- // Given a JSObject, returns that object stripped of wrappers. At each stage,
- // the security wrapper has the opportunity to veto the unwrap. If
- // stopAtWindowProxy is true, then this returns the WindowProxy if it was
- // previously wrapped.
- JS_FRIEND_API(JSObject*)
- CheckedUnwrap(JSObject* obj, bool stopAtWindowProxy = true);
- // Unwrap only the outermost security wrapper, with the same semantics as
- // above. This is the checked version of Wrapper::wrappedObject.
- JS_FRIEND_API(JSObject*)
- UnwrapOneChecked(JSObject* obj, bool stopAtWindowProxy = true);
- JS_FRIEND_API(bool)
- IsCrossCompartmentWrapper(JSObject* obj);
- void
- NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper);
- void
- RemapWrapper(JSContext* cx, JSObject* wobj, JSObject* newTarget);
- JS_FRIEND_API(bool)
- RemapAllWrappersForObject(JSContext* cx, JSObject* oldTarget,
- JSObject* newTarget);
- // API to recompute all cross-compartment wrappers whose source and target
- // match the given filters.
- JS_FRIEND_API(bool)
- RecomputeWrappers(JSContext* cx, const CompartmentFilter& sourceFilter,
- const CompartmentFilter& targetFilter);
- } /* namespace js */
- #endif /* jswrapper_h */
|