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 #include "RemoteObjectProxy.h"
8 #include "AccessCheck.h"
9 #include "jsfriendapi.h"
10 #include "js/Object.h" // JS::GetClass
11 #include "xpcprivate.h"
13 namespace mozilla::dom
{
15 bool RemoteObjectProxyBase::getOwnPropertyDescriptor(
16 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
, JS::Handle
<jsid
> aId
,
17 JS::MutableHandle
<Maybe
<JS::PropertyDescriptor
>> aDesc
) const {
18 bool ok
= CrossOriginGetOwnPropertyHelper(aCx
, aProxy
, aId
, aDesc
);
19 if (!ok
|| aDesc
.isSome()) {
23 return CrossOriginPropertyFallback(aCx
, aProxy
, aId
, aDesc
);
26 bool RemoteObjectProxyBase::defineProperty(
27 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
, JS::Handle
<jsid
> aId
,
28 JS::Handle
<JS::PropertyDescriptor
> aDesc
,
29 JS::ObjectOpResult
& aResult
) const {
30 // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-defineownproperty
32 // https://html.spec.whatwg.org/multipage/browsers.html#location-defineownproperty
34 return ReportCrossOriginDenial(aCx
, aId
, "define"_ns
);
37 bool RemoteObjectProxyBase::ownPropertyKeys(
38 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
39 JS::MutableHandleVector
<jsid
> aProps
) const {
40 // https://html.spec.whatwg.org/multipage/browsers.html#crossoriginownpropertykeys-(-o-)
42 // https://html.spec.whatwg.org/multipage/browsers.html#crossoriginproperties-(-o-)
43 JS::Rooted
<JSObject
*> holder(aCx
);
44 if (!EnsureHolder(aCx
, aProxy
, &holder
) ||
45 !js::GetPropertyKeys(aCx
, holder
,
46 JSITER_OWNONLY
| JSITER_HIDDEN
| JSITER_SYMBOLS
,
51 // https://html.spec.whatwg.org/multipage/browsers.html#crossoriginownpropertykeys-(-o-)
53 return xpc::AppendCrossOriginWhitelistedPropNames(aCx
, aProps
);
56 bool RemoteObjectProxyBase::delete_(JSContext
* aCx
,
57 JS::Handle
<JSObject
*> aProxy
,
59 JS::ObjectOpResult
& aResult
) const {
60 // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-delete
62 // https://html.spec.whatwg.org/multipage/browsers.html#location-delete step 2
63 return ReportCrossOriginDenial(aCx
, aId
, "delete"_ns
);
66 bool RemoteObjectProxyBase::getPrototypeIfOrdinary(
67 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
, bool* aIsOrdinary
,
68 JS::MutableHandle
<JSObject
*> aProtop
) const {
69 // WindowProxy's and Location's [[GetPrototypeOf]] traps aren't the ordinary
72 // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof
73 // https://html.spec.whatwg.org/multipage/browsers.html#location-getprototypeof
75 // We nonetheless can implement it with a static [[Prototype]], because the
76 // [[GetPrototypeOf]] trap should always return null.
81 bool RemoteObjectProxyBase::preventExtensions(
82 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
83 JS::ObjectOpResult
& aResult
) const {
84 // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-preventextensions
86 // https://html.spec.whatwg.org/multipage/browsers.html#location-preventextensions
87 return aResult
.failCantPreventExtensions();
90 bool RemoteObjectProxyBase::isExtensible(JSContext
* aCx
,
91 JS::Handle
<JSObject
*> aProxy
,
92 bool* aExtensible
) const {
93 // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-isextensible
95 // https://html.spec.whatwg.org/multipage/browsers.html#location-isextensible
100 bool RemoteObjectProxyBase::get(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
101 JS::Handle
<JS::Value
> aReceiver
,
102 JS::Handle
<jsid
> aId
,
103 JS::MutableHandle
<JS::Value
> aVp
) const {
104 return CrossOriginGet(aCx
, aProxy
, aReceiver
, aId
, aVp
);
107 bool RemoteObjectProxyBase::set(JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
108 JS::Handle
<jsid
> aId
,
109 JS::Handle
<JS::Value
> aValue
,
110 JS::Handle
<JS::Value
> aReceiver
,
111 JS::ObjectOpResult
& aResult
) const {
112 return CrossOriginSet(aCx
, aProxy
, aId
, aValue
, aReceiver
, aResult
);
115 bool RemoteObjectProxyBase::getOwnEnumerablePropertyKeys(
116 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
,
117 JS::MutableHandleVector
<jsid
> aProps
) const {
121 const char* RemoteObjectProxyBase::className(
122 JSContext
* aCx
, JS::Handle
<JSObject
*> aProxy
) const {
123 MOZ_ASSERT(js::IsProxy(aProxy
));
128 void RemoteObjectProxyBase::GetOrCreateProxyObject(
129 JSContext
* aCx
, void* aNative
, const JSClass
* aClasp
,
130 JS::Handle
<JSObject
*> aTransplantTo
, JS::MutableHandle
<JSObject
*> aProxy
,
131 bool& aNewObjectCreated
) const {
132 xpc::CompartmentPrivate
* priv
=
133 xpc::CompartmentPrivate::Get(JS::CurrentGlobalOrNull(aCx
));
134 xpc::CompartmentPrivate::RemoteProxyMap
& map
= priv
->GetRemoteProxyMap();
135 auto result
= map
.lookupForAdd(aNative
);
137 MOZ_ASSERT(!aTransplantTo
,
138 "No existing value allowed if we're doing a transplant");
140 aProxy
.set(result
->value());
142 // During a transplant, we put an object that is temporarily not a
143 // proxy object into the map. Make sure that we don't return one of
144 // these objects in the middle of a transplant.
145 MOZ_RELEASE_ASSERT(JS::GetClass(aProxy
) == aClasp
);
150 js::ProxyOptions options
;
151 options
.setClass(aClasp
);
152 JS::Rooted
<JS::Value
> native(aCx
, JS::PrivateValue(aNative
));
153 JS::Rooted
<JSObject
*> obj(
154 aCx
, js::NewProxyObject(aCx
, this, native
, nullptr, options
));
160 if (!JS_SetImmutablePrototype(aCx
, obj
, &success
)) {
165 aNewObjectCreated
= true;
167 // If we're transplanting onto an object, we want to make sure that it does
168 // not have the same class as aClasp to ensure that the release assert earlier
169 // in this function will actually fire if we try to return a proxy object in
170 // the middle of a transplant.
171 MOZ_ASSERT_IF(aTransplantTo
, JS::GetClass(aTransplantTo
) != aClasp
);
173 if (!map
.add(result
, aNative
, aTransplantTo
? aTransplantTo
: obj
)) {
180 const char RemoteObjectProxyBase::sCrossOriginProxyFamily
= 0;
182 } // namespace mozilla::dom