1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
7 #ifndef mozilla_dom_RemoteObjectProxy_h
8 #define mozilla_dom_RemoteObjectProxy_h
11 #include "mozilla/Maybe.h"
12 #include "mozilla/dom/MaybeCrossOriginObject.h"
13 #include "mozilla/dom/PrototypeList.h"
14 #include "xpcpublic.h"
16 namespace mozilla::dom
{
18 class BrowsingContext
;
21 * Base class for RemoteObjectProxy. Implements the pieces of the handler that
22 * don't depend on properties/methods of the specific WebIDL interface that this
25 class RemoteObjectProxyBase
: public js::BaseProxyHandler
,
26 public MaybeCrossOriginObjectMixins
{
28 explicit constexpr RemoteObjectProxyBase(prototypes::ID aPrototypeID
)
29 : BaseProxyHandler(&sCrossOriginProxyFamily
, false),
30 mPrototypeID(aPrototypeID
) {}
33 bool finalizeInBackground(const JS::Value
& priv
) const final
{ return false; }
35 // Standard internal methods
36 bool getOwnPropertyDescriptor(
37 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
, JS::Handle
<jsid
> aId
,
38 JS::MutableHandle
<Maybe
<JS::PropertyDescriptor
>> aDesc
) const override
;
39 bool ownPropertyKeys(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
40 JS::MutableHandleVector
<jsid
> aProps
) const override
;
41 bool defineProperty(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
43 JS::Handle
<JS::PropertyDescriptor
> aDesc
,
44 JS::ObjectOpResult
& result
) const final
;
45 bool delete_(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
46 JS::Handle
<jsid
> aId
, JS::ObjectOpResult
& aResult
) const final
;
48 bool getPrototypeIfOrdinary(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
50 JS::MutableHandle
<JSObject
*> aProtop
) const final
;
52 bool preventExtensions(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
53 JS::ObjectOpResult
& aResult
) const final
;
54 bool isExtensible(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
55 bool* aExtensible
) const final
;
57 bool get(JSContext
* cx
, JS::Handle
<JSObject
*> aProxy
,
58 JS::Handle
<JS::Value
> aReceiver
, JS::Handle
<jsid
> aId
,
59 JS::MutableHandle
<JS::Value
> aVp
) const final
;
60 bool set(JSContext
* cx
, JS::Handle
<JSObject
*> aProxy
, JS::Handle
<jsid
> aId
,
61 JS::Handle
<JS::Value
> aValue
, JS::Handle
<JS::Value
> aReceiver
,
62 JS::ObjectOpResult
& aResult
) const final
;
64 // SpiderMonkey extensions
65 bool getOwnEnumerablePropertyKeys(
66 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
67 JS::MutableHandleVector
<jsid
> aProps
) const override
;
68 const char* className(JSContext
* aCx
,
69 JS::Handle
<JSObject
*> aProxy
) const final
;
71 // Cross origin objects like RemoteWindowProxy should not participate in
73 virtual bool throwOnPrivateField() const override
{ return true; }
75 bool isCallable(JSObject
* aObj
) const final
{ return false; }
76 bool isConstructor(JSObject
* aObj
) const final
{ return false; }
78 virtual void NoteChildren(JSObject
* aProxy
,
79 nsCycleCollectionTraversalCallback
& aCb
) const = 0;
81 static void* GetNative(JSObject
* aProxy
) {
82 return js::GetProxyPrivate(aProxy
).toPrivate();
86 * Returns true if aProxy is a cross-process proxy that represents
87 * an object implementing the WebIDL interface for aProtoID. aProxy
88 * should be a proxy object.
90 static inline bool IsRemoteObjectProxy(JSObject
* aProxy
,
91 prototypes::ID aProtoID
) {
92 const js::BaseProxyHandler
* handler
= js::GetProxyHandler(aProxy
);
93 return handler
->family() == &sCrossOriginProxyFamily
&&
94 static_cast<const RemoteObjectProxyBase
*>(handler
)->mPrototypeID
==
99 * Returns true if aProxy is a cross-process proxy, no matter which
100 * interface it represents. aProxy should be a proxy object.
102 static inline bool IsRemoteObjectProxy(JSObject
* aProxy
) {
103 const js::BaseProxyHandler
* handler
= js::GetProxyHandler(aProxy
);
104 return handler
->family() == &sCrossOriginProxyFamily
;
109 * Gets an existing cached proxy object, or creates a new one and caches it.
110 * aProxy will be null on failure. aNewObjectCreated is set to true if a new
111 * object was created, callers probably need to addref the native in that
112 * case. aNewObjectCreated can be true even if aProxy is null, if something
113 * failed after creating the object.
115 void GetOrCreateProxyObject(JSContext
* aCx
, void* aNative
,
116 const JSClass
* aClasp
,
117 JS::Handle
<JSObject
*> aTransplantTo
,
118 JS::MutableHandle
<JSObject
*> aProxy
,
119 bool& aNewObjectCreated
) const;
121 const prototypes::ID mPrototypeID
;
123 friend struct SetDOMProxyInformation
;
124 static const char sCrossOriginProxyFamily
;
128 * Proxy handler for proxy objects that represent an object implementing a
129 * WebIDL interface that has cross-origin accessible properties/methods, and
130 * which lives in a different process. The WebIDL code generator will create
131 * arrays of cross-origin accessible properties/methods that can be used as
132 * arguments to this template.
134 * The properties and methods can be cached on a holder JSObject, stored in a
135 * reserved slot on the proxy object.
137 * The proxy objects that use a handler derived from this one are stored in a
138 * hash map in the JS compartment's private (@see
139 * xpc::CompartmentPrivate::GetRemoteProxyMap).
141 template <class Native
, const CrossOriginProperties
& P
>
142 class RemoteObjectProxy
: public RemoteObjectProxyBase
{
144 void finalize(JS::GCContext
* aGcx
, JSObject
* aProxy
) const final
{
145 auto native
= static_cast<Native
*>(GetNative(aProxy
));
146 RefPtr
<Native
> self(dont_AddRef(native
));
149 void GetProxyObject(JSContext
* aCx
, Native
* aNative
,
150 JS::Handle
<JSObject
*> aTransplantTo
,
151 JS::MutableHandle
<JSObject
*> aProxy
) const {
152 bool objectCreated
= false;
153 GetOrCreateProxyObject(aCx
, aNative
, &sClass
, aTransplantTo
, aProxy
,
161 using RemoteObjectProxyBase::RemoteObjectProxyBase
;
164 bool EnsureHolder(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
165 JS::MutableHandle
<JSObject
*> aHolder
) const final
{
166 return MaybeCrossOriginObjectMixins::EnsureHolder(
167 aCx
, aProxy
, /* slot = */ 0, P
, aHolder
);
170 static const JSClass sClass
;
174 * Returns true if aObj is a cross-process proxy object that
175 * represents an object implementing the WebIDL interface for
178 inline bool IsRemoteObjectProxy(JSObject
* aObj
, prototypes::ID aProtoID
) {
179 if (!js::IsProxy(aObj
)) {
182 return RemoteObjectProxyBase::IsRemoteObjectProxy(aObj
, aProtoID
);
186 * Returns true if aObj is a cross-process proxy object, no matter
187 * which WebIDL interface it corresponds to.
189 inline bool IsRemoteObjectProxy(JSObject
* aObj
) {
190 if (!js::IsProxy(aObj
)) {
193 return RemoteObjectProxyBase::IsRemoteObjectProxy(aObj
);
197 * Return the browsing context for this remote outer window proxy.
198 * Only call this function on remote outer window proxies.
200 BrowsingContext
* GetBrowsingContext(JSObject
* aProxy
);
202 } // namespace mozilla::dom
204 #endif /* mozilla_dom_RemoteObjectProxy_h */