Line data Source code
1 : /* THIS FILE IS AUTOGENERATED FROM PushSubscription.webidl BY Codegen.py - DO NOT EDIT */
2 :
3 : #include "AtomList.h"
4 : #include "PushSubscriptionBinding.h"
5 : #include "WrapperFactory.h"
6 : #include "jsapi.h"
7 : #include "jsfriendapi.h"
8 : #include "mozilla/OwningNonNull.h"
9 : #include "mozilla/UseCounter.h"
10 : #include "mozilla/dom/BindingUtils.h"
11 : #include "mozilla/dom/DOMJSClass.h"
12 : #include "mozilla/dom/NonRefcountedDOMObject.h"
13 : #include "mozilla/dom/Nullable.h"
14 : #include "mozilla/dom/Promise.h"
15 : #include "mozilla/dom/PushSubscription.h"
16 : #include "mozilla/dom/PushSubscriptionOptions.h"
17 : #include "mozilla/dom/ScriptSettings.h"
18 : #include "mozilla/dom/SimpleGlobalObject.h"
19 : #include "mozilla/dom/ToJSValue.h"
20 : #include "mozilla/dom/TypedArray.h"
21 : #include "mozilla/dom/UnionConversions.h"
22 : #include "mozilla/dom/XrayExpandoClass.h"
23 : #include "nsContentUtils.h"
24 :
25 : namespace mozilla {
26 : namespace dom {
27 :
28 : namespace PushEncryptionKeyNameValues {
29 : extern const EnumEntry strings[3] = {
30 : {"p256dh", 6},
31 : {"auth", 4},
32 : { nullptr, 0 }
33 : };
34 : } // namespace PushEncryptionKeyNameValues
35 :
36 : bool
37 0 : ToJSValue(JSContext* aCx, PushEncryptionKeyName aArgument, JS::MutableHandle<JS::Value> aValue)
38 : {
39 0 : MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(PushEncryptionKeyNameValues::strings));
40 : JSString* resultStr =
41 0 : JS_NewStringCopyN(aCx, PushEncryptionKeyNameValues::strings[uint32_t(aArgument)].value,
42 0 : PushEncryptionKeyNameValues::strings[uint32_t(aArgument)].length);
43 0 : if (!resultStr) {
44 0 : return false;
45 : }
46 0 : aValue.setString(resultStr);
47 0 : return true;
48 : }
49 :
50 :
51 :
52 0 : PushSubscriptionInit::PushSubscriptionInit()
53 : {
54 : // Safe to pass a null context if we pass a null value
55 0 : Init(nullptr, JS::NullHandleValue);
56 0 : }
57 :
58 :
59 : bool
60 0 : PushSubscriptionInit::InitIds(JSContext* cx, PushSubscriptionInitAtoms* atomsCache)
61 : {
62 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
63 :
64 : // Initialize these in reverse order so that any failure leaves the first one
65 : // uninitialized.
66 0 : if (!atomsCache->scope_id.init(cx, "scope") ||
67 0 : !atomsCache->p256dhKey_id.init(cx, "p256dhKey") ||
68 0 : !atomsCache->endpoint_id.init(cx, "endpoint") ||
69 0 : !atomsCache->authSecret_id.init(cx, "authSecret") ||
70 0 : !atomsCache->appServerKey_id.init(cx, "appServerKey")) {
71 0 : return false;
72 : }
73 0 : return true;
74 : }
75 :
76 : bool
77 0 : PushSubscriptionInit::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
78 : {
79 : // Passing a null JSContext is OK only if we're initing from null,
80 : // Since in that case we will not have to do any property gets
81 : // Also evaluate isNullOrUndefined in order to avoid false-positive
82 : // checkers by static analysis tools
83 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
84 0 : PushSubscriptionInitAtoms* atomsCache = nullptr;
85 0 : if (cx) {
86 0 : atomsCache = GetAtomCache<PushSubscriptionInitAtoms>(cx);
87 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
88 0 : return false;
89 : }
90 : }
91 :
92 0 : if (!IsConvertibleToDictionary(val)) {
93 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
94 : }
95 :
96 0 : bool isNull = val.isNullOrUndefined();
97 : // We only need these if !isNull, in which case we have |cx|.
98 0 : Maybe<JS::Rooted<JSObject *> > object;
99 0 : Maybe<JS::Rooted<JS::Value> > temp;
100 0 : if (!isNull) {
101 0 : MOZ_ASSERT(cx);
102 0 : object.emplace(cx, &val.toObject());
103 0 : temp.emplace(cx);
104 : }
105 0 : if (!isNull) {
106 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->appServerKey_id, temp.ptr())) {
107 0 : return false;
108 : }
109 : }
110 0 : if (!isNull && !temp->isUndefined()) {
111 0 : mAppServerKey.Construct();
112 0 : if (temp.ref().isNullOrUndefined()) {
113 0 : (mAppServerKey.Value()).SetNull();
114 : } else {
115 : {
116 0 : bool done = false, failed = false, tryNext;
117 0 : if (temp.ref().isObject()) {
118 0 : done = (failed = !(mAppServerKey.Value()).SetValue().TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
119 0 : (failed = !(mAppServerKey.Value()).SetValue().TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
120 :
121 : }
122 0 : if (failed) {
123 0 : return false;
124 : }
125 0 : if (!done) {
126 0 : ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'appServerKey' member of PushSubscriptionInit", "ArrayBufferView, ArrayBuffer");
127 0 : return false;
128 : }
129 : }
130 : }
131 0 : mIsAnyMemberPresent = true;
132 : }
133 :
134 0 : if (!isNull) {
135 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->authSecret_id, temp.ptr())) {
136 0 : return false;
137 : }
138 : }
139 0 : if (!isNull && !temp->isUndefined()) {
140 0 : mAuthSecret.Construct();
141 0 : if (temp.ref().isObject()) {
142 0 : if (!(mAuthSecret.Value()).SetValue().Init(&temp.ref().toObject())) {
143 0 : ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'authSecret' member of PushSubscriptionInit", "ArrayBufferOrNull");
144 0 : return false;
145 : }
146 0 : } else if (temp.ref().isNullOrUndefined()) {
147 0 : (mAuthSecret.Value()).SetNull();
148 : } else {
149 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'authSecret' member of PushSubscriptionInit");
150 0 : return false;
151 : }
152 0 : mIsAnyMemberPresent = true;
153 : }
154 :
155 0 : if (!isNull) {
156 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->endpoint_id, temp.ptr())) {
157 0 : return false;
158 : }
159 : }
160 0 : if (!isNull && !temp->isUndefined()) {
161 0 : if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mEndpoint)) {
162 0 : return false;
163 : }
164 0 : NormalizeUSVString(mEndpoint);
165 0 : mIsAnyMemberPresent = true;
166 0 : } else if (cx) {
167 : // Don't error out if we have no cx. In that
168 : // situation the caller is default-constructing us and we'll
169 : // just assume they know what they're doing.
170 0 : return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
171 0 : "'endpoint' member of PushSubscriptionInit");
172 : }
173 :
174 0 : if (!isNull) {
175 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->p256dhKey_id, temp.ptr())) {
176 0 : return false;
177 : }
178 : }
179 0 : if (!isNull && !temp->isUndefined()) {
180 0 : mP256dhKey.Construct();
181 0 : if (temp.ref().isObject()) {
182 0 : if (!(mP256dhKey.Value()).SetValue().Init(&temp.ref().toObject())) {
183 0 : ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "'p256dhKey' member of PushSubscriptionInit", "ArrayBufferOrNull");
184 0 : return false;
185 : }
186 0 : } else if (temp.ref().isNullOrUndefined()) {
187 0 : (mP256dhKey.Value()).SetNull();
188 : } else {
189 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'p256dhKey' member of PushSubscriptionInit");
190 0 : return false;
191 : }
192 0 : mIsAnyMemberPresent = true;
193 : }
194 :
195 0 : if (!isNull) {
196 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->scope_id, temp.ptr())) {
197 0 : return false;
198 : }
199 : }
200 0 : if (!isNull && !temp->isUndefined()) {
201 0 : if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mScope)) {
202 0 : return false;
203 : }
204 0 : NormalizeUSVString(mScope);
205 0 : mIsAnyMemberPresent = true;
206 0 : } else if (cx) {
207 : // Don't error out if we have no cx. In that
208 : // situation the caller is default-constructing us and we'll
209 : // just assume they know what they're doing.
210 0 : return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
211 0 : "'scope' member of PushSubscriptionInit");
212 : }
213 0 : return true;
214 : }
215 :
216 : bool
217 0 : PushSubscriptionInit::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
218 : {
219 0 : PushSubscriptionInitAtoms* atomsCache = GetAtomCache<PushSubscriptionInitAtoms>(cx);
220 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
221 0 : return false;
222 : }
223 :
224 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
225 0 : if (!obj) {
226 0 : return false;
227 : }
228 0 : rval.set(JS::ObjectValue(*obj));
229 :
230 0 : if (mAppServerKey.WasPassed()) {
231 : do {
232 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
233 0 : JS::Rooted<JS::Value> temp(cx);
234 0 : Nullable<OwningArrayBufferViewOrArrayBuffer > const & currentValue = mAppServerKey.InternalValue();
235 0 : if (currentValue.IsNull()) {
236 0 : temp.setNull();
237 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->appServerKey_id, temp, JSPROP_ENUMERATE)) {
238 0 : return false;
239 : }
240 0 : break;
241 : }
242 0 : if (!currentValue.Value().ToJSVal(cx, obj, &temp)) {
243 0 : return false;
244 : }
245 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->appServerKey_id, temp, JSPROP_ENUMERATE)) {
246 0 : return false;
247 : }
248 0 : break;
249 : } while(0);
250 : }
251 :
252 0 : if (mAuthSecret.WasPassed()) {
253 : do {
254 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
255 0 : JS::Rooted<JS::Value> temp(cx);
256 0 : Nullable<ArrayBuffer> const & currentValue = mAuthSecret.InternalValue();
257 0 : if (currentValue.IsNull()) {
258 0 : temp.setNull();
259 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->authSecret_id, temp, JSPROP_ENUMERATE)) {
260 0 : return false;
261 : }
262 0 : break;
263 : }
264 0 : temp.setObject(*currentValue.Value().Obj());
265 0 : if (!MaybeWrapNonDOMObjectValue(cx, &temp)) {
266 0 : return false;
267 : }
268 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->authSecret_id, temp, JSPROP_ENUMERATE)) {
269 0 : return false;
270 : }
271 0 : break;
272 : } while(0);
273 : }
274 :
275 : do {
276 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
277 0 : JS::Rooted<JS::Value> temp(cx);
278 0 : nsString const & currentValue = mEndpoint;
279 0 : if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
280 0 : return false;
281 : }
282 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->endpoint_id, temp, JSPROP_ENUMERATE)) {
283 0 : return false;
284 : }
285 0 : break;
286 : } while(0);
287 :
288 0 : if (mP256dhKey.WasPassed()) {
289 : do {
290 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
291 0 : JS::Rooted<JS::Value> temp(cx);
292 0 : Nullable<ArrayBuffer> const & currentValue = mP256dhKey.InternalValue();
293 0 : if (currentValue.IsNull()) {
294 0 : temp.setNull();
295 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->p256dhKey_id, temp, JSPROP_ENUMERATE)) {
296 0 : return false;
297 : }
298 0 : break;
299 : }
300 0 : temp.setObject(*currentValue.Value().Obj());
301 0 : if (!MaybeWrapNonDOMObjectValue(cx, &temp)) {
302 0 : return false;
303 : }
304 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->p256dhKey_id, temp, JSPROP_ENUMERATE)) {
305 0 : return false;
306 : }
307 0 : break;
308 : } while(0);
309 : }
310 :
311 : do {
312 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
313 0 : JS::Rooted<JS::Value> temp(cx);
314 0 : nsString const & currentValue = mScope;
315 0 : if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
316 0 : return false;
317 : }
318 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->scope_id, temp, JSPROP_ENUMERATE)) {
319 0 : return false;
320 : }
321 0 : break;
322 : } while(0);
323 :
324 0 : return true;
325 : }
326 :
327 : void
328 0 : PushSubscriptionInit::TraceDictionary(JSTracer* trc)
329 : {
330 0 : if (mAppServerKey.WasPassed()) {
331 0 : if (!mAppServerKey.Value().IsNull()) {
332 0 : mAppServerKey.Value().Value().TraceUnion(trc);
333 : }
334 : }
335 :
336 0 : if (mAuthSecret.WasPassed()) {
337 0 : if (!mAuthSecret.Value().IsNull()) {
338 0 : mAuthSecret.Value().Value().TraceSelf(trc);
339 : }
340 : }
341 :
342 0 : if (mP256dhKey.WasPassed()) {
343 0 : if (!mP256dhKey.Value().IsNull()) {
344 0 : mP256dhKey.Value().Value().TraceSelf(trc);
345 : }
346 : }
347 0 : }
348 :
349 : namespace binding_detail {
350 : } // namespace binding_detail
351 :
352 :
353 :
354 0 : PushSubscriptionKeys::PushSubscriptionKeys()
355 : {
356 : // Safe to pass a null context if we pass a null value
357 0 : Init(nullptr, JS::NullHandleValue);
358 0 : }
359 :
360 :
361 :
362 : bool
363 0 : PushSubscriptionKeys::InitIds(JSContext* cx, PushSubscriptionKeysAtoms* atomsCache)
364 : {
365 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
366 :
367 : // Initialize these in reverse order so that any failure leaves the first one
368 : // uninitialized.
369 0 : if (!atomsCache->p256dh_id.init(cx, "p256dh") ||
370 0 : !atomsCache->auth_id.init(cx, "auth")) {
371 0 : return false;
372 : }
373 0 : return true;
374 : }
375 :
376 : bool
377 0 : PushSubscriptionKeys::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
378 : {
379 : // Passing a null JSContext is OK only if we're initing from null,
380 : // Since in that case we will not have to do any property gets
381 : // Also evaluate isNullOrUndefined in order to avoid false-positive
382 : // checkers by static analysis tools
383 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
384 0 : PushSubscriptionKeysAtoms* atomsCache = nullptr;
385 0 : if (cx) {
386 0 : atomsCache = GetAtomCache<PushSubscriptionKeysAtoms>(cx);
387 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
388 0 : return false;
389 : }
390 : }
391 :
392 0 : if (!IsConvertibleToDictionary(val)) {
393 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
394 : }
395 :
396 0 : bool isNull = val.isNullOrUndefined();
397 : // We only need these if !isNull, in which case we have |cx|.
398 0 : Maybe<JS::Rooted<JSObject *> > object;
399 0 : Maybe<JS::Rooted<JS::Value> > temp;
400 0 : if (!isNull) {
401 0 : MOZ_ASSERT(cx);
402 0 : object.emplace(cx, &val.toObject());
403 0 : temp.emplace(cx);
404 : }
405 0 : if (!isNull) {
406 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->auth_id, temp.ptr())) {
407 0 : return false;
408 : }
409 : }
410 0 : if (!isNull && !temp->isUndefined()) {
411 0 : mAuth.Construct();
412 0 : if (!ConvertJSValueToByteString(cx, temp.ref(), false, (mAuth.Value()))) {
413 0 : return false;
414 : }
415 0 : mIsAnyMemberPresent = true;
416 : }
417 :
418 0 : if (!isNull) {
419 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->p256dh_id, temp.ptr())) {
420 0 : return false;
421 : }
422 : }
423 0 : if (!isNull && !temp->isUndefined()) {
424 0 : mP256dh.Construct();
425 0 : if (!ConvertJSValueToByteString(cx, temp.ref(), false, (mP256dh.Value()))) {
426 0 : return false;
427 : }
428 0 : mIsAnyMemberPresent = true;
429 : }
430 0 : return true;
431 : }
432 :
433 : bool
434 0 : PushSubscriptionKeys::Init(const nsAString& aJSON)
435 : {
436 0 : AutoJSAPI jsapi;
437 0 : JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
438 0 : if (!cleanGlobal) {
439 0 : return false;
440 : }
441 0 : if (!jsapi.Init(cleanGlobal)) {
442 0 : return false;
443 : }
444 0 : JSContext* cx = jsapi.cx();
445 0 : JS::Rooted<JS::Value> json(cx);
446 0 : bool ok = ParseJSON(cx, aJSON, &json);
447 0 : NS_ENSURE_TRUE(ok, false);
448 0 : return Init(cx, json);
449 : }
450 :
451 : bool
452 0 : PushSubscriptionKeys::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
453 : {
454 0 : PushSubscriptionKeysAtoms* atomsCache = GetAtomCache<PushSubscriptionKeysAtoms>(cx);
455 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
456 0 : return false;
457 : }
458 :
459 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
460 0 : if (!obj) {
461 0 : return false;
462 : }
463 0 : rval.set(JS::ObjectValue(*obj));
464 :
465 0 : if (mAuth.WasPassed()) {
466 : do {
467 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
468 0 : JS::Rooted<JS::Value> temp(cx);
469 0 : nsCString const & currentValue = mAuth.InternalValue();
470 0 : if (!NonVoidByteStringToJsval(cx, currentValue, &temp)) {
471 0 : return false;
472 : }
473 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->auth_id, temp, JSPROP_ENUMERATE)) {
474 0 : return false;
475 : }
476 0 : break;
477 : } while(0);
478 : }
479 :
480 0 : if (mP256dh.WasPassed()) {
481 : do {
482 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
483 0 : JS::Rooted<JS::Value> temp(cx);
484 0 : nsCString const & currentValue = mP256dh.InternalValue();
485 0 : if (!NonVoidByteStringToJsval(cx, currentValue, &temp)) {
486 0 : return false;
487 : }
488 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->p256dh_id, temp, JSPROP_ENUMERATE)) {
489 0 : return false;
490 : }
491 0 : break;
492 : } while(0);
493 : }
494 :
495 0 : return true;
496 : }
497 :
498 : bool
499 0 : PushSubscriptionKeys::ToJSON(nsAString& aJSON) const
500 : {
501 0 : AutoJSAPI jsapi;
502 0 : jsapi.Init();
503 0 : JSContext *cx = jsapi.cx();
504 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
505 : // because we'll only be creating objects, in ways that have no
506 : // side-effects, followed by a call to JS::ToJSONMaybeSafely,
507 : // which likewise guarantees no side-effects for the sorts of
508 : // things we will pass it.
509 0 : JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
510 0 : JS::Rooted<JS::Value> val(cx);
511 0 : if (!ToObjectInternal(cx, &val)) {
512 0 : return false;
513 : }
514 0 : JS::Rooted<JSObject*> obj(cx, &val.toObject());
515 0 : return StringifyToJSON(cx, obj, aJSON);
516 : }
517 :
518 : void
519 0 : PushSubscriptionKeys::TraceDictionary(JSTracer* trc)
520 : {
521 0 : }
522 :
523 : PushSubscriptionKeys&
524 0 : PushSubscriptionKeys::operator=(const PushSubscriptionKeys& aOther)
525 : {
526 0 : mAuth.Reset();
527 0 : if (aOther.mAuth.WasPassed()) {
528 0 : mAuth.Construct(aOther.mAuth.Value());
529 : }
530 0 : mP256dh.Reset();
531 0 : if (aOther.mP256dh.WasPassed()) {
532 0 : mP256dh.Construct(aOther.mP256dh.Value());
533 : }
534 0 : return *this;
535 : }
536 :
537 : namespace binding_detail {
538 : } // namespace binding_detail
539 :
540 :
541 :
542 0 : PushSubscriptionJSON::PushSubscriptionJSON()
543 0 : : mKeys(FastDictionaryInitializer())
544 : {
545 : // Safe to pass a null context if we pass a null value
546 0 : Init(nullptr, JS::NullHandleValue);
547 0 : }
548 :
549 :
550 :
551 : bool
552 0 : PushSubscriptionJSON::InitIds(JSContext* cx, PushSubscriptionJSONAtoms* atomsCache)
553 : {
554 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
555 :
556 : // Initialize these in reverse order so that any failure leaves the first one
557 : // uninitialized.
558 0 : if (!atomsCache->keys_id.init(cx, "keys") ||
559 0 : !atomsCache->endpoint_id.init(cx, "endpoint")) {
560 0 : return false;
561 : }
562 0 : return true;
563 : }
564 :
565 : bool
566 0 : PushSubscriptionJSON::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
567 : {
568 : // Passing a null JSContext is OK only if we're initing from null,
569 : // Since in that case we will not have to do any property gets
570 : // Also evaluate isNullOrUndefined in order to avoid false-positive
571 : // checkers by static analysis tools
572 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
573 0 : PushSubscriptionJSONAtoms* atomsCache = nullptr;
574 0 : if (cx) {
575 0 : atomsCache = GetAtomCache<PushSubscriptionJSONAtoms>(cx);
576 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
577 0 : return false;
578 : }
579 : }
580 :
581 0 : if (!IsConvertibleToDictionary(val)) {
582 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
583 : }
584 :
585 0 : bool isNull = val.isNullOrUndefined();
586 : // We only need these if !isNull, in which case we have |cx|.
587 0 : Maybe<JS::Rooted<JSObject *> > object;
588 0 : Maybe<JS::Rooted<JS::Value> > temp;
589 0 : if (!isNull) {
590 0 : MOZ_ASSERT(cx);
591 0 : object.emplace(cx, &val.toObject());
592 0 : temp.emplace(cx);
593 : }
594 0 : if (!isNull) {
595 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->endpoint_id, temp.ptr())) {
596 0 : return false;
597 : }
598 : }
599 0 : if (!isNull && !temp->isUndefined()) {
600 0 : mEndpoint.Construct();
601 0 : if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mEndpoint.Value()))) {
602 0 : return false;
603 : }
604 0 : NormalizeUSVString((mEndpoint.Value()));
605 0 : mIsAnyMemberPresent = true;
606 : }
607 :
608 0 : if (!isNull) {
609 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->keys_id, temp.ptr())) {
610 0 : return false;
611 : }
612 : }
613 0 : if (!mKeys.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue, "'keys' member of PushSubscriptionJSON", passedToJSImpl)) {
614 0 : return false;
615 : }
616 0 : mIsAnyMemberPresent = true;
617 0 : return true;
618 : }
619 :
620 : bool
621 0 : PushSubscriptionJSON::Init(const nsAString& aJSON)
622 : {
623 0 : AutoJSAPI jsapi;
624 0 : JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
625 0 : if (!cleanGlobal) {
626 0 : return false;
627 : }
628 0 : if (!jsapi.Init(cleanGlobal)) {
629 0 : return false;
630 : }
631 0 : JSContext* cx = jsapi.cx();
632 0 : JS::Rooted<JS::Value> json(cx);
633 0 : bool ok = ParseJSON(cx, aJSON, &json);
634 0 : NS_ENSURE_TRUE(ok, false);
635 0 : return Init(cx, json);
636 : }
637 :
638 : bool
639 0 : PushSubscriptionJSON::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
640 : {
641 0 : PushSubscriptionJSONAtoms* atomsCache = GetAtomCache<PushSubscriptionJSONAtoms>(cx);
642 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
643 0 : return false;
644 : }
645 :
646 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
647 0 : if (!obj) {
648 0 : return false;
649 : }
650 0 : rval.set(JS::ObjectValue(*obj));
651 :
652 0 : if (mEndpoint.WasPassed()) {
653 : do {
654 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
655 0 : JS::Rooted<JS::Value> temp(cx);
656 0 : nsString const & currentValue = mEndpoint.InternalValue();
657 0 : if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
658 0 : return false;
659 : }
660 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->endpoint_id, temp, JSPROP_ENUMERATE)) {
661 0 : return false;
662 : }
663 0 : break;
664 : } while(0);
665 : }
666 :
667 : do {
668 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
669 0 : JS::Rooted<JS::Value> temp(cx);
670 0 : PushSubscriptionKeys const & currentValue = mKeys;
671 0 : if (!currentValue.ToObjectInternal(cx, &temp)) {
672 0 : return false;
673 : }
674 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->keys_id, temp, JSPROP_ENUMERATE)) {
675 0 : return false;
676 : }
677 0 : break;
678 : } while(0);
679 :
680 0 : return true;
681 : }
682 :
683 : bool
684 0 : PushSubscriptionJSON::ToJSON(nsAString& aJSON) const
685 : {
686 0 : AutoJSAPI jsapi;
687 0 : jsapi.Init();
688 0 : JSContext *cx = jsapi.cx();
689 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
690 : // because we'll only be creating objects, in ways that have no
691 : // side-effects, followed by a call to JS::ToJSONMaybeSafely,
692 : // which likewise guarantees no side-effects for the sorts of
693 : // things we will pass it.
694 0 : JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
695 0 : JS::Rooted<JS::Value> val(cx);
696 0 : if (!ToObjectInternal(cx, &val)) {
697 0 : return false;
698 : }
699 0 : JS::Rooted<JSObject*> obj(cx, &val.toObject());
700 0 : return StringifyToJSON(cx, obj, aJSON);
701 : }
702 :
703 : void
704 0 : PushSubscriptionJSON::TraceDictionary(JSTracer* trc)
705 : {
706 0 : }
707 :
708 : PushSubscriptionJSON&
709 0 : PushSubscriptionJSON::operator=(const PushSubscriptionJSON& aOther)
710 : {
711 0 : mEndpoint.Reset();
712 0 : if (aOther.mEndpoint.WasPassed()) {
713 0 : mEndpoint.Construct(aOther.mEndpoint.Value());
714 : }
715 0 : mKeys = aOther.mKeys;
716 0 : return *this;
717 : }
718 :
719 : namespace binding_detail {
720 : } // namespace binding_detail
721 :
722 :
723 : namespace PushSubscriptionBinding {
724 :
725 : static bool
726 0 : get_endpoint(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushSubscription* self, JSJitGetterCallArgs args)
727 : {
728 0 : DOMString result;
729 0 : self->GetEndpoint(result);
730 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
731 0 : if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
732 0 : return false;
733 : }
734 0 : return true;
735 : }
736 :
737 : static const JSJitInfo endpoint_getterinfo = {
738 : { (JSJitGetterOp)get_endpoint },
739 : { prototypes::id::PushSubscription },
740 : { PrototypeTraits<prototypes::id::PushSubscription>::Depth },
741 : JSJitInfo::Getter,
742 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
743 : JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */
744 : false, /* isInfallible. False in setters. */
745 : false, /* isMovable. Not relevant for setters. */
746 : false, /* isEliminatable. Not relevant for setters. */
747 : false, /* isAlwaysInSlot. Only relevant for getters. */
748 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
749 : false, /* isTypedMethod. Only relevant for methods. */
750 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
751 : };
752 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
753 : static_assert(0 < 1, "There is no slot for us");
754 :
755 : static bool
756 0 : get_options(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushSubscription* self, JSJitGetterCallArgs args)
757 : {
758 0 : auto result(StrongOrRawPtr<mozilla::dom::PushSubscriptionOptions>(self->Options()));
759 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
760 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
761 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
762 0 : return false;
763 : }
764 0 : return true;
765 : }
766 :
767 : static const JSJitInfo options_getterinfo = {
768 : { (JSJitGetterOp)get_options },
769 : { prototypes::id::PushSubscription },
770 : { PrototypeTraits<prototypes::id::PushSubscription>::Depth },
771 : JSJitInfo::Getter,
772 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
773 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
774 : false, /* isInfallible. False in setters. */
775 : false, /* isMovable. Not relevant for setters. */
776 : false, /* isEliminatable. Not relevant for setters. */
777 : false, /* isAlwaysInSlot. Only relevant for getters. */
778 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
779 : false, /* isTypedMethod. Only relevant for methods. */
780 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
781 : };
782 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
783 : static_assert(0 < 1, "There is no slot for us");
784 :
785 : static bool
786 0 : getKey(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushSubscription* self, const JSJitMethodCallArgs& args)
787 : {
788 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
789 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "PushSubscription.getKey");
790 : }
791 : PushEncryptionKeyName arg0;
792 : {
793 : int index;
794 0 : if (!FindEnumStringIndex<true>(cx, args[0], PushEncryptionKeyNameValues::strings, "PushEncryptionKeyName", "Argument 1 of PushSubscription.getKey", &index)) {
795 0 : return false;
796 : }
797 0 : MOZ_ASSERT(index >= 0);
798 0 : arg0 = static_cast<PushEncryptionKeyName>(index);
799 : }
800 0 : binding_detail::FastErrorResult rv;
801 0 : JS::Rooted<JSObject*> result(cx);
802 0 : self->GetKey(cx, arg0, &result, rv);
803 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
804 0 : return false;
805 : }
806 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
807 0 : if (result) {
808 0 : JS::ExposeObjectToActiveJS(result);
809 : }
810 0 : args.rval().setObjectOrNull(result);
811 0 : if (!MaybeWrapNonDOMObjectOrNullValue(cx, args.rval())) {
812 0 : return false;
813 : }
814 0 : return true;
815 : }
816 :
817 : static const JSJitInfo getKey_methodinfo = {
818 : { (JSJitGetterOp)getKey },
819 : { prototypes::id::PushSubscription },
820 : { PrototypeTraits<prototypes::id::PushSubscription>::Depth },
821 : JSJitInfo::Method,
822 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
823 : JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */
824 : false, /* isInfallible. False in setters. */
825 : false, /* isMovable. Not relevant for setters. */
826 : false, /* isEliminatable. Not relevant for setters. */
827 : false, /* isAlwaysInSlot. Only relevant for getters. */
828 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
829 : false, /* isTypedMethod. Only relevant for methods. */
830 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
831 : };
832 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
833 : static_assert(0 < 1, "There is no slot for us");
834 :
835 : static bool
836 0 : unsubscribe(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushSubscription* self, const JSJitMethodCallArgs& args)
837 : {
838 0 : binding_detail::FastErrorResult rv;
839 0 : auto result(StrongOrRawPtr<Promise>(self->Unsubscribe(rv)));
840 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
841 0 : return false;
842 : }
843 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
844 0 : SetDocumentAndPageUseCounter(cx, obj, eUseCounter_PushSubscription_unsubscribe);
845 0 : if (!ToJSValue(cx, result, args.rval())) {
846 0 : return false;
847 : }
848 0 : return true;
849 : }
850 :
851 : static bool
852 0 : unsubscribe_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushSubscription* self, const JSJitMethodCallArgs& args)
853 : {
854 : // Make sure to save the callee before someone maybe messes
855 : // with rval().
856 0 : JS::Rooted<JSObject*> callee(cx, &args.callee());
857 0 : bool ok = unsubscribe(cx, obj, self, args);
858 0 : if (ok) {
859 0 : return true;
860 : }
861 0 : return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
862 0 : args.rval());
863 : }
864 :
865 : static const JSJitInfo unsubscribe_methodinfo = {
866 : { (JSJitGetterOp)unsubscribe_promiseWrapper },
867 : { prototypes::id::PushSubscription },
868 : { PrototypeTraits<prototypes::id::PushSubscription>::Depth },
869 : JSJitInfo::Method,
870 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
871 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
872 : false, /* isInfallible. False in setters. */
873 : false, /* isMovable. Not relevant for setters. */
874 : false, /* isEliminatable. Not relevant for setters. */
875 : false, /* isAlwaysInSlot. Only relevant for getters. */
876 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
877 : false, /* isTypedMethod. Only relevant for methods. */
878 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
879 : };
880 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
881 : static_assert(0 < 1, "There is no slot for us");
882 :
883 : static bool
884 0 : toJSON(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushSubscription* self, const JSJitMethodCallArgs& args)
885 : {
886 0 : binding_detail::FastErrorResult rv;
887 0 : PushSubscriptionJSON result;
888 0 : self->ToJSON(result, rv);
889 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
890 0 : return false;
891 : }
892 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
893 0 : if (!result.ToObjectInternal(cx, args.rval())) {
894 0 : return false;
895 : }
896 0 : return true;
897 : }
898 :
899 : static const JSJitInfo toJSON_methodinfo = {
900 : { (JSJitGetterOp)toJSON },
901 : { prototypes::id::PushSubscription },
902 : { PrototypeTraits<prototypes::id::PushSubscription>::Depth },
903 : JSJitInfo::Method,
904 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
905 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
906 : false, /* isInfallible. False in setters. */
907 : false, /* isMovable. Not relevant for setters. */
908 : false, /* isEliminatable. Not relevant for setters. */
909 : false, /* isAlwaysInSlot. Only relevant for getters. */
910 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
911 : false, /* isTypedMethod. Only relevant for methods. */
912 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
913 : };
914 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
915 : static_assert(0 < 1, "There is no slot for us");
916 :
917 : static bool
918 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
919 : {
920 0 : mozilla::dom::PushSubscription* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushSubscription>(obj);
921 : // We don't want to preserve if we don't have a wrapper, and we
922 : // obviously can't preserve if we're not initialized.
923 0 : if (self && self->GetWrapperPreserveColor()) {
924 0 : PreserveWrapper(self);
925 : }
926 0 : return true;
927 : }
928 :
929 : static void
930 0 : _finalize(js::FreeOp* fop, JSObject* obj)
931 : {
932 0 : mozilla::dom::PushSubscription* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushSubscription>(obj);
933 0 : if (self) {
934 0 : ClearWrapper(self, self, obj);
935 0 : AddForDeferredFinalization<mozilla::dom::PushSubscription>(self);
936 : }
937 0 : }
938 :
939 : static void
940 0 : _objectMoved(JSObject* obj, const JSObject* old)
941 : {
942 0 : mozilla::dom::PushSubscription* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushSubscription>(obj);
943 0 : if (self) {
944 0 : UpdateWrapper(self, self, obj, old);
945 : }
946 0 : }
947 :
948 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
949 : #if defined(__clang__)
950 : #pragma clang diagnostic push
951 : #pragma clang diagnostic ignored "-Wmissing-braces"
952 : #endif
953 : static const JSFunctionSpec sMethods_specs[] = {
954 : JS_FNSPEC("getKey", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&getKey_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
955 : JS_FNSPEC("unsubscribe", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&unsubscribe_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
956 : JS_FNSPEC("toJSON", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&toJSON_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
957 : JS_FS_END
958 : };
959 : #if defined(__clang__)
960 : #pragma clang diagnostic pop
961 : #endif
962 :
963 :
964 : // Can't be const because the pref-enabled boolean needs to be writable
965 : static Prefable<const JSFunctionSpec> sMethods[] = {
966 : { nullptr, &sMethods_specs[0] },
967 : { nullptr, nullptr }
968 : };
969 :
970 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
971 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
972 : static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
973 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
974 :
975 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
976 : #if defined(__clang__)
977 : #pragma clang diagnostic push
978 : #pragma clang diagnostic ignored "-Wmissing-braces"
979 : #endif
980 : static const JSPropertySpec sAttributes_specs[] = {
981 : { "endpoint", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &endpoint_getterinfo, nullptr, nullptr },
982 : { "options", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &options_getterinfo, nullptr, nullptr },
983 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
984 : };
985 : #if defined(__clang__)
986 : #pragma clang diagnostic pop
987 : #endif
988 :
989 :
990 : // Can't be const because the pref-enabled boolean needs to be writable
991 : static Prefable<const JSPropertySpec> sAttributes[] = {
992 : { nullptr, &sAttributes_specs[0] },
993 : { nullptr, nullptr }
994 : };
995 :
996 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
997 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
998 : static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
999 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1000 :
1001 :
1002 : static uint16_t sNativeProperties_sortedPropertyIndices[5];
1003 : static PropertyInfo sNativeProperties_propertyInfos[5];
1004 :
1005 : static const NativePropertiesN<2> sNativeProperties = {
1006 : false, 0,
1007 : false, 0,
1008 : true, 0 /* sMethods */,
1009 : true, 1 /* sAttributes */,
1010 : false, 0,
1011 : false, 0,
1012 : false, 0,
1013 : -1,
1014 : 5,
1015 : sNativeProperties_sortedPropertyIndices,
1016 : {
1017 : { sMethods, &sNativeProperties_propertyInfos[0] },
1018 : { sAttributes, &sNativeProperties_propertyInfos[3] }
1019 : }
1020 : };
1021 : static_assert(5 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
1022 : "We have a property info count that is oversized");
1023 :
1024 : static bool
1025 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
1026 : {
1027 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
1028 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
1029 0 : if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
1030 0 : return ThrowingConstructor(cx, argc, vp);
1031 : }
1032 :
1033 0 : if (!args.isConstructing()) {
1034 : // XXXbz wish I could get the name from the callee instead of
1035 : // Adding more relocations
1036 0 : return ThrowConstructorWithoutNew(cx, "PushSubscription");
1037 : }
1038 :
1039 0 : GlobalObject global(cx, obj);
1040 0 : if (global.Failed()) {
1041 0 : return false;
1042 : }
1043 :
1044 0 : JS::Rooted<JSObject*> desiredProto(cx);
1045 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
1046 0 : return false;
1047 : }
1048 :
1049 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
1050 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "PushSubscription");
1051 : }
1052 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
1053 0 : RootedDictionary<binding_detail::FastPushSubscriptionInit> arg0(cx);
1054 0 : if (!arg0.Init(cx, args[0], "Argument 1 of PushSubscription.constructor", false)) {
1055 0 : return false;
1056 : }
1057 0 : Maybe<JSAutoCompartment> ac;
1058 0 : if (objIsXray) {
1059 0 : obj = js::CheckedUnwrap(obj);
1060 0 : if (!obj) {
1061 0 : return false;
1062 : }
1063 0 : ac.emplace(cx, obj);
1064 0 : if (!JS_WrapObject(cx, &desiredProto)) {
1065 0 : return false;
1066 : }
1067 0 : if (arg0.mAppServerKey.WasPassed()) {
1068 0 : if (arg0.mAppServerKey.Value().Value().IsArrayBufferView()) {
1069 0 : if (!arg0.mAppServerKey.Value().Value().GetAsArrayBufferView().WrapIntoNewCompartment(cx)) {
1070 0 : return false;
1071 : }
1072 : }
1073 0 : else if (arg0.mAppServerKey.Value().Value().IsArrayBuffer()) {
1074 0 : if (!arg0.mAppServerKey.Value().Value().GetAsArrayBuffer().WrapIntoNewCompartment(cx)) {
1075 0 : return false;
1076 : }
1077 : }
1078 : }
1079 0 : if (arg0.mAuthSecret.WasPassed()) {
1080 0 : if (!arg0.mAuthSecret.Value().IsNull()) {
1081 0 : if (!arg0.mAuthSecret.Value().Value().WrapIntoNewCompartment(cx)) {
1082 0 : return false;
1083 : }
1084 : }
1085 : }
1086 0 : if (arg0.mP256dhKey.WasPassed()) {
1087 0 : if (!arg0.mP256dhKey.Value().IsNull()) {
1088 0 : if (!arg0.mP256dhKey.Value().Value().WrapIntoNewCompartment(cx)) {
1089 0 : return false;
1090 : }
1091 : }
1092 : }
1093 : }
1094 0 : binding_detail::FastErrorResult rv;
1095 0 : auto result(StrongOrRawPtr<mozilla::dom::PushSubscription>(mozilla::dom::PushSubscription::Constructor(global, Constify(arg0), rv)));
1096 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
1097 0 : return false;
1098 : }
1099 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
1100 : static_assert(!IsPointer<decltype(result)>::value,
1101 : "NewObject implies that we need to keep the object alive with a strong reference.");
1102 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
1103 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
1104 0 : return false;
1105 : }
1106 0 : return true;
1107 : }
1108 :
1109 : static const js::ClassOps sInterfaceObjectClassOps = {
1110 : nullptr, /* addProperty */
1111 : nullptr, /* delProperty */
1112 : nullptr, /* getProperty */
1113 : nullptr, /* setProperty */
1114 : nullptr, /* enumerate */
1115 : nullptr, /* newEnumerate */
1116 : nullptr, /* resolve */
1117 : nullptr, /* mayResolve */
1118 : nullptr, /* finalize */
1119 : _constructor, /* call */
1120 : nullptr, /* hasInstance */
1121 : _constructor, /* construct */
1122 : nullptr, /* trace */
1123 : };
1124 :
1125 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
1126 : {
1127 : "Function",
1128 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
1129 : &sInterfaceObjectClassOps,
1130 : JS_NULL_CLASS_SPEC,
1131 : JS_NULL_CLASS_EXT,
1132 : &sInterfaceObjectClassObjectOps
1133 : },
1134 : eInterface,
1135 : true,
1136 : prototypes::id::PushSubscription,
1137 : PrototypeTraits<prototypes::id::PushSubscription>::Depth,
1138 : sNativePropertyHooks,
1139 : "function PushSubscription() {\n [native code]\n}",
1140 : JS::GetRealmFunctionPrototype
1141 : };
1142 :
1143 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
1144 : {
1145 : "PushSubscriptionPrototype",
1146 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
1147 : JS_NULL_CLASS_OPS,
1148 : JS_NULL_CLASS_SPEC,
1149 : JS_NULL_CLASS_EXT,
1150 : JS_NULL_OBJECT_OPS
1151 : },
1152 : eInterfacePrototype,
1153 : false,
1154 : prototypes::id::PushSubscription,
1155 : PrototypeTraits<prototypes::id::PushSubscription>::Depth,
1156 : sNativePropertyHooks,
1157 : "[object PushSubscriptionPrototype]",
1158 : JS::GetRealmObjectPrototype
1159 : };
1160 :
1161 : bool
1162 1 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
1163 : {
1164 1 : return nsContentUtils::PushEnabled(aCx, aObj);
1165 : }
1166 :
1167 : JSObject*
1168 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
1169 : {
1170 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
1171 : }
1172 :
1173 : static const js::ClassOps sClassOps = {
1174 : _addProperty, /* addProperty */
1175 : nullptr, /* delProperty */
1176 : nullptr, /* getProperty */
1177 : nullptr, /* setProperty */
1178 : nullptr, /* enumerate */
1179 : nullptr, /* newEnumerate */
1180 : nullptr, /* resolve */
1181 : nullptr, /* mayResolve */
1182 : _finalize, /* finalize */
1183 : nullptr, /* call */
1184 : nullptr, /* hasInstance */
1185 : nullptr, /* construct */
1186 : nullptr, /* trace */
1187 : };
1188 :
1189 : static const js::ClassExtension sClassExtension = {
1190 : nullptr, /* weakmapKeyDelegateOp */
1191 : _objectMoved /* objectMovedOp */
1192 : };
1193 :
1194 : static const DOMJSClass sClass = {
1195 : { "PushSubscription",
1196 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1197 : &sClassOps,
1198 : JS_NULL_CLASS_SPEC,
1199 : &sClassExtension,
1200 : JS_NULL_OBJECT_OPS
1201 : },
1202 : { prototypes::id::PushSubscription, 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 },
1203 : IsBaseOf<nsISupports, mozilla::dom::PushSubscription >::value,
1204 : sNativePropertyHooks,
1205 : FindAssociatedGlobalForNative<mozilla::dom::PushSubscription>::Get,
1206 : GetProtoObjectHandle,
1207 : GetCCParticipant<mozilla::dom::PushSubscription>::Get()
1208 : };
1209 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1210 : "Must have the right minimal number of reserved slots.");
1211 : static_assert(1 >= 1,
1212 : "Must have enough reserved slots.");
1213 :
1214 : const JSClass*
1215 0 : GetJSClass()
1216 : {
1217 0 : return sClass.ToJSClass();
1218 : }
1219 :
1220 : bool
1221 0 : Wrap(JSContext* aCx, mozilla::dom::PushSubscription* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1222 : {
1223 : MOZ_ASSERT(static_cast<mozilla::dom::PushSubscription*>(aObject) ==
1224 : reinterpret_cast<mozilla::dom::PushSubscription*>(aObject),
1225 : "Multiple inheritance for mozilla::dom::PushSubscription is broken.");
1226 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1227 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1228 0 : MOZ_ASSERT(!aCache->GetWrapper(),
1229 : "You should probably not be using Wrap() directly; use "
1230 : "GetOrCreateDOMReflector instead");
1231 :
1232 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1233 : "nsISupports must be on our primary inheritance chain");
1234 :
1235 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1236 0 : if (!global) {
1237 0 : return false;
1238 : }
1239 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
1240 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
1241 :
1242 : // That might have ended up wrapping us already, due to the wonders
1243 : // of XBL. Check for that, and bail out as needed.
1244 0 : aReflector.set(aCache->GetWrapper());
1245 0 : if (aReflector) {
1246 : #ifdef DEBUG
1247 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1248 : #endif // DEBUG
1249 0 : return true;
1250 : }
1251 :
1252 0 : JSAutoCompartment ac(aCx, global);
1253 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1254 0 : if (!canonicalProto) {
1255 0 : return false;
1256 : }
1257 0 : JS::Rooted<JSObject*> proto(aCx);
1258 0 : if (aGivenProto) {
1259 0 : proto = aGivenProto;
1260 : // Unfortunately, while aGivenProto was in the compartment of aCx
1261 : // coming in, we changed compartments to that of "parent" so may need
1262 : // to wrap the proto here.
1263 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1264 0 : if (!JS_WrapObject(aCx, &proto)) {
1265 0 : return false;
1266 : }
1267 : }
1268 : } else {
1269 0 : proto = canonicalProto;
1270 : }
1271 :
1272 0 : BindingJSObjectCreator<mozilla::dom::PushSubscription> creator(aCx);
1273 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1274 0 : if (!aReflector) {
1275 0 : return false;
1276 : }
1277 :
1278 0 : aCache->SetWrapper(aReflector);
1279 0 : creator.InitializationSucceeded();
1280 :
1281 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1282 : aCache->GetWrapperPreserveColor() == aReflector);
1283 : // If proto != canonicalProto, we have to preserve our wrapper;
1284 : // otherwise we won't be able to properly recreate it later, since
1285 : // we won't know what proto to use. Note that we don't check
1286 : // aGivenProto here, since it's entirely possible (and even
1287 : // somewhat common) to have a non-null aGivenProto which is the
1288 : // same as canonicalProto.
1289 0 : if (proto != canonicalProto) {
1290 0 : PreserveWrapper(aObject);
1291 : }
1292 :
1293 0 : return true;
1294 : }
1295 :
1296 : const NativePropertyHooks sNativePropertyHooks[] = { {
1297 : nullptr,
1298 : nullptr,
1299 : nullptr,
1300 : { sNativeProperties.Upcast(), nullptr },
1301 : prototypes::id::PushSubscription,
1302 : constructors::id::PushSubscription,
1303 : nullptr,
1304 : &DefaultXrayExpandoObjectClass
1305 : } };
1306 :
1307 : void
1308 1 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1309 : {
1310 2 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
1311 1 : if (!parentProto) {
1312 0 : return;
1313 : }
1314 :
1315 2 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
1316 1 : if (!constructorProto) {
1317 0 : return;
1318 : }
1319 :
1320 : static bool sIdsInited = false;
1321 1 : if (!sIdsInited && NS_IsMainThread()) {
1322 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
1323 0 : return;
1324 : }
1325 0 : sIdsInited = true;
1326 : }
1327 :
1328 1 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::PushSubscription);
1329 1 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::PushSubscription);
1330 2 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1331 : &sPrototypeClass.mBase, protoCache,
1332 : constructorProto, &sInterfaceObjectClass.mBase, 1, nullptr,
1333 : interfaceCache,
1334 : sNativeProperties.Upcast(),
1335 : nullptr,
1336 : "PushSubscription", aDefineOnGlobal,
1337 : nullptr,
1338 1 : false);
1339 : }
1340 :
1341 : JS::Handle<JSObject*>
1342 0 : GetProtoObjectHandle(JSContext* aCx)
1343 : {
1344 : /* Get the interface prototype object for this class. This will create the
1345 : object as needed. */
1346 0 : bool aDefineOnGlobal = true;
1347 :
1348 : /* Make sure our global is sane. Hopefully we can remove this sometime */
1349 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
1350 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
1351 0 : return nullptr;
1352 : }
1353 :
1354 : /* Check to see whether the interface objects are already installed */
1355 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
1356 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::PushSubscription)) {
1357 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
1358 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
1359 : }
1360 :
1361 : /*
1362 : * The object might _still_ be null, but that's OK.
1363 : *
1364 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1365 : * traced by TraceProtoAndIfaceCache() and its contents are never
1366 : * changed after they have been set.
1367 : *
1368 : * Calling address() avoids the read read barrier that does gray
1369 : * unmarking, but it's not possible for the object to be gray here.
1370 : */
1371 :
1372 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::PushSubscription);
1373 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1374 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1375 : }
1376 :
1377 : JS::Handle<JSObject*>
1378 1 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
1379 : {
1380 : /* Get the interface object for this class. This will create the object as
1381 : needed. */
1382 :
1383 : /* Make sure our global is sane. Hopefully we can remove this sometime */
1384 1 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
1385 1 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
1386 0 : return nullptr;
1387 : }
1388 :
1389 : /* Check to see whether the interface objects are already installed */
1390 1 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
1391 1 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::PushSubscription)) {
1392 2 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
1393 1 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
1394 : }
1395 :
1396 : /*
1397 : * The object might _still_ be null, but that's OK.
1398 : *
1399 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1400 : * traced by TraceProtoAndIfaceCache() and its contents are never
1401 : * changed after they have been set.
1402 : *
1403 : * Calling address() avoids the read read barrier that does gray
1404 : * unmarking, but it's not possible for the object to be gray here.
1405 : */
1406 :
1407 1 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::PushSubscription);
1408 1 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1409 1 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1410 : }
1411 :
1412 : JSObject*
1413 1 : GetConstructorObject(JSContext* aCx)
1414 : {
1415 1 : return GetConstructorObjectHandle(aCx);
1416 : }
1417 :
1418 : } // namespace PushSubscriptionBinding
1419 :
1420 :
1421 :
1422 : } // namespace dom
1423 : } // namespace mozilla
|