Line data Source code
1 : /* THIS FILE IS AUTOGENERATED FROM Permissions.webidl BY Codegen.py - DO NOT EDIT */
2 :
3 : #include "AtomList.h"
4 : #include "PermissionsBinding.h"
5 : #include "WrapperFactory.h"
6 : #include "jsapi.h"
7 : #include "mozilla/OwningNonNull.h"
8 : #include "mozilla/Preferences.h"
9 : #include "mozilla/dom/BindingUtils.h"
10 : #include "mozilla/dom/DOMJSClass.h"
11 : #include "mozilla/dom/NonRefcountedDOMObject.h"
12 : #include "mozilla/dom/Permissions.h"
13 : #include "mozilla/dom/Promise.h"
14 : #include "mozilla/dom/ScriptSettings.h"
15 : #include "mozilla/dom/SimpleGlobalObject.h"
16 : #include "mozilla/dom/ToJSValue.h"
17 : #include "mozilla/dom/XrayExpandoClass.h"
18 :
19 : namespace mozilla {
20 : namespace dom {
21 :
22 : namespace PermissionNameValues {
23 : extern const EnumEntry strings[5] = {
24 : {"geolocation", 11},
25 : {"notifications", 13},
26 : {"push", 4},
27 : {"persistent-storage", 18},
28 : { nullptr, 0 }
29 : };
30 : } // namespace PermissionNameValues
31 :
32 : bool
33 0 : ToJSValue(JSContext* aCx, PermissionName aArgument, JS::MutableHandle<JS::Value> aValue)
34 : {
35 0 : MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(PermissionNameValues::strings));
36 : JSString* resultStr =
37 0 : JS_NewStringCopyN(aCx, PermissionNameValues::strings[uint32_t(aArgument)].value,
38 0 : PermissionNameValues::strings[uint32_t(aArgument)].length);
39 0 : if (!resultStr) {
40 0 : return false;
41 : }
42 0 : aValue.setString(resultStr);
43 0 : return true;
44 : }
45 :
46 :
47 :
48 0 : PermissionDescriptor::PermissionDescriptor()
49 : {
50 : // Safe to pass a null context if we pass a null value
51 0 : Init(nullptr, JS::NullHandleValue);
52 0 : }
53 :
54 :
55 :
56 : bool
57 0 : PermissionDescriptor::InitIds(JSContext* cx, PermissionDescriptorAtoms* atomsCache)
58 : {
59 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
60 :
61 : // Initialize these in reverse order so that any failure leaves the first one
62 : // uninitialized.
63 0 : if (!atomsCache->name_id.init(cx, "name")) {
64 0 : return false;
65 : }
66 0 : return true;
67 : }
68 :
69 : bool
70 0 : PermissionDescriptor::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
71 : {
72 : // Passing a null JSContext is OK only if we're initing from null,
73 : // Since in that case we will not have to do any property gets
74 : // Also evaluate isNullOrUndefined in order to avoid false-positive
75 : // checkers by static analysis tools
76 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
77 0 : PermissionDescriptorAtoms* atomsCache = nullptr;
78 0 : if (cx) {
79 0 : atomsCache = GetAtomCache<PermissionDescriptorAtoms>(cx);
80 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
81 0 : return false;
82 : }
83 : }
84 :
85 0 : if (!IsConvertibleToDictionary(val)) {
86 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
87 : }
88 :
89 0 : bool isNull = val.isNullOrUndefined();
90 : // We only need these if !isNull, in which case we have |cx|.
91 0 : Maybe<JS::Rooted<JSObject *> > object;
92 0 : Maybe<JS::Rooted<JS::Value> > temp;
93 0 : if (!isNull) {
94 0 : MOZ_ASSERT(cx);
95 0 : object.emplace(cx, &val.toObject());
96 0 : temp.emplace(cx);
97 : }
98 0 : if (!isNull) {
99 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->name_id, temp.ptr())) {
100 0 : return false;
101 : }
102 : }
103 0 : if (!isNull && !temp->isUndefined()) {
104 : {
105 : int index;
106 0 : if (!FindEnumStringIndex<true>(cx, temp.ref(), PermissionNameValues::strings, "PermissionName", "'name' member of PermissionDescriptor", &index)) {
107 0 : return false;
108 : }
109 0 : MOZ_ASSERT(index >= 0);
110 0 : mName = static_cast<PermissionName>(index);
111 : }
112 0 : mIsAnyMemberPresent = true;
113 0 : } else if (cx) {
114 : // Don't error out if we have no cx. In that
115 : // situation the caller is default-constructing us and we'll
116 : // just assume they know what they're doing.
117 0 : return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
118 0 : "'name' member of PermissionDescriptor");
119 : }
120 0 : return true;
121 : }
122 :
123 : bool
124 0 : PermissionDescriptor::Init(const nsAString& aJSON)
125 : {
126 0 : AutoJSAPI jsapi;
127 0 : JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
128 0 : if (!cleanGlobal) {
129 0 : return false;
130 : }
131 0 : if (!jsapi.Init(cleanGlobal)) {
132 0 : return false;
133 : }
134 0 : JSContext* cx = jsapi.cx();
135 0 : JS::Rooted<JS::Value> json(cx);
136 0 : bool ok = ParseJSON(cx, aJSON, &json);
137 0 : NS_ENSURE_TRUE(ok, false);
138 0 : return Init(cx, json);
139 : }
140 :
141 : bool
142 0 : PermissionDescriptor::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
143 : {
144 0 : PermissionDescriptorAtoms* atomsCache = GetAtomCache<PermissionDescriptorAtoms>(cx);
145 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
146 0 : return false;
147 : }
148 :
149 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
150 0 : if (!obj) {
151 0 : return false;
152 : }
153 0 : rval.set(JS::ObjectValue(*obj));
154 :
155 : do {
156 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
157 0 : JS::Rooted<JS::Value> temp(cx);
158 0 : PermissionName const & currentValue = mName;
159 0 : if (!ToJSValue(cx, currentValue, &temp)) {
160 0 : return false;
161 : }
162 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->name_id, temp, JSPROP_ENUMERATE)) {
163 0 : return false;
164 : }
165 0 : break;
166 : } while(0);
167 :
168 0 : return true;
169 : }
170 :
171 : bool
172 0 : PermissionDescriptor::ToJSON(nsAString& aJSON) const
173 : {
174 0 : AutoJSAPI jsapi;
175 0 : jsapi.Init();
176 0 : JSContext *cx = jsapi.cx();
177 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
178 : // because we'll only be creating objects, in ways that have no
179 : // side-effects, followed by a call to JS::ToJSONMaybeSafely,
180 : // which likewise guarantees no side-effects for the sorts of
181 : // things we will pass it.
182 0 : JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
183 0 : JS::Rooted<JS::Value> val(cx);
184 0 : if (!ToObjectInternal(cx, &val)) {
185 0 : return false;
186 : }
187 0 : JS::Rooted<JSObject*> obj(cx, &val.toObject());
188 0 : return StringifyToJSON(cx, obj, aJSON);
189 : }
190 :
191 : void
192 0 : PermissionDescriptor::TraceDictionary(JSTracer* trc)
193 : {
194 0 : }
195 :
196 : PermissionDescriptor&
197 0 : PermissionDescriptor::operator=(const PermissionDescriptor& aOther)
198 : {
199 0 : mName = aOther.mName;
200 0 : return *this;
201 : }
202 :
203 : namespace binding_detail {
204 : } // namespace binding_detail
205 :
206 :
207 : namespace PermissionsBinding {
208 :
209 : static bool
210 0 : query(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Permissions* self, const JSJitMethodCallArgs& args)
211 : {
212 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
213 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "Permissions.query");
214 : }
215 0 : JS::Rooted<JSObject*> arg0(cx);
216 0 : if (args[0].isObject()) {
217 0 : arg0 = &args[0].toObject();
218 : } else {
219 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of Permissions.query");
220 0 : return false;
221 : }
222 0 : binding_detail::FastErrorResult rv;
223 0 : auto result(StrongOrRawPtr<Promise>(self->Query(cx, arg0, rv)));
224 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
225 0 : return false;
226 : }
227 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
228 0 : if (!ToJSValue(cx, result, args.rval())) {
229 0 : return false;
230 : }
231 0 : return true;
232 : }
233 :
234 : static bool
235 0 : query_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Permissions* self, const JSJitMethodCallArgs& args)
236 : {
237 : // Make sure to save the callee before someone maybe messes
238 : // with rval().
239 0 : JS::Rooted<JSObject*> callee(cx, &args.callee());
240 0 : bool ok = query(cx, obj, self, args);
241 0 : if (ok) {
242 0 : return true;
243 : }
244 0 : return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
245 0 : args.rval());
246 : }
247 :
248 : static const JSJitInfo query_methodinfo = {
249 : { (JSJitGetterOp)query_promiseWrapper },
250 : { prototypes::id::Permissions },
251 : { PrototypeTraits<prototypes::id::Permissions>::Depth },
252 : JSJitInfo::Method,
253 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
254 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
255 : false, /* isInfallible. False in setters. */
256 : false, /* isMovable. Not relevant for setters. */
257 : false, /* isEliminatable. Not relevant for setters. */
258 : false, /* isAlwaysInSlot. Only relevant for getters. */
259 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
260 : false, /* isTypedMethod. Only relevant for methods. */
261 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
262 : };
263 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
264 : static_assert(0 < 1, "There is no slot for us");
265 :
266 : static bool
267 0 : revoke(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Permissions* self, const JSJitMethodCallArgs& args)
268 : {
269 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
270 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "Permissions.revoke");
271 : }
272 0 : JS::Rooted<JSObject*> arg0(cx);
273 0 : if (args[0].isObject()) {
274 0 : arg0 = &args[0].toObject();
275 : } else {
276 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of Permissions.revoke");
277 0 : return false;
278 : }
279 0 : binding_detail::FastErrorResult rv;
280 0 : auto result(StrongOrRawPtr<Promise>(self->Revoke(cx, arg0, rv)));
281 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
282 0 : return false;
283 : }
284 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
285 0 : if (!ToJSValue(cx, result, args.rval())) {
286 0 : return false;
287 : }
288 0 : return true;
289 : }
290 :
291 : static bool
292 0 : revoke_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Permissions* self, const JSJitMethodCallArgs& args)
293 : {
294 : // Make sure to save the callee before someone maybe messes
295 : // with rval().
296 0 : JS::Rooted<JSObject*> callee(cx, &args.callee());
297 0 : bool ok = revoke(cx, obj, self, args);
298 0 : if (ok) {
299 0 : return true;
300 : }
301 0 : return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
302 0 : args.rval());
303 : }
304 :
305 : static const JSJitInfo revoke_methodinfo = {
306 : { (JSJitGetterOp)revoke_promiseWrapper },
307 : { prototypes::id::Permissions },
308 : { PrototypeTraits<prototypes::id::Permissions>::Depth },
309 : JSJitInfo::Method,
310 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
311 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
312 : false, /* isInfallible. False in setters. */
313 : false, /* isMovable. Not relevant for setters. */
314 : false, /* isEliminatable. Not relevant for setters. */
315 : false, /* isAlwaysInSlot. Only relevant for getters. */
316 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
317 : false, /* isTypedMethod. Only relevant for methods. */
318 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
319 : };
320 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
321 : static_assert(0 < 1, "There is no slot for us");
322 :
323 : static bool
324 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
325 : {
326 0 : mozilla::dom::Permissions* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Permissions>(obj);
327 : // We don't want to preserve if we don't have a wrapper, and we
328 : // obviously can't preserve if we're not initialized.
329 0 : if (self && self->GetWrapperPreserveColor()) {
330 0 : PreserveWrapper(self);
331 : }
332 0 : return true;
333 : }
334 :
335 : static void
336 0 : _finalize(js::FreeOp* fop, JSObject* obj)
337 : {
338 0 : mozilla::dom::Permissions* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Permissions>(obj);
339 0 : if (self) {
340 0 : ClearWrapper(self, self, obj);
341 0 : AddForDeferredFinalization<mozilla::dom::Permissions>(self);
342 : }
343 0 : }
344 :
345 : static void
346 0 : _objectMoved(JSObject* obj, const JSObject* old)
347 : {
348 0 : mozilla::dom::Permissions* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Permissions>(obj);
349 0 : if (self) {
350 0 : UpdateWrapper(self, self, obj, old);
351 : }
352 0 : }
353 :
354 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
355 : #if defined(__clang__)
356 : #pragma clang diagnostic push
357 : #pragma clang diagnostic ignored "-Wmissing-braces"
358 : #endif
359 : static const JSFunctionSpec sMethods_specs[] = {
360 : JS_FNSPEC("query", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&query_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
361 : JS_FS_END,
362 : JS_FNSPEC("revoke", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&revoke_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
363 : JS_FS_END
364 : };
365 : #if defined(__clang__)
366 : #pragma clang diagnostic pop
367 : #endif
368 :
369 : static PrefableDisablers sMethods_disablers2 = {
370 : true, false, 0, nullptr
371 : };
372 :
373 : // Can't be const because the pref-enabled boolean needs to be writable
374 : static Prefable<const JSFunctionSpec> sMethods[] = {
375 : { nullptr, &sMethods_specs[0] },
376 : { &sMethods_disablers2, &sMethods_specs[2] },
377 : { nullptr, nullptr }
378 : };
379 :
380 : static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
381 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
382 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
383 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
384 :
385 :
386 : static uint16_t sNativeProperties_sortedPropertyIndices[2];
387 : static PropertyInfo sNativeProperties_propertyInfos[2];
388 :
389 : static const NativePropertiesN<1> sNativeProperties = {
390 : false, 0,
391 : false, 0,
392 : true, 0 /* sMethods */,
393 : false, 0,
394 : false, 0,
395 : false, 0,
396 : false, 0,
397 : -1,
398 : 2,
399 : sNativeProperties_sortedPropertyIndices,
400 : {
401 : { sMethods, &sNativeProperties_propertyInfos[0] }
402 : }
403 : };
404 : static_assert(2 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
405 : "We have a property info count that is oversized");
406 :
407 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
408 : {
409 : "Function",
410 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
411 : &sBoringInterfaceObjectClassClassOps,
412 : JS_NULL_CLASS_SPEC,
413 : JS_NULL_CLASS_EXT,
414 : &sInterfaceObjectClassObjectOps
415 : },
416 : eInterface,
417 : true,
418 : prototypes::id::Permissions,
419 : PrototypeTraits<prototypes::id::Permissions>::Depth,
420 : sNativePropertyHooks,
421 : "function Permissions() {\n [native code]\n}",
422 : JS::GetRealmFunctionPrototype
423 : };
424 :
425 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
426 : {
427 : "PermissionsPrototype",
428 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
429 : JS_NULL_CLASS_OPS,
430 : JS_NULL_CLASS_SPEC,
431 : JS_NULL_CLASS_EXT,
432 : JS_NULL_OBJECT_OPS
433 : },
434 : eInterfacePrototype,
435 : false,
436 : prototypes::id::Permissions,
437 : PrototypeTraits<prototypes::id::Permissions>::Depth,
438 : sNativePropertyHooks,
439 : "[object PermissionsPrototype]",
440 : JS::GetRealmObjectPrototype
441 : };
442 :
443 : JSObject*
444 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
445 : {
446 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
447 : }
448 :
449 : static const js::ClassOps sClassOps = {
450 : _addProperty, /* addProperty */
451 : nullptr, /* delProperty */
452 : nullptr, /* getProperty */
453 : nullptr, /* setProperty */
454 : nullptr, /* enumerate */
455 : nullptr, /* newEnumerate */
456 : nullptr, /* resolve */
457 : nullptr, /* mayResolve */
458 : _finalize, /* finalize */
459 : nullptr, /* call */
460 : nullptr, /* hasInstance */
461 : nullptr, /* construct */
462 : nullptr, /* trace */
463 : };
464 :
465 : static const js::ClassExtension sClassExtension = {
466 : nullptr, /* weakmapKeyDelegateOp */
467 : _objectMoved /* objectMovedOp */
468 : };
469 :
470 : static const DOMJSClass sClass = {
471 : { "Permissions",
472 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
473 : &sClassOps,
474 : JS_NULL_CLASS_SPEC,
475 : &sClassExtension,
476 : JS_NULL_OBJECT_OPS
477 : },
478 : { prototypes::id::Permissions, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
479 : IsBaseOf<nsISupports, mozilla::dom::Permissions >::value,
480 : sNativePropertyHooks,
481 : FindAssociatedGlobalForNative<mozilla::dom::Permissions>::Get,
482 : GetProtoObjectHandle,
483 : GetCCParticipant<mozilla::dom::Permissions>::Get()
484 : };
485 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
486 : "Must have the right minimal number of reserved slots.");
487 : static_assert(1 >= 1,
488 : "Must have enough reserved slots.");
489 :
490 : const JSClass*
491 0 : GetJSClass()
492 : {
493 0 : return sClass.ToJSClass();
494 : }
495 :
496 : bool
497 0 : Wrap(JSContext* aCx, mozilla::dom::Permissions* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
498 : {
499 : MOZ_ASSERT(static_cast<mozilla::dom::Permissions*>(aObject) ==
500 : reinterpret_cast<mozilla::dom::Permissions*>(aObject),
501 : "Multiple inheritance for mozilla::dom::Permissions is broken.");
502 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
503 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
504 0 : MOZ_ASSERT(!aCache->GetWrapper(),
505 : "You should probably not be using Wrap() directly; use "
506 : "GetOrCreateDOMReflector instead");
507 :
508 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
509 : "nsISupports must be on our primary inheritance chain");
510 :
511 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
512 0 : if (!global) {
513 0 : return false;
514 : }
515 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
516 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
517 :
518 : // That might have ended up wrapping us already, due to the wonders
519 : // of XBL. Check for that, and bail out as needed.
520 0 : aReflector.set(aCache->GetWrapper());
521 0 : if (aReflector) {
522 : #ifdef DEBUG
523 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
524 : #endif // DEBUG
525 0 : return true;
526 : }
527 :
528 0 : JSAutoCompartment ac(aCx, global);
529 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
530 0 : if (!canonicalProto) {
531 0 : return false;
532 : }
533 0 : JS::Rooted<JSObject*> proto(aCx);
534 0 : if (aGivenProto) {
535 0 : proto = aGivenProto;
536 : // Unfortunately, while aGivenProto was in the compartment of aCx
537 : // coming in, we changed compartments to that of "parent" so may need
538 : // to wrap the proto here.
539 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
540 0 : if (!JS_WrapObject(aCx, &proto)) {
541 0 : return false;
542 : }
543 : }
544 : } else {
545 0 : proto = canonicalProto;
546 : }
547 :
548 0 : BindingJSObjectCreator<mozilla::dom::Permissions> creator(aCx);
549 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
550 0 : if (!aReflector) {
551 0 : return false;
552 : }
553 :
554 0 : aCache->SetWrapper(aReflector);
555 0 : creator.InitializationSucceeded();
556 :
557 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
558 : aCache->GetWrapperPreserveColor() == aReflector);
559 : // If proto != canonicalProto, we have to preserve our wrapper;
560 : // otherwise we won't be able to properly recreate it later, since
561 : // we won't know what proto to use. Note that we don't check
562 : // aGivenProto here, since it's entirely possible (and even
563 : // somewhat common) to have a non-null aGivenProto which is the
564 : // same as canonicalProto.
565 0 : if (proto != canonicalProto) {
566 0 : PreserveWrapper(aObject);
567 : }
568 :
569 0 : return true;
570 : }
571 :
572 : const NativePropertyHooks sNativePropertyHooks[] = { {
573 : nullptr,
574 : nullptr,
575 : nullptr,
576 : { sNativeProperties.Upcast(), nullptr },
577 : prototypes::id::Permissions,
578 : constructors::id::Permissions,
579 : nullptr,
580 : &DefaultXrayExpandoObjectClass
581 : } };
582 :
583 : void
584 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
585 : {
586 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
587 0 : if (!parentProto) {
588 0 : return;
589 : }
590 :
591 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
592 0 : if (!constructorProto) {
593 0 : return;
594 : }
595 :
596 : static bool sIdsInited = false;
597 0 : if (!sIdsInited && NS_IsMainThread()) {
598 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
599 0 : return;
600 : }
601 0 : sIdsInited = true;
602 : }
603 :
604 : static bool sPrefCachesInited = false;
605 0 : if (!sPrefCachesInited && NS_IsMainThread()) {
606 0 : sPrefCachesInited = true;
607 0 : Preferences::AddBoolVarCache(&sMethods[1].disablers->enabled, "dom.permissions.revoke.enable");
608 : }
609 :
610 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::Permissions);
611 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::Permissions);
612 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
613 : &sPrototypeClass.mBase, protoCache,
614 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
615 : interfaceCache,
616 : sNativeProperties.Upcast(),
617 : nullptr,
618 : "Permissions", aDefineOnGlobal,
619 : nullptr,
620 0 : false);
621 : }
622 :
623 : JS::Handle<JSObject*>
624 0 : GetProtoObjectHandle(JSContext* aCx)
625 : {
626 : /* Get the interface prototype object for this class. This will create the
627 : object as needed. */
628 0 : bool aDefineOnGlobal = true;
629 :
630 : /* Make sure our global is sane. Hopefully we can remove this sometime */
631 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
632 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
633 0 : return nullptr;
634 : }
635 :
636 : /* Check to see whether the interface objects are already installed */
637 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
638 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::Permissions)) {
639 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
640 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
641 : }
642 :
643 : /*
644 : * The object might _still_ be null, but that's OK.
645 : *
646 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
647 : * traced by TraceProtoAndIfaceCache() and its contents are never
648 : * changed after they have been set.
649 : *
650 : * Calling address() avoids the read read barrier that does gray
651 : * unmarking, but it's not possible for the object to be gray here.
652 : */
653 :
654 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::Permissions);
655 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
656 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
657 : }
658 :
659 : JS::Handle<JSObject*>
660 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
661 : {
662 : /* Get the interface object for this class. This will create the object as
663 : needed. */
664 :
665 : /* Make sure our global is sane. Hopefully we can remove this sometime */
666 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
667 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
668 0 : return nullptr;
669 : }
670 :
671 : /* Check to see whether the interface objects are already installed */
672 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
673 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::Permissions)) {
674 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
675 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
676 : }
677 :
678 : /*
679 : * The object might _still_ be null, but that's OK.
680 : *
681 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
682 : * traced by TraceProtoAndIfaceCache() and its contents are never
683 : * changed after they have been set.
684 : *
685 : * Calling address() avoids the read read barrier that does gray
686 : * unmarking, but it's not possible for the object to be gray here.
687 : */
688 :
689 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::Permissions);
690 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
691 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
692 : }
693 :
694 : JSObject*
695 0 : GetConstructorObject(JSContext* aCx)
696 : {
697 0 : return GetConstructorObjectHandle(aCx);
698 : }
699 :
700 : } // namespace PermissionsBinding
701 :
702 :
703 :
704 : } // namespace dom
705 : } // namespace mozilla
|