Bug 1756164: part 2) Document the order of the external clipboard formats and remove...
[gecko.git] / dom / bindings / RemoteObjectProxy.cpp
blobf0f0e7d1be867cdaf0b2ba4e670503ebe86ad111
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()) {
20 return ok;
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
31 // step 3 and
32 // https://html.spec.whatwg.org/multipage/browsers.html#location-defineownproperty
33 // step 2
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-)
41 // step 2 and
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,
47 aProps)) {
48 return false;
51 // https://html.spec.whatwg.org/multipage/browsers.html#crossoriginownpropertykeys-(-o-)
52 // step 3 and 4
53 return xpc::AppendCrossOriginWhitelistedPropNames(aCx, aProps);
56 bool RemoteObjectProxyBase::delete_(JSContext* aCx,
57 JS::Handle<JSObject*> aProxy,
58 JS::Handle<jsid> aId,
59 JS::ObjectOpResult& aResult) const {
60 // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-delete
61 // step 3 and
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
70 // definition:
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.
77 *aIsOrdinary = true;
78 return true;
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
85 // and
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
94 // and
95 // https://html.spec.whatwg.org/multipage/browsers.html#location-isextensible
96 *aExtensible = true;
97 return true;
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 {
118 return true;
121 const char* RemoteObjectProxyBase::className(
122 JSContext* aCx, JS::Handle<JSObject*> aProxy) const {
123 MOZ_ASSERT(js::IsProxy(aProxy));
125 return "Object";
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 if (auto result = map.lookup(aNative)) {
136 MOZ_ASSERT(!aTransplantTo,
137 "No existing value allowed if we're doing a transplant");
139 aProxy.set(result->value());
141 // During a transplant, we put an object that is temporarily not a
142 // proxy object into the map. Make sure that we don't return one of
143 // these objects in the middle of a transplant.
144 MOZ_RELEASE_ASSERT(JS::GetClass(aProxy) == aClasp);
146 return;
149 js::ProxyOptions options;
150 options.setClass(aClasp);
151 JS::Rooted<JS::Value> native(aCx, JS::PrivateValue(aNative));
152 JS::Rooted<JSObject*> obj(
153 aCx, js::NewProxyObject(aCx, this, native, nullptr, options));
154 if (!obj) {
155 return;
158 bool success;
159 if (!JS_SetImmutablePrototype(aCx, obj, &success)) {
160 return;
162 MOZ_ASSERT(success);
164 aNewObjectCreated = true;
166 // If we're transplanting onto an object, we want to make sure that it does
167 // not have the same class as aClasp to ensure that the release assert earlier
168 // in this function will actually fire if we try to return a proxy object in
169 // the middle of a transplant.
170 MOZ_ASSERT_IF(aTransplantTo, JS::GetClass(aTransplantTo) != aClasp);
172 if (!map.put(aNative, aTransplantTo ? aTransplantTo : obj)) {
173 return;
176 aProxy.set(obj);
179 const char RemoteObjectProxyBase::sCrossOriginProxyFamily = 0;
181 } // namespace mozilla::dom