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