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
|