Coverage Report

Created: 2018-09-25 14:53

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