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/. */
10 #include "mozilla/Attributes.h"
16 class DummyFrameGuard
;
19 * Helper for Wrapper::New default options.
21 * Callers of Wrapper::New() who wish to specify a prototype for the created
22 * Wrapper, *MUST* construct a WrapperOptions with a JSContext.
24 class MOZ_STACK_CLASS WrapperOptions
: public ProxyOptions
{
26 WrapperOptions() : ProxyOptions(false, nullptr),
30 explicit WrapperOptions(JSContext
* cx
) : ProxyOptions(false, nullptr),
36 inline JSObject
* proto() const;
37 WrapperOptions
& setProto(JSObject
* protoArg
) {
44 mozilla::Maybe
<JS::RootedObject
> proto_
;
48 * A wrapper is a proxy with a target object to which it generally forwards
49 * operations, but may restrict access to certain operations or instrument
50 * the trap operations in various ways. A wrapper is distinct from a Direct Proxy
51 * Handler in the sense that it can be "unwrapped" in C++, exposing the underlying
52 * object (Direct Proxy Handlers have an underlying target object, but don't
53 * expect to expose this object via any kind of unwrapping operation). Callers
54 * should be careful to avoid unwrapping security wrappers in the wrong context.
56 class JS_FRIEND_API(Wrapper
) : public DirectProxyHandler
61 using BaseProxyHandler::Action
;
64 CROSS_COMPARTMENT
= 1 << 0,
65 LAST_USED_FLAG
= CROSS_COMPARTMENT
68 virtual bool defaultValue(JSContext
* cx
, HandleObject obj
, JSType hint
,
69 MutableHandleValue vp
) const MOZ_OVERRIDE
;
71 static JSObject
* New(JSContext
* cx
, JSObject
* obj
, JSObject
* parent
, const Wrapper
* handler
,
72 const WrapperOptions
* options
= nullptr);
74 static JSObject
* Renew(JSContext
* cx
, JSObject
* existing
, JSObject
* obj
, const Wrapper
* handler
);
76 static const Wrapper
* wrapperHandler(JSObject
* wrapper
);
78 static JSObject
* wrappedObject(JSObject
* wrapper
);
80 unsigned flags() const {
84 explicit MOZ_CONSTEXPR
Wrapper(unsigned aFlags
, bool aHasPrototype
= false,
85 bool aHasSecurityPolicy
= false)
86 : DirectProxyHandler(&family
, aHasPrototype
, aHasSecurityPolicy
),
90 virtual bool finalizeInBackground(Value priv
) const MOZ_OVERRIDE
;
92 static const char family
;
93 static const Wrapper singleton
;
94 static const Wrapper singletonWithPrototype
;
96 static JSObject
* defaultProto
;
100 WrapperOptions::proto() const
102 return proto_
? *proto_
: Wrapper::defaultProto
;
105 /* Base class for all cross compartment wrapper handlers. */
106 class JS_FRIEND_API(CrossCompartmentWrapper
) : public Wrapper
109 explicit MOZ_CONSTEXPR
CrossCompartmentWrapper(unsigned aFlags
, bool aHasPrototype
= false,
110 bool aHasSecurityPolicy
= false)
111 : Wrapper(CROSS_COMPARTMENT
| aFlags
, aHasPrototype
, aHasSecurityPolicy
)
114 /* ES5 Harmony fundamental wrapper traps. */
115 virtual bool preventExtensions(JSContext
* cx
, HandleObject wrapper
) const MOZ_OVERRIDE
;
116 virtual bool getPropertyDescriptor(JSContext
* cx
, HandleObject wrapper
, HandleId id
,
117 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
118 virtual bool getOwnPropertyDescriptor(JSContext
* cx
, HandleObject wrapper
, HandleId id
,
119 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
120 virtual bool defineProperty(JSContext
* cx
, HandleObject wrapper
, HandleId id
,
121 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
122 virtual bool getOwnPropertyNames(JSContext
* cx
, HandleObject wrapper
,
123 AutoIdVector
& props
) const MOZ_OVERRIDE
;
124 virtual bool delete_(JSContext
* cx
, HandleObject wrapper
, HandleId id
, bool* bp
) const MOZ_OVERRIDE
;
125 virtual bool enumerate(JSContext
* cx
, HandleObject wrapper
, AutoIdVector
& props
) const MOZ_OVERRIDE
;
127 /* ES5 Harmony derived wrapper traps. */
128 virtual bool has(JSContext
* cx
, HandleObject wrapper
, HandleId id
, bool* bp
) const MOZ_OVERRIDE
;
129 virtual bool hasOwn(JSContext
* cx
, HandleObject wrapper
, HandleId id
, bool* bp
) const MOZ_OVERRIDE
;
130 virtual bool get(JSContext
* cx
, HandleObject wrapper
, HandleObject receiver
,
131 HandleId id
, MutableHandleValue vp
) const MOZ_OVERRIDE
;
132 virtual bool set(JSContext
* cx
, HandleObject wrapper
, HandleObject receiver
,
133 HandleId id
, bool strict
, MutableHandleValue vp
) const MOZ_OVERRIDE
;
134 virtual bool keys(JSContext
* cx
, HandleObject wrapper
, AutoIdVector
& props
) const MOZ_OVERRIDE
;
135 virtual bool iterate(JSContext
* cx
, HandleObject wrapper
, unsigned flags
,
136 MutableHandleValue vp
) const MOZ_OVERRIDE
;
138 /* Spidermonkey extensions. */
139 virtual bool isExtensible(JSContext
* cx
, HandleObject wrapper
, bool* extensible
) const MOZ_OVERRIDE
;
140 virtual bool call(JSContext
* cx
, HandleObject wrapper
, const CallArgs
& args
) const MOZ_OVERRIDE
;
141 virtual bool construct(JSContext
* cx
, HandleObject wrapper
, const CallArgs
& args
) const MOZ_OVERRIDE
;
142 virtual bool nativeCall(JSContext
* cx
, IsAcceptableThis test
, NativeImpl impl
,
143 CallArgs args
) const MOZ_OVERRIDE
;
144 virtual bool hasInstance(JSContext
* cx
, HandleObject wrapper
, MutableHandleValue v
,
145 bool* bp
) const MOZ_OVERRIDE
;
146 virtual const char* className(JSContext
* cx
, HandleObject proxy
) const MOZ_OVERRIDE
;
147 virtual JSString
* fun_toString(JSContext
* cx
, HandleObject wrapper
,
148 unsigned indent
) const MOZ_OVERRIDE
;
149 virtual bool regexp_toShared(JSContext
* cx
, HandleObject proxy
, RegExpGuard
* g
) const MOZ_OVERRIDE
;
150 virtual bool boxedValue_unbox(JSContext
* cx
, HandleObject proxy
, MutableHandleValue vp
) const MOZ_OVERRIDE
;
151 virtual bool defaultValue(JSContext
* cx
, HandleObject wrapper
, JSType hint
,
152 MutableHandleValue vp
) const MOZ_OVERRIDE
;
153 virtual bool getPrototypeOf(JSContext
* cx
, HandleObject proxy
,
154 MutableHandleObject protop
) const MOZ_OVERRIDE
;
155 virtual bool setPrototypeOf(JSContext
* cx
, HandleObject proxy
, HandleObject proto
,
156 bool* bp
) const MOZ_OVERRIDE
;
158 static const CrossCompartmentWrapper singleton
;
159 static const CrossCompartmentWrapper singletonWithPrototype
;
163 * Base class for security wrappers. A security wrapper is potentially hiding
164 * all or part of some wrapped object thus SecurityWrapper defaults to denying
165 * access to the wrappee. This is the opposite of Wrapper which tries to be
166 * completely transparent.
168 * NB: Currently, only a few ProxyHandler operations are overridden to deny
169 * access, relying on derived SecurityWrapper to block access when necessary.
171 template <class Base
>
172 class JS_FRIEND_API(SecurityWrapper
) : public Base
175 explicit MOZ_CONSTEXPR
SecurityWrapper(unsigned flags
, bool hasPrototype
= false)
176 : Base(flags
, hasPrototype
, /* hasSecurityPolicy = */ true)
179 virtual bool isExtensible(JSContext
* cx
, HandleObject wrapper
, bool* extensible
) const MOZ_OVERRIDE
;
180 virtual bool preventExtensions(JSContext
* cx
, HandleObject wrapper
) const MOZ_OVERRIDE
;
181 virtual bool enter(JSContext
* cx
, HandleObject wrapper
, HandleId id
, Wrapper::Action act
,
182 bool* bp
) const MOZ_OVERRIDE
;
183 virtual bool nativeCall(JSContext
* cx
, IsAcceptableThis test
, NativeImpl impl
,
184 CallArgs args
) const MOZ_OVERRIDE
;
185 virtual bool defaultValue(JSContext
* cx
, HandleObject wrapper
, JSType hint
,
186 MutableHandleValue vp
) const MOZ_OVERRIDE
;
187 virtual bool objectClassIs(HandleObject obj
, ESClassValue classValue
,
188 JSContext
* cx
) const MOZ_OVERRIDE
;
189 virtual bool regexp_toShared(JSContext
* cx
, HandleObject proxy
, RegExpGuard
* g
) const MOZ_OVERRIDE
;
190 virtual bool boxedValue_unbox(JSContext
* cx
, HandleObject proxy
, MutableHandleValue vp
) const MOZ_OVERRIDE
;
191 virtual bool defineProperty(JSContext
* cx
, HandleObject wrapper
, HandleId id
,
192 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
194 virtual bool setPrototypeOf(JSContext
* cx
, HandleObject proxy
, HandleObject proto
,
195 bool* bp
) const MOZ_OVERRIDE
;
197 virtual bool watch(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleId id
,
198 JS::HandleObject callable
) const MOZ_OVERRIDE
;
199 virtual bool unwatch(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleId id
) const MOZ_OVERRIDE
;
202 * Allow our subclasses to select the superclass behavior they want without
203 * needing to specify an exact superclass.
205 typedef Base Permissive
;
206 typedef SecurityWrapper
<Base
> Restrictive
;
209 typedef SecurityWrapper
<Wrapper
> SameCompartmentSecurityWrapper
;
210 typedef SecurityWrapper
<CrossCompartmentWrapper
> CrossCompartmentSecurityWrapper
;
212 class JS_FRIEND_API(DeadObjectProxy
) : public BaseProxyHandler
215 explicit MOZ_CONSTEXPR
DeadObjectProxy()
216 : BaseProxyHandler(&family
)
219 /* ES5 Harmony fundamental wrapper traps. */
220 virtual bool preventExtensions(JSContext
* cx
, HandleObject proxy
) const MOZ_OVERRIDE
;
221 virtual bool getPropertyDescriptor(JSContext
* cx
, HandleObject wrapper
, HandleId id
,
222 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
223 virtual bool getOwnPropertyDescriptor(JSContext
* cx
, HandleObject wrapper
, HandleId id
,
224 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
225 virtual bool defineProperty(JSContext
* cx
, HandleObject wrapper
, HandleId id
,
226 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
227 virtual bool getOwnPropertyNames(JSContext
* cx
, HandleObject wrapper
,
228 AutoIdVector
& props
) const MOZ_OVERRIDE
;
229 virtual bool delete_(JSContext
* cx
, HandleObject wrapper
, HandleId id
, bool* bp
) const MOZ_OVERRIDE
;
230 virtual bool enumerate(JSContext
* cx
, HandleObject wrapper
, AutoIdVector
& props
) const MOZ_OVERRIDE
;
232 /* Spidermonkey extensions. */
233 virtual bool isExtensible(JSContext
* cx
, HandleObject proxy
, bool* extensible
) const MOZ_OVERRIDE
;
234 virtual bool call(JSContext
* cx
, HandleObject proxy
, const CallArgs
& args
) const MOZ_OVERRIDE
;
235 virtual bool construct(JSContext
* cx
, HandleObject proxy
, const CallArgs
& args
) const MOZ_OVERRIDE
;
236 virtual bool nativeCall(JSContext
* cx
, IsAcceptableThis test
, NativeImpl impl
,
237 CallArgs args
) const MOZ_OVERRIDE
;
238 virtual bool hasInstance(JSContext
* cx
, HandleObject proxy
, MutableHandleValue v
,
239 bool* bp
) const MOZ_OVERRIDE
;
240 virtual bool objectClassIs(HandleObject obj
, ESClassValue classValue
,
241 JSContext
* cx
) const MOZ_OVERRIDE
;
242 virtual const char* className(JSContext
* cx
, HandleObject proxy
) const MOZ_OVERRIDE
;
243 virtual JSString
* fun_toString(JSContext
* cx
, HandleObject proxy
, unsigned indent
) const MOZ_OVERRIDE
;
244 virtual bool regexp_toShared(JSContext
* cx
, HandleObject proxy
, RegExpGuard
* g
) const MOZ_OVERRIDE
;
245 virtual bool defaultValue(JSContext
* cx
, HandleObject obj
, JSType hint
,
246 MutableHandleValue vp
) const MOZ_OVERRIDE
;
247 virtual bool getPrototypeOf(JSContext
* cx
, HandleObject proxy
,
248 MutableHandleObject protop
) const MOZ_OVERRIDE
;
250 static const char family
;
251 static const DeadObjectProxy singleton
;
255 TransparentObjectWrapper(JSContext
* cx
, HandleObject existing
, HandleObject obj
,
256 HandleObject parent
);
259 IsWrapper(JSObject
* obj
)
261 return IsProxy(obj
) && GetProxyHandler(obj
)->family() == &Wrapper::family
;
264 // Given a JSObject, returns that object stripped of wrappers. If
265 // stopAtOuter is true, then this returns the outer window if it was
266 // previously wrapped. Otherwise, this returns the first object for
267 // which JSObject::isWrapper returns false.
268 JS_FRIEND_API(JSObject
*)
269 UncheckedUnwrap(JSObject
* obj
, bool stopAtOuter
= true, unsigned* flagsp
= nullptr);
271 // Given a JSObject, returns that object stripped of wrappers. At each stage,
272 // the security wrapper has the opportunity to veto the unwrap. Since checked
273 // code should never be unwrapping outer window wrappers, we always stop at
275 JS_FRIEND_API(JSObject
*)
276 CheckedUnwrap(JSObject
* obj
, bool stopAtOuter
= true);
278 // Unwrap only the outermost security wrapper, with the same semantics as
279 // above. This is the checked version of Wrapper::wrappedObject.
280 JS_FRIEND_API(JSObject
*)
281 UnwrapOneChecked(JSObject
* obj
, bool stopAtOuter
= true);
284 IsCrossCompartmentWrapper(JSObject
* obj
);
287 IsDeadProxyObject(JSObject
* obj
);
290 NewDeadProxyObject(JSContext
* cx
, JSObject
* parent
,
291 const ProxyOptions
& options
= ProxyOptions());
294 NukeCrossCompartmentWrapper(JSContext
* cx
, JSObject
* wrapper
);
297 RemapWrapper(JSContext
* cx
, JSObject
* wobj
, JSObject
* newTarget
);
300 RemapAllWrappersForObject(JSContext
* cx
, JSObject
* oldTarget
,
301 JSObject
* newTarget
);
303 // API to recompute all cross-compartment wrappers whose source and target
304 // match the given filters.
306 RecomputeWrappers(JSContext
* cx
, const CompartmentFilter
& sourceFilter
,
307 const CompartmentFilter
& targetFilter
);
311 #endif /* jswrapper_h */