Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/WebAuthenticationBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM WebAuthentication.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "CredentialManagementBinding.h"
5
#include "WebAuthenticationBinding.h"
6
#include "WrapperFactory.h"
7
#include "jsapi.h"
8
#include "jsfriendapi.h"
9
#include "mozilla/OwningNonNull.h"
10
#include "mozilla/Preferences.h"
11
#include "mozilla/dom/AuthenticatorAssertionResponse.h"
12
#include "mozilla/dom/AuthenticatorAttestationResponse.h"
13
#include "mozilla/dom/AuthenticatorResponse.h"
14
#include "mozilla/dom/BindingUtils.h"
15
#include "mozilla/dom/DOMJSClass.h"
16
#include "mozilla/dom/NonRefcountedDOMObject.h"
17
#include "mozilla/dom/Nullable.h"
18
#include "mozilla/dom/PrimitiveConversions.h"
19
#include "mozilla/dom/Promise.h"
20
#include "mozilla/dom/PublicKeyCredential.h"
21
#include "mozilla/dom/ScriptSettings.h"
22
#include "mozilla/dom/SimpleGlobalObject.h"
23
#include "mozilla/dom/ToJSValue.h"
24
#include "mozilla/dom/TypedArray.h"
25
#include "mozilla/dom/UnionConversions.h"
26
#include "mozilla/dom/XrayExpandoClass.h"
27
28
namespace mozilla {
29
namespace dom {
30
31
namespace binding_detail {}; // Just to make sure it's known as a namespace
32
using namespace mozilla::dom::binding_detail;
33
34
35
namespace AuthenticatorAttachmentValues {
36
extern const EnumEntry strings[3] = {
37
  {"platform", 8},
38
  {"cross-platform", 14},
39
  { nullptr, 0 }
40
};
41
} // namespace AuthenticatorAttachmentValues
42
43
bool
44
ToJSValue(JSContext* aCx, AuthenticatorAttachment aArgument, JS::MutableHandle<JS::Value> aValue)
45
0
{
46
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(AuthenticatorAttachmentValues::strings));
47
0
  JSString* resultStr =
48
0
    JS_NewStringCopyN(aCx, AuthenticatorAttachmentValues::strings[uint32_t(aArgument)].value,
49
0
                      AuthenticatorAttachmentValues::strings[uint32_t(aArgument)].length);
50
0
  if (!resultStr) {
51
0
    return false;
52
0
  }
53
0
  aValue.setString(resultStr);
54
0
  return true;
55
0
}
56
57
58
namespace AttestationConveyancePreferenceValues {
59
extern const EnumEntry strings[4] = {
60
  {"none", 4},
61
  {"indirect", 8},
62
  {"direct", 6},
63
  { nullptr, 0 }
64
};
65
} // namespace AttestationConveyancePreferenceValues
66
67
bool
68
ToJSValue(JSContext* aCx, AttestationConveyancePreference aArgument, JS::MutableHandle<JS::Value> aValue)
69
0
{
70
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(AttestationConveyancePreferenceValues::strings));
71
0
  JSString* resultStr =
72
0
    JS_NewStringCopyN(aCx, AttestationConveyancePreferenceValues::strings[uint32_t(aArgument)].value,
73
0
                      AttestationConveyancePreferenceValues::strings[uint32_t(aArgument)].length);
74
0
  if (!resultStr) {
75
0
    return false;
76
0
  }
77
0
  aValue.setString(resultStr);
78
0
  return true;
79
0
}
80
81
82
namespace UserVerificationRequirementValues {
83
extern const EnumEntry strings[4] = {
84
  {"required", 8},
85
  {"preferred", 9},
86
  {"discouraged", 11},
87
  { nullptr, 0 }
88
};
89
} // namespace UserVerificationRequirementValues
90
91
bool
92
ToJSValue(JSContext* aCx, UserVerificationRequirement aArgument, JS::MutableHandle<JS::Value> aValue)
93
0
{
94
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(UserVerificationRequirementValues::strings));
95
0
  JSString* resultStr =
96
0
    JS_NewStringCopyN(aCx, UserVerificationRequirementValues::strings[uint32_t(aArgument)].value,
97
0
                      UserVerificationRequirementValues::strings[uint32_t(aArgument)].length);
98
0
  if (!resultStr) {
99
0
    return false;
100
0
  }
101
0
  aValue.setString(resultStr);
102
0
  return true;
103
0
}
104
105
106
namespace PublicKeyCredentialTypeValues {
107
extern const EnumEntry strings[2] = {
108
  {"public-key", 10},
109
  { nullptr, 0 }
110
};
111
} // namespace PublicKeyCredentialTypeValues
112
113
bool
114
ToJSValue(JSContext* aCx, PublicKeyCredentialType aArgument, JS::MutableHandle<JS::Value> aValue)
115
0
{
116
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(PublicKeyCredentialTypeValues::strings));
117
0
  JSString* resultStr =
118
0
    JS_NewStringCopyN(aCx, PublicKeyCredentialTypeValues::strings[uint32_t(aArgument)].value,
119
0
                      PublicKeyCredentialTypeValues::strings[uint32_t(aArgument)].length);
120
0
  if (!resultStr) {
121
0
    return false;
122
0
  }
123
0
  aValue.setString(resultStr);
124
0
  return true;
125
0
}
126
127
128
namespace AuthenticatorTransportValues {
129
extern const EnumEntry strings[4] = {
130
  {"usb", 3},
131
  {"nfc", 3},
132
  {"ble", 3},
133
  { nullptr, 0 }
134
};
135
} // namespace AuthenticatorTransportValues
136
137
bool
138
ToJSValue(JSContext* aCx, AuthenticatorTransport aArgument, JS::MutableHandle<JS::Value> aValue)
139
0
{
140
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(AuthenticatorTransportValues::strings));
141
0
  JSString* resultStr =
142
0
    JS_NewStringCopyN(aCx, AuthenticatorTransportValues::strings[uint32_t(aArgument)].value,
143
0
                      AuthenticatorTransportValues::strings[uint32_t(aArgument)].length);
144
0
  if (!resultStr) {
145
0
    return false;
146
0
  }
147
0
  aValue.setString(resultStr);
148
0
  return true;
149
0
}
150
151
152
153
AuthenticationExtensionsClientInputs::AuthenticationExtensionsClientInputs()
154
0
{
155
0
  // Safe to pass a null context if we pass a null value
156
0
  Init(nullptr, JS::NullHandleValue);
157
0
}
158
159
160
161
bool
162
AuthenticationExtensionsClientInputs::InitIds(JSContext* cx, AuthenticationExtensionsClientInputsAtoms* atomsCache)
163
0
{
164
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
165
0
166
0
  // Initialize these in reverse order so that any failure leaves the first one
167
0
  // uninitialized.
168
0
  if (!atomsCache->appid_id.init(cx, "appid")) {
169
0
    return false;
170
0
  }
171
0
  return true;
172
0
}
173
174
bool
175
AuthenticationExtensionsClientInputs::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
176
0
{
177
0
  // Passing a null JSContext is OK only if we're initing from null,
178
0
  // Since in that case we will not have to do any property gets
179
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
180
0
  // checkers by static analysis tools
181
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
182
0
  AuthenticationExtensionsClientInputsAtoms* atomsCache = nullptr;
183
0
  if (cx) {
184
0
    atomsCache = GetAtomCache<AuthenticationExtensionsClientInputsAtoms>(cx);
185
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
186
0
      return false;
187
0
    }
188
0
  }
189
0
190
0
  if (!IsConvertibleToDictionary(val)) {
191
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
192
0
  }
193
0
194
0
  bool isNull = val.isNullOrUndefined();
195
0
  // We only need these if !isNull, in which case we have |cx|.
196
0
  Maybe<JS::Rooted<JSObject *> > object;
197
0
  Maybe<JS::Rooted<JS::Value> > temp;
198
0
  if (!isNull) {
199
0
    MOZ_ASSERT(cx);
200
0
    object.emplace(cx, &val.toObject());
201
0
    temp.emplace(cx);
202
0
  }
203
0
  if (!isNull) {
204
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->appid_id, temp.ptr())) {
205
0
      return false;
206
0
    }
207
0
  }
208
0
  if (!isNull && !temp->isUndefined()) {
209
0
    mAppid.Construct();
210
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mAppid.Value()))) {
211
0
      return false;
212
0
    }
213
0
    NormalizeUSVString((mAppid.Value()));
214
0
    mIsAnyMemberPresent = true;
215
0
  }
216
0
  return true;
217
0
}
218
219
bool
220
AuthenticationExtensionsClientInputs::Init(const nsAString& aJSON)
221
0
{
222
0
  AutoJSAPI jsapi;
223
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
224
0
  if (!cleanGlobal) {
225
0
    return false;
226
0
  }
227
0
  if (!jsapi.Init(cleanGlobal)) {
228
0
    return false;
229
0
  }
230
0
  JSContext* cx = jsapi.cx();
231
0
  JS::Rooted<JS::Value> json(cx);
232
0
  bool ok = ParseJSON(cx, aJSON, &json);
233
0
  NS_ENSURE_TRUE(ok, false);
234
0
  return Init(cx, json);
235
0
}
236
237
bool
238
AuthenticationExtensionsClientInputs::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
239
0
{
240
0
  AuthenticationExtensionsClientInputsAtoms* atomsCache = GetAtomCache<AuthenticationExtensionsClientInputsAtoms>(cx);
241
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
242
0
    return false;
243
0
  }
244
0
245
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
246
0
  if (!obj) {
247
0
    return false;
248
0
  }
249
0
  rval.set(JS::ObjectValue(*obj));
250
0
251
0
  if (mAppid.WasPassed()) {
252
0
    do {
253
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
254
0
      JS::Rooted<JS::Value> temp(cx);
255
0
      nsString const & currentValue = mAppid.InternalValue();
256
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
257
0
        return false;
258
0
      }
259
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->appid_id, temp, JSPROP_ENUMERATE)) {
260
0
        return false;
261
0
      }
262
0
      break;
263
0
    } while(false);
264
0
  }
265
0
266
0
  return true;
267
0
}
268
269
bool
270
AuthenticationExtensionsClientInputs::ToJSON(nsAString& aJSON) const
271
0
{
272
0
  AutoJSAPI jsapi;
273
0
  jsapi.Init();
274
0
  JSContext *cx = jsapi.cx();
275
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
276
0
  // because we'll only be creating objects, in ways that have no
277
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
278
0
  // which likewise guarantees no side-effects for the sorts of
279
0
  // things we will pass it.
280
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
281
0
  JS::Rooted<JS::Value> val(cx);
282
0
  if (!ToObjectInternal(cx, &val)) {
283
0
    return false;
284
0
  }
285
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
286
0
  return StringifyToJSON(cx, obj, aJSON);
287
0
}
288
289
void
290
AuthenticationExtensionsClientInputs::TraceDictionary(JSTracer* trc)
291
0
{
292
0
}
293
294
AuthenticationExtensionsClientInputs&
295
AuthenticationExtensionsClientInputs::operator=(const AuthenticationExtensionsClientInputs& aOther)
296
0
{
297
0
  DictionaryBase::operator=(aOther);
298
0
  mAppid.Reset();
299
0
  if (aOther.mAppid.WasPassed()) {
300
0
    mAppid.Construct(aOther.mAppid.Value());
301
0
  }
302
0
  return *this;
303
0
}
304
305
namespace binding_detail {
306
} // namespace binding_detail
307
308
309
310
AuthenticationExtensionsClientOutputs::AuthenticationExtensionsClientOutputs()
311
0
{
312
0
  // Safe to pass a null context if we pass a null value
313
0
  Init(nullptr, JS::NullHandleValue);
314
0
}
315
316
317
318
bool
319
AuthenticationExtensionsClientOutputs::InitIds(JSContext* cx, AuthenticationExtensionsClientOutputsAtoms* atomsCache)
320
0
{
321
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
322
0
323
0
  // Initialize these in reverse order so that any failure leaves the first one
324
0
  // uninitialized.
325
0
  if (!atomsCache->appid_id.init(cx, "appid")) {
326
0
    return false;
327
0
  }
328
0
  return true;
329
0
}
330
331
bool
332
AuthenticationExtensionsClientOutputs::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
333
0
{
334
0
  // Passing a null JSContext is OK only if we're initing from null,
335
0
  // Since in that case we will not have to do any property gets
336
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
337
0
  // checkers by static analysis tools
338
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
339
0
  AuthenticationExtensionsClientOutputsAtoms* atomsCache = nullptr;
340
0
  if (cx) {
341
0
    atomsCache = GetAtomCache<AuthenticationExtensionsClientOutputsAtoms>(cx);
342
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
343
0
      return false;
344
0
    }
345
0
  }
346
0
347
0
  if (!IsConvertibleToDictionary(val)) {
348
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
349
0
  }
350
0
351
0
  bool isNull = val.isNullOrUndefined();
352
0
  // We only need these if !isNull, in which case we have |cx|.
353
0
  Maybe<JS::Rooted<JSObject *> > object;
354
0
  Maybe<JS::Rooted<JS::Value> > temp;
355
0
  if (!isNull) {
356
0
    MOZ_ASSERT(cx);
357
0
    object.emplace(cx, &val.toObject());
358
0
    temp.emplace(cx);
359
0
  }
360
0
  if (!isNull) {
361
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->appid_id, temp.ptr())) {
362
0
      return false;
363
0
    }
364
0
  }
365
0
  if (!isNull && !temp->isUndefined()) {
366
0
    mAppid.Construct();
367
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mAppid.Value()))) {
368
0
      return false;
369
0
    }
370
0
    mIsAnyMemberPresent = true;
371
0
  }
372
0
  return true;
373
0
}
374
375
bool
376
AuthenticationExtensionsClientOutputs::Init(const nsAString& aJSON)
377
0
{
378
0
  AutoJSAPI jsapi;
379
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
380
0
  if (!cleanGlobal) {
381
0
    return false;
382
0
  }
383
0
  if (!jsapi.Init(cleanGlobal)) {
384
0
    return false;
385
0
  }
386
0
  JSContext* cx = jsapi.cx();
387
0
  JS::Rooted<JS::Value> json(cx);
388
0
  bool ok = ParseJSON(cx, aJSON, &json);
389
0
  NS_ENSURE_TRUE(ok, false);
390
0
  return Init(cx, json);
391
0
}
392
393
bool
394
AuthenticationExtensionsClientOutputs::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
395
0
{
396
0
  AuthenticationExtensionsClientOutputsAtoms* atomsCache = GetAtomCache<AuthenticationExtensionsClientOutputsAtoms>(cx);
397
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
398
0
    return false;
399
0
  }
400
0
401
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
402
0
  if (!obj) {
403
0
    return false;
404
0
  }
405
0
  rval.set(JS::ObjectValue(*obj));
406
0
407
0
  if (mAppid.WasPassed()) {
408
0
    do {
409
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
410
0
      JS::Rooted<JS::Value> temp(cx);
411
0
      bool const & currentValue = mAppid.InternalValue();
412
0
      temp.setBoolean(currentValue);
413
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->appid_id, temp, JSPROP_ENUMERATE)) {
414
0
        return false;
415
0
      }
416
0
      break;
417
0
    } while(false);
418
0
  }
419
0
420
0
  return true;
421
0
}
422
423
bool
424
AuthenticationExtensionsClientOutputs::ToJSON(nsAString& aJSON) const
425
0
{
426
0
  AutoJSAPI jsapi;
427
0
  jsapi.Init();
428
0
  JSContext *cx = jsapi.cx();
429
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
430
0
  // because we'll only be creating objects, in ways that have no
431
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
432
0
  // which likewise guarantees no side-effects for the sorts of
433
0
  // things we will pass it.
434
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
435
0
  JS::Rooted<JS::Value> val(cx);
436
0
  if (!ToObjectInternal(cx, &val)) {
437
0
    return false;
438
0
  }
439
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
440
0
  return StringifyToJSON(cx, obj, aJSON);
441
0
}
442
443
void
444
AuthenticationExtensionsClientOutputs::TraceDictionary(JSTracer* trc)
445
0
{
446
0
}
447
448
AuthenticationExtensionsClientOutputs&
449
AuthenticationExtensionsClientOutputs::operator=(const AuthenticationExtensionsClientOutputs& aOther)
450
0
{
451
0
  DictionaryBase::operator=(aOther);
452
0
  mAppid.Reset();
453
0
  if (aOther.mAppid.WasPassed()) {
454
0
    mAppid.Construct(aOther.mAppid.Value());
455
0
  }
456
0
  return *this;
457
0
}
458
459
namespace binding_detail {
460
} // namespace binding_detail
461
462
463
464
AuthenticatorSelectionCriteria::AuthenticatorSelectionCriteria()
465
0
{
466
0
  // Safe to pass a null context if we pass a null value
467
0
  Init(nullptr, JS::NullHandleValue);
468
0
}
469
470
471
472
bool
473
AuthenticatorSelectionCriteria::InitIds(JSContext* cx, AuthenticatorSelectionCriteriaAtoms* atomsCache)
474
0
{
475
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
476
0
477
0
  // Initialize these in reverse order so that any failure leaves the first one
478
0
  // uninitialized.
479
0
  if (!atomsCache->userVerification_id.init(cx, "userVerification") ||
480
0
      !atomsCache->requireResidentKey_id.init(cx, "requireResidentKey") ||
481
0
      !atomsCache->authenticatorAttachment_id.init(cx, "authenticatorAttachment")) {
482
0
    return false;
483
0
  }
484
0
  return true;
485
0
}
486
487
bool
488
AuthenticatorSelectionCriteria::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
489
0
{
490
0
  // Passing a null JSContext is OK only if we're initing from null,
491
0
  // Since in that case we will not have to do any property gets
492
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
493
0
  // checkers by static analysis tools
494
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
495
0
  AuthenticatorSelectionCriteriaAtoms* atomsCache = nullptr;
496
0
  if (cx) {
497
0
    atomsCache = GetAtomCache<AuthenticatorSelectionCriteriaAtoms>(cx);
498
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
499
0
      return false;
500
0
    }
501
0
  }
502
0
503
0
  if (!IsConvertibleToDictionary(val)) {
504
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
505
0
  }
506
0
507
0
  bool isNull = val.isNullOrUndefined();
508
0
  // We only need these if !isNull, in which case we have |cx|.
509
0
  Maybe<JS::Rooted<JSObject *> > object;
510
0
  Maybe<JS::Rooted<JS::Value> > temp;
511
0
  if (!isNull) {
512
0
    MOZ_ASSERT(cx);
513
0
    object.emplace(cx, &val.toObject());
514
0
    temp.emplace(cx);
515
0
  }
516
0
  if (!isNull) {
517
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->authenticatorAttachment_id, temp.ptr())) {
518
0
      return false;
519
0
    }
520
0
  }
521
0
  if (!isNull && !temp->isUndefined()) {
522
0
    mAuthenticatorAttachment.Construct();
523
0
    {
524
0
      int index;
525
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), AuthenticatorAttachmentValues::strings, "AuthenticatorAttachment", "'authenticatorAttachment' member of AuthenticatorSelectionCriteria", &index)) {
526
0
        return false;
527
0
      }
528
0
      MOZ_ASSERT(index >= 0);
529
0
      (mAuthenticatorAttachment.Value()) = static_cast<AuthenticatorAttachment>(index);
530
0
    }
531
0
    mIsAnyMemberPresent = true;
532
0
  }
533
0
534
0
  if (!isNull) {
535
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->requireResidentKey_id, temp.ptr())) {
536
0
      return false;
537
0
    }
538
0
  }
539
0
  if (!isNull && !temp->isUndefined()) {
540
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mRequireResidentKey)) {
541
0
      return false;
542
0
    }
543
0
  } else {
544
0
    mRequireResidentKey = false;
545
0
  }
546
0
  mIsAnyMemberPresent = true;
547
0
548
0
  if (!isNull) {
549
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->userVerification_id, temp.ptr())) {
550
0
      return false;
551
0
    }
552
0
  }
553
0
  if (!isNull && !temp->isUndefined()) {
554
0
    {
555
0
      int index;
556
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), UserVerificationRequirementValues::strings, "UserVerificationRequirement", "'userVerification' member of AuthenticatorSelectionCriteria", &index)) {
557
0
        return false;
558
0
      }
559
0
      MOZ_ASSERT(index >= 0);
560
0
      mUserVerification = static_cast<UserVerificationRequirement>(index);
561
0
    }
562
0
  } else {
563
0
    mUserVerification = UserVerificationRequirement::Preferred;
564
0
  }
565
0
  mIsAnyMemberPresent = true;
566
0
  return true;
567
0
}
568
569
bool
570
AuthenticatorSelectionCriteria::Init(const nsAString& aJSON)
571
0
{
572
0
  AutoJSAPI jsapi;
573
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
574
0
  if (!cleanGlobal) {
575
0
    return false;
576
0
  }
577
0
  if (!jsapi.Init(cleanGlobal)) {
578
0
    return false;
579
0
  }
580
0
  JSContext* cx = jsapi.cx();
581
0
  JS::Rooted<JS::Value> json(cx);
582
0
  bool ok = ParseJSON(cx, aJSON, &json);
583
0
  NS_ENSURE_TRUE(ok, false);
584
0
  return Init(cx, json);
585
0
}
586
587
bool
588
AuthenticatorSelectionCriteria::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
589
0
{
590
0
  AuthenticatorSelectionCriteriaAtoms* atomsCache = GetAtomCache<AuthenticatorSelectionCriteriaAtoms>(cx);
591
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
592
0
    return false;
593
0
  }
594
0
595
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
596
0
  if (!obj) {
597
0
    return false;
598
0
  }
599
0
  rval.set(JS::ObjectValue(*obj));
600
0
601
0
  if (mAuthenticatorAttachment.WasPassed()) {
602
0
    do {
603
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
604
0
      JS::Rooted<JS::Value> temp(cx);
605
0
      AuthenticatorAttachment const & currentValue = mAuthenticatorAttachment.InternalValue();
606
0
      if (!ToJSValue(cx, currentValue, &temp)) {
607
0
        return false;
608
0
      }
609
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->authenticatorAttachment_id, temp, JSPROP_ENUMERATE)) {
610
0
        return false;
611
0
      }
612
0
      break;
613
0
    } while(false);
614
0
  }
615
0
616
0
  do {
617
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
618
0
    JS::Rooted<JS::Value> temp(cx);
619
0
    bool const & currentValue = mRequireResidentKey;
620
0
    temp.setBoolean(currentValue);
621
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->requireResidentKey_id, temp, JSPROP_ENUMERATE)) {
622
0
      return false;
623
0
    }
624
0
    break;
625
0
  } while(false);
626
0
627
0
  do {
628
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
629
0
    JS::Rooted<JS::Value> temp(cx);
630
0
    UserVerificationRequirement const & currentValue = mUserVerification;
631
0
    if (!ToJSValue(cx, currentValue, &temp)) {
632
0
      return false;
633
0
    }
634
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->userVerification_id, temp, JSPROP_ENUMERATE)) {
635
0
      return false;
636
0
    }
637
0
    break;
638
0
  } while(false);
639
0
640
0
  return true;
641
0
}
642
643
bool
644
AuthenticatorSelectionCriteria::ToJSON(nsAString& aJSON) const
645
0
{
646
0
  AutoJSAPI jsapi;
647
0
  jsapi.Init();
648
0
  JSContext *cx = jsapi.cx();
649
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
650
0
  // because we'll only be creating objects, in ways that have no
651
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
652
0
  // which likewise guarantees no side-effects for the sorts of
653
0
  // things we will pass it.
654
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
655
0
  JS::Rooted<JS::Value> val(cx);
656
0
  if (!ToObjectInternal(cx, &val)) {
657
0
    return false;
658
0
  }
659
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
660
0
  return StringifyToJSON(cx, obj, aJSON);
661
0
}
662
663
void
664
AuthenticatorSelectionCriteria::TraceDictionary(JSTracer* trc)
665
0
{
666
0
}
667
668
AuthenticatorSelectionCriteria&
669
AuthenticatorSelectionCriteria::operator=(const AuthenticatorSelectionCriteria& aOther)
670
0
{
671
0
  DictionaryBase::operator=(aOther);
672
0
  mAuthenticatorAttachment.Reset();
673
0
  if (aOther.mAuthenticatorAttachment.WasPassed()) {
674
0
    mAuthenticatorAttachment.Construct(aOther.mAuthenticatorAttachment.Value());
675
0
  }
676
0
  mRequireResidentKey = aOther.mRequireResidentKey;
677
0
  mUserVerification = aOther.mUserVerification;
678
0
  return *this;
679
0
}
680
681
namespace binding_detail {
682
} // namespace binding_detail
683
684
685
686
PublicKeyCredentialDescriptor::PublicKeyCredentialDescriptor()
687
0
{
688
0
  // Safe to pass a null context if we pass a null value
689
0
  Init(nullptr, JS::NullHandleValue);
690
0
}
691
692
693
bool
694
PublicKeyCredentialDescriptor::InitIds(JSContext* cx, PublicKeyCredentialDescriptorAtoms* atomsCache)
695
0
{
696
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
697
0
698
0
  // Initialize these in reverse order so that any failure leaves the first one
699
0
  // uninitialized.
700
0
  if (!atomsCache->type_id.init(cx, "type") ||
701
0
      !atomsCache->transports_id.init(cx, "transports") ||
702
0
      !atomsCache->id_id.init(cx, "id")) {
703
0
    return false;
704
0
  }
705
0
  return true;
706
0
}
707
708
bool
709
PublicKeyCredentialDescriptor::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
710
0
{
711
0
  // Passing a null JSContext is OK only if we're initing from null,
712
0
  // Since in that case we will not have to do any property gets
713
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
714
0
  // checkers by static analysis tools
715
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
716
0
  PublicKeyCredentialDescriptorAtoms* atomsCache = nullptr;
717
0
  if (cx) {
718
0
    atomsCache = GetAtomCache<PublicKeyCredentialDescriptorAtoms>(cx);
719
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
720
0
      return false;
721
0
    }
722
0
  }
723
0
724
0
  if (!IsConvertibleToDictionary(val)) {
725
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
726
0
  }
727
0
728
0
  bool isNull = val.isNullOrUndefined();
729
0
  // We only need these if !isNull, in which case we have |cx|.
730
0
  Maybe<JS::Rooted<JSObject *> > object;
731
0
  Maybe<JS::Rooted<JS::Value> > temp;
732
0
  if (!isNull) {
733
0
    MOZ_ASSERT(cx);
734
0
    object.emplace(cx, &val.toObject());
735
0
    temp.emplace(cx);
736
0
  }
737
0
  if (!isNull) {
738
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->id_id, temp.ptr())) {
739
0
      return false;
740
0
    }
741
0
  }
742
0
  if (!isNull && !temp->isUndefined()) {
743
0
    {
744
0
      bool done = false, failed = false, tryNext;
745
0
      if (temp.ref().isObject()) {
746
0
        done = (failed = !mId.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
747
0
               (failed = !mId.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
748
0
749
0
      }
750
0
      if (failed) {
751
0
        return false;
752
0
      }
753
0
      if (!done) {
754
0
        ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'id' member of PublicKeyCredentialDescriptor", "ArrayBufferView, ArrayBuffer");
755
0
        return false;
756
0
      }
757
0
    }
758
0
    mIsAnyMemberPresent = true;
759
0
  } else if (cx) {
760
0
    // Don't error out if we have no cx.  In that
761
0
    // situation the caller is default-constructing us and we'll
762
0
    // just assume they know what they're doing.
763
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
764
0
                             "'id' member of PublicKeyCredentialDescriptor");
765
0
  }
766
0
767
0
  if (!isNull) {
768
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->transports_id, temp.ptr())) {
769
0
      return false;
770
0
    }
771
0
  }
772
0
  if (!isNull && !temp->isUndefined()) {
773
0
    mTransports.Construct();
774
0
    if (temp.ref().isObject()) {
775
0
      JS::ForOfIterator iter(cx);
776
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
777
0
        return false;
778
0
      }
779
0
      if (!iter.valueIsIterable()) {
780
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transports' member of PublicKeyCredentialDescriptor");
781
0
        return false;
782
0
      }
783
0
      Sequence<AuthenticatorTransport> &arr = (mTransports.Value());
784
0
      JS::Rooted<JS::Value> temp(cx);
785
0
      while (true) {
786
0
        bool done;
787
0
        if (!iter.next(&temp, &done)) {
788
0
          return false;
789
0
        }
790
0
        if (done) {
791
0
          break;
792
0
        }
793
0
        AuthenticatorTransport* slotPtr = arr.AppendElement(mozilla::fallible);
794
0
        if (!slotPtr) {
795
0
          JS_ReportOutOfMemory(cx);
796
0
          return false;
797
0
        }
798
0
        AuthenticatorTransport& slot = *slotPtr;
799
0
        {
800
0
          int index;
801
0
          if (!FindEnumStringIndex<true>(cx, temp, AuthenticatorTransportValues::strings, "AuthenticatorTransport", "Element of 'transports' member of PublicKeyCredentialDescriptor", &index)) {
802
0
            return false;
803
0
          }
804
0
          MOZ_ASSERT(index >= 0);
805
0
          slot = static_cast<AuthenticatorTransport>(index);
806
0
        }
807
0
      }
808
0
    } else {
809
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transports' member of PublicKeyCredentialDescriptor");
810
0
      return false;
811
0
    }
812
0
    mIsAnyMemberPresent = true;
813
0
  }
814
0
815
0
  if (!isNull) {
816
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
817
0
      return false;
818
0
    }
819
0
  }
820
0
  if (!isNull && !temp->isUndefined()) {
821
0
    {
822
0
      int index;
823
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), PublicKeyCredentialTypeValues::strings, "PublicKeyCredentialType", "'type' member of PublicKeyCredentialDescriptor", &index)) {
824
0
        return false;
825
0
      }
826
0
      MOZ_ASSERT(index >= 0);
827
0
      mType = static_cast<PublicKeyCredentialType>(index);
828
0
    }
829
0
    mIsAnyMemberPresent = true;
830
0
  } else if (cx) {
831
0
    // Don't error out if we have no cx.  In that
832
0
    // situation the caller is default-constructing us and we'll
833
0
    // just assume they know what they're doing.
834
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
835
0
                             "'type' member of PublicKeyCredentialDescriptor");
836
0
  }
837
0
  return true;
838
0
}
839
840
bool
841
PublicKeyCredentialDescriptor::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
842
0
{
843
0
  PublicKeyCredentialDescriptorAtoms* atomsCache = GetAtomCache<PublicKeyCredentialDescriptorAtoms>(cx);
844
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
845
0
    return false;
846
0
  }
847
0
848
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
849
0
  if (!obj) {
850
0
    return false;
851
0
  }
852
0
  rval.set(JS::ObjectValue(*obj));
853
0
854
0
  do {
855
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
856
0
    JS::Rooted<JS::Value> temp(cx);
857
0
    OwningArrayBufferViewOrArrayBuffer const & currentValue = mId;
858
0
    if (!currentValue.ToJSVal(cx, obj, &temp)) {
859
0
      return false;
860
0
    }
861
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->id_id, temp, JSPROP_ENUMERATE)) {
862
0
      return false;
863
0
    }
864
0
    break;
865
0
  } while(false);
866
0
867
0
  if (mTransports.WasPassed()) {
868
0
    do {
869
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
870
0
      JS::Rooted<JS::Value> temp(cx);
871
0
      Sequence<AuthenticatorTransport> const & currentValue = mTransports.InternalValue();
872
0
873
0
      uint32_t length = currentValue.Length();
874
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
875
0
      if (!returnArray) {
876
0
        return false;
877
0
      }
878
0
      // Scope for 'tmp'
879
0
      {
880
0
        JS::Rooted<JS::Value> tmp(cx);
881
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
882
0
          // Control block to let us common up the JS_DefineElement calls when there
883
0
          // are different ways to succeed at wrapping the object.
884
0
          do {
885
0
            if (!ToJSValue(cx, currentValue[sequenceIdx0], &tmp)) {
886
0
              return false;
887
0
            }
888
0
            break;
889
0
          } while (false);
890
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
891
0
                                JSPROP_ENUMERATE)) {
892
0
            return false;
893
0
          }
894
0
        }
895
0
      }
896
0
      temp.setObject(*returnArray);
897
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->transports_id, temp, JSPROP_ENUMERATE)) {
898
0
        return false;
899
0
      }
900
0
      break;
901
0
    } while(false);
902
0
  }
903
0
904
0
  do {
905
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
906
0
    JS::Rooted<JS::Value> temp(cx);
907
0
    PublicKeyCredentialType const & currentValue = mType;
908
0
    if (!ToJSValue(cx, currentValue, &temp)) {
909
0
      return false;
910
0
    }
911
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->type_id, temp, JSPROP_ENUMERATE)) {
912
0
      return false;
913
0
    }
914
0
    break;
915
0
  } while(false);
916
0
917
0
  return true;
918
0
}
919
920
void
921
PublicKeyCredentialDescriptor::TraceDictionary(JSTracer* trc)
922
0
{
923
0
  mId.TraceUnion(trc);
924
0
}
925
926
namespace binding_detail {
927
} // namespace binding_detail
928
929
930
931
PublicKeyCredentialEntity::PublicKeyCredentialEntity()
932
0
{
933
0
  // Safe to pass a null context if we pass a null value
934
0
  Init(nullptr, JS::NullHandleValue);
935
0
}
936
937
938
939
bool
940
PublicKeyCredentialEntity::InitIds(JSContext* cx, PublicKeyCredentialEntityAtoms* atomsCache)
941
0
{
942
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
943
0
944
0
  // Initialize these in reverse order so that any failure leaves the first one
945
0
  // uninitialized.
946
0
  if (!atomsCache->name_id.init(cx, "name") ||
947
0
      !atomsCache->icon_id.init(cx, "icon")) {
948
0
    return false;
949
0
  }
950
0
  return true;
951
0
}
952
953
bool
954
PublicKeyCredentialEntity::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
955
0
{
956
0
  // Passing a null JSContext is OK only if we're initing from null,
957
0
  // Since in that case we will not have to do any property gets
958
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
959
0
  // checkers by static analysis tools
960
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
961
0
  PublicKeyCredentialEntityAtoms* atomsCache = nullptr;
962
0
  if (cx) {
963
0
    atomsCache = GetAtomCache<PublicKeyCredentialEntityAtoms>(cx);
964
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
965
0
      return false;
966
0
    }
967
0
  }
968
0
969
0
  if (!IsConvertibleToDictionary(val)) {
970
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
971
0
  }
972
0
973
0
  bool isNull = val.isNullOrUndefined();
974
0
  // We only need these if !isNull, in which case we have |cx|.
975
0
  Maybe<JS::Rooted<JSObject *> > object;
976
0
  Maybe<JS::Rooted<JS::Value> > temp;
977
0
  if (!isNull) {
978
0
    MOZ_ASSERT(cx);
979
0
    object.emplace(cx, &val.toObject());
980
0
    temp.emplace(cx);
981
0
  }
982
0
  if (!isNull) {
983
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->icon_id, temp.ptr())) {
984
0
      return false;
985
0
    }
986
0
  }
987
0
  if (!isNull && !temp->isUndefined()) {
988
0
    mIcon.Construct();
989
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mIcon.Value()))) {
990
0
      return false;
991
0
    }
992
0
    NormalizeUSVString((mIcon.Value()));
993
0
    mIsAnyMemberPresent = true;
994
0
  }
995
0
996
0
  if (!isNull) {
997
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->name_id, temp.ptr())) {
998
0
      return false;
999
0
    }
1000
0
  }
1001
0
  if (!isNull && !temp->isUndefined()) {
1002
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mName)) {
1003
0
      return false;
1004
0
    }
1005
0
    mIsAnyMemberPresent = true;
1006
0
  } else if (cx) {
1007
0
    // Don't error out if we have no cx.  In that
1008
0
    // situation the caller is default-constructing us and we'll
1009
0
    // just assume they know what they're doing.
1010
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1011
0
                             "'name' member of PublicKeyCredentialEntity");
1012
0
  }
1013
0
  return true;
1014
0
}
1015
1016
bool
1017
PublicKeyCredentialEntity::Init(const nsAString& aJSON)
1018
0
{
1019
0
  AutoJSAPI jsapi;
1020
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1021
0
  if (!cleanGlobal) {
1022
0
    return false;
1023
0
  }
1024
0
  if (!jsapi.Init(cleanGlobal)) {
1025
0
    return false;
1026
0
  }
1027
0
  JSContext* cx = jsapi.cx();
1028
0
  JS::Rooted<JS::Value> json(cx);
1029
0
  bool ok = ParseJSON(cx, aJSON, &json);
1030
0
  NS_ENSURE_TRUE(ok, false);
1031
0
  return Init(cx, json);
1032
0
}
1033
1034
bool
1035
PublicKeyCredentialEntity::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1036
0
{
1037
0
  PublicKeyCredentialEntityAtoms* atomsCache = GetAtomCache<PublicKeyCredentialEntityAtoms>(cx);
1038
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1039
0
    return false;
1040
0
  }
1041
0
1042
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1043
0
  if (!obj) {
1044
0
    return false;
1045
0
  }
1046
0
  rval.set(JS::ObjectValue(*obj));
1047
0
1048
0
  if (mIcon.WasPassed()) {
1049
0
    do {
1050
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1051
0
      JS::Rooted<JS::Value> temp(cx);
1052
0
      nsString const & currentValue = mIcon.InternalValue();
1053
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1054
0
        return false;
1055
0
      }
1056
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->icon_id, temp, JSPROP_ENUMERATE)) {
1057
0
        return false;
1058
0
      }
1059
0
      break;
1060
0
    } while(false);
1061
0
  }
1062
0
1063
0
  do {
1064
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1065
0
    JS::Rooted<JS::Value> temp(cx);
1066
0
    nsString const & currentValue = mName;
1067
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1068
0
      return false;
1069
0
    }
1070
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->name_id, temp, JSPROP_ENUMERATE)) {
1071
0
      return false;
1072
0
    }
1073
0
    break;
1074
0
  } while(false);
1075
0
1076
0
  return true;
1077
0
}
1078
1079
bool
1080
PublicKeyCredentialEntity::ToJSON(nsAString& aJSON) const
1081
0
{
1082
0
  AutoJSAPI jsapi;
1083
0
  jsapi.Init();
1084
0
  JSContext *cx = jsapi.cx();
1085
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1086
0
  // because we'll only be creating objects, in ways that have no
1087
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1088
0
  // which likewise guarantees no side-effects for the sorts of
1089
0
  // things we will pass it.
1090
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1091
0
  JS::Rooted<JS::Value> val(cx);
1092
0
  if (!ToObjectInternal(cx, &val)) {
1093
0
    return false;
1094
0
  }
1095
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1096
0
  return StringifyToJSON(cx, obj, aJSON);
1097
0
}
1098
1099
void
1100
PublicKeyCredentialEntity::TraceDictionary(JSTracer* trc)
1101
0
{
1102
0
}
1103
1104
PublicKeyCredentialEntity&
1105
PublicKeyCredentialEntity::operator=(const PublicKeyCredentialEntity& aOther)
1106
0
{
1107
0
  DictionaryBase::operator=(aOther);
1108
0
  mIcon.Reset();
1109
0
  if (aOther.mIcon.WasPassed()) {
1110
0
    mIcon.Construct(aOther.mIcon.Value());
1111
0
  }
1112
0
  mName = aOther.mName;
1113
0
  return *this;
1114
0
}
1115
1116
namespace binding_detail {
1117
} // namespace binding_detail
1118
1119
1120
1121
PublicKeyCredentialParameters::PublicKeyCredentialParameters()
1122
0
{
1123
0
  // Safe to pass a null context if we pass a null value
1124
0
  Init(nullptr, JS::NullHandleValue);
1125
0
}
1126
1127
1128
1129
bool
1130
PublicKeyCredentialParameters::InitIds(JSContext* cx, PublicKeyCredentialParametersAtoms* atomsCache)
1131
0
{
1132
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1133
0
1134
0
  // Initialize these in reverse order so that any failure leaves the first one
1135
0
  // uninitialized.
1136
0
  if (!atomsCache->type_id.init(cx, "type") ||
1137
0
      !atomsCache->alg_id.init(cx, "alg")) {
1138
0
    return false;
1139
0
  }
1140
0
  return true;
1141
0
}
1142
1143
bool
1144
PublicKeyCredentialParameters::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1145
0
{
1146
0
  // Passing a null JSContext is OK only if we're initing from null,
1147
0
  // Since in that case we will not have to do any property gets
1148
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1149
0
  // checkers by static analysis tools
1150
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1151
0
  PublicKeyCredentialParametersAtoms* atomsCache = nullptr;
1152
0
  if (cx) {
1153
0
    atomsCache = GetAtomCache<PublicKeyCredentialParametersAtoms>(cx);
1154
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1155
0
      return false;
1156
0
    }
1157
0
  }
1158
0
1159
0
  if (!IsConvertibleToDictionary(val)) {
1160
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1161
0
  }
1162
0
1163
0
  bool isNull = val.isNullOrUndefined();
1164
0
  // We only need these if !isNull, in which case we have |cx|.
1165
0
  Maybe<JS::Rooted<JSObject *> > object;
1166
0
  Maybe<JS::Rooted<JS::Value> > temp;
1167
0
  if (!isNull) {
1168
0
    MOZ_ASSERT(cx);
1169
0
    object.emplace(cx, &val.toObject());
1170
0
    temp.emplace(cx);
1171
0
  }
1172
0
  if (!isNull) {
1173
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->alg_id, temp.ptr())) {
1174
0
      return false;
1175
0
    }
1176
0
  }
1177
0
  if (!isNull && !temp->isUndefined()) {
1178
0
    if (!ValueToPrimitive<int32_t, eDefault>(cx, temp.ref(), &mAlg)) {
1179
0
      return false;
1180
0
    }
1181
0
    mIsAnyMemberPresent = true;
1182
0
  } else if (cx) {
1183
0
    // Don't error out if we have no cx.  In that
1184
0
    // situation the caller is default-constructing us and we'll
1185
0
    // just assume they know what they're doing.
1186
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1187
0
                             "'alg' member of PublicKeyCredentialParameters");
1188
0
  }
1189
0
1190
0
  if (!isNull) {
1191
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
1192
0
      return false;
1193
0
    }
1194
0
  }
1195
0
  if (!isNull && !temp->isUndefined()) {
1196
0
    {
1197
0
      int index;
1198
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), PublicKeyCredentialTypeValues::strings, "PublicKeyCredentialType", "'type' member of PublicKeyCredentialParameters", &index)) {
1199
0
        return false;
1200
0
      }
1201
0
      MOZ_ASSERT(index >= 0);
1202
0
      mType = static_cast<PublicKeyCredentialType>(index);
1203
0
    }
1204
0
    mIsAnyMemberPresent = true;
1205
0
  } else if (cx) {
1206
0
    // Don't error out if we have no cx.  In that
1207
0
    // situation the caller is default-constructing us and we'll
1208
0
    // just assume they know what they're doing.
1209
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1210
0
                             "'type' member of PublicKeyCredentialParameters");
1211
0
  }
1212
0
  return true;
1213
0
}
1214
1215
bool
1216
PublicKeyCredentialParameters::Init(const nsAString& aJSON)
1217
0
{
1218
0
  AutoJSAPI jsapi;
1219
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1220
0
  if (!cleanGlobal) {
1221
0
    return false;
1222
0
  }
1223
0
  if (!jsapi.Init(cleanGlobal)) {
1224
0
    return false;
1225
0
  }
1226
0
  JSContext* cx = jsapi.cx();
1227
0
  JS::Rooted<JS::Value> json(cx);
1228
0
  bool ok = ParseJSON(cx, aJSON, &json);
1229
0
  NS_ENSURE_TRUE(ok, false);
1230
0
  return Init(cx, json);
1231
0
}
1232
1233
bool
1234
PublicKeyCredentialParameters::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1235
0
{
1236
0
  PublicKeyCredentialParametersAtoms* atomsCache = GetAtomCache<PublicKeyCredentialParametersAtoms>(cx);
1237
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1238
0
    return false;
1239
0
  }
1240
0
1241
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1242
0
  if (!obj) {
1243
0
    return false;
1244
0
  }
1245
0
  rval.set(JS::ObjectValue(*obj));
1246
0
1247
0
  do {
1248
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1249
0
    JS::Rooted<JS::Value> temp(cx);
1250
0
    int32_t const & currentValue = mAlg;
1251
0
    temp.setInt32(int32_t(currentValue));
1252
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->alg_id, temp, JSPROP_ENUMERATE)) {
1253
0
      return false;
1254
0
    }
1255
0
    break;
1256
0
  } while(false);
1257
0
1258
0
  do {
1259
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1260
0
    JS::Rooted<JS::Value> temp(cx);
1261
0
    PublicKeyCredentialType const & currentValue = mType;
1262
0
    if (!ToJSValue(cx, currentValue, &temp)) {
1263
0
      return false;
1264
0
    }
1265
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->type_id, temp, JSPROP_ENUMERATE)) {
1266
0
      return false;
1267
0
    }
1268
0
    break;
1269
0
  } while(false);
1270
0
1271
0
  return true;
1272
0
}
1273
1274
bool
1275
PublicKeyCredentialParameters::ToJSON(nsAString& aJSON) const
1276
0
{
1277
0
  AutoJSAPI jsapi;
1278
0
  jsapi.Init();
1279
0
  JSContext *cx = jsapi.cx();
1280
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1281
0
  // because we'll only be creating objects, in ways that have no
1282
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1283
0
  // which likewise guarantees no side-effects for the sorts of
1284
0
  // things we will pass it.
1285
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1286
0
  JS::Rooted<JS::Value> val(cx);
1287
0
  if (!ToObjectInternal(cx, &val)) {
1288
0
    return false;
1289
0
  }
1290
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1291
0
  return StringifyToJSON(cx, obj, aJSON);
1292
0
}
1293
1294
void
1295
PublicKeyCredentialParameters::TraceDictionary(JSTracer* trc)
1296
0
{
1297
0
}
1298
1299
PublicKeyCredentialParameters&
1300
PublicKeyCredentialParameters::operator=(const PublicKeyCredentialParameters& aOther)
1301
0
{
1302
0
  DictionaryBase::operator=(aOther);
1303
0
  mAlg = aOther.mAlg;
1304
0
  mType = aOther.mType;
1305
0
  return *this;
1306
0
}
1307
1308
namespace binding_detail {
1309
} // namespace binding_detail
1310
1311
1312
1313
CollectedClientData::CollectedClientData()
1314
  : mClientExtensions(FastDictionaryInitializer())
1315
0
{
1316
0
  // Safe to pass a null context if we pass a null value
1317
0
  Init(nullptr, JS::NullHandleValue);
1318
0
}
1319
1320
1321
bool
1322
CollectedClientData::InitIds(JSContext* cx, CollectedClientDataAtoms* atomsCache)
1323
0
{
1324
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1325
0
1326
0
  // Initialize these in reverse order so that any failure leaves the first one
1327
0
  // uninitialized.
1328
0
  if (!atomsCache->type_id.init(cx, "type") ||
1329
0
      !atomsCache->tokenBindingId_id.init(cx, "tokenBindingId") ||
1330
0
      !atomsCache->origin_id.init(cx, "origin") ||
1331
0
      !atomsCache->hashAlgorithm_id.init(cx, "hashAlgorithm") ||
1332
0
      !atomsCache->clientExtensions_id.init(cx, "clientExtensions") ||
1333
0
      !atomsCache->challenge_id.init(cx, "challenge") ||
1334
0
      !atomsCache->authenticatorExtensions_id.init(cx, "authenticatorExtensions")) {
1335
0
    return false;
1336
0
  }
1337
0
  return true;
1338
0
}
1339
1340
bool
1341
CollectedClientData::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1342
0
{
1343
0
  // Passing a null JSContext is OK only if we're initing from null,
1344
0
  // Since in that case we will not have to do any property gets
1345
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1346
0
  // checkers by static analysis tools
1347
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1348
0
  CollectedClientDataAtoms* atomsCache = nullptr;
1349
0
  if (cx) {
1350
0
    atomsCache = GetAtomCache<CollectedClientDataAtoms>(cx);
1351
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1352
0
      return false;
1353
0
    }
1354
0
  }
1355
0
1356
0
  if (!IsConvertibleToDictionary(val)) {
1357
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1358
0
  }
1359
0
1360
0
  bool isNull = val.isNullOrUndefined();
1361
0
  // We only need these if !isNull, in which case we have |cx|.
1362
0
  Maybe<JS::Rooted<JSObject *> > object;
1363
0
  Maybe<JS::Rooted<JS::Value> > temp;
1364
0
  if (!isNull) {
1365
0
    MOZ_ASSERT(cx);
1366
0
    object.emplace(cx, &val.toObject());
1367
0
    temp.emplace(cx);
1368
0
  }
1369
0
  if (!isNull) {
1370
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->authenticatorExtensions_id, temp.ptr())) {
1371
0
      return false;
1372
0
    }
1373
0
  }
1374
0
  if (!isNull && !temp->isUndefined()) {
1375
0
    mAuthenticatorExtensions.Construct();
1376
0
    if (temp.ref().isObject()) {
1377
0
      auto& recordEntries = (mAuthenticatorExtensions.Value()).Entries();
1378
0
1379
0
      JS::Rooted<JSObject*> recordObj(cx, &temp.ref().toObject());
1380
0
      JS::AutoIdVector ids(cx);
1381
0
      if (!js::GetPropertyKeys(cx, recordObj,
1382
0
                               JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &ids)) {
1383
0
        return false;
1384
0
      }
1385
0
      if (!recordEntries.SetCapacity(ids.length(), mozilla::fallible)) {
1386
0
        JS_ReportOutOfMemory(cx);
1387
0
        return false;
1388
0
      }
1389
0
      JS::Rooted<JS::Value> propNameValue(cx);
1390
0
      JS::Rooted<JS::Value> temp(cx);
1391
0
      JS::Rooted<jsid> curId(cx);
1392
0
      JS::Rooted<JS::Value> idVal(cx);
1393
0
      // Use a hashset to keep track of ids seen, to avoid
1394
0
      // introducing nasty O(N^2) behavior scanning for them all the
1395
0
      // time.  Ideally we'd use a data structure with O(1) lookup
1396
0
      // _and_ ordering for the MozMap, but we don't have one lying
1397
0
      // around.
1398
0
      nsTHashtable<nsStringHashKey> idsSeen;
1399
0
      for (size_t i = 0; i < ids.length(); ++i) {
1400
0
        curId = ids[i];
1401
0
1402
0
        JS::Rooted<JS::PropertyDescriptor> desc(cx);
1403
0
        if (!JS_GetOwnPropertyDescriptorById(cx, recordObj, curId,
1404
0
                                             &desc)) {
1405
0
          return false;
1406
0
        }
1407
0
1408
0
        if (!desc.object() /* == undefined in spec terms */ ||
1409
0
            !desc.enumerable()) {
1410
0
          continue;
1411
0
        }
1412
0
1413
0
        idVal = js::IdToValue(curId);
1414
0
        nsString propName;
1415
0
        // This will just throw if idVal is a Symbol, like the spec says
1416
0
        // to do.
1417
0
        if (!ConvertJSValueToString(cx, idVal, propName)) {
1418
0
          return false;
1419
0
        }
1420
0
1421
0
        if (!JS_GetPropertyById(cx, recordObj, curId, &temp)) {
1422
0
          return false;
1423
0
        }
1424
0
1425
0
        Record<nsString, nsString>::EntryType* entry;
1426
0
        if (!idsSeen.EnsureInserted(propName)) {
1427
0
          // Find the existing entry.
1428
0
          auto idx = recordEntries.IndexOf(propName);
1429
0
          MOZ_ASSERT(idx != recordEntries.NoIndex,
1430
0
                     "Why is it not found?");
1431
0
          // Now blow it away to make it look like it was just added
1432
0
          // to the array, because it's not obvious that it's
1433
0
          // safe to write to its already-initialized mValue via our
1434
0
          // normal codegen conversions.  For example, the value
1435
0
          // could be a union and this would change its type, but
1436
0
          // codegen assumes we won't do that.
1437
0
          entry = recordEntries.ReconstructElementAt(idx);
1438
0
        } else {
1439
0
          // Safe to do an infallible append here, because we did a
1440
0
          // SetCapacity above to the right capacity.
1441
0
          entry = recordEntries.AppendElement();
1442
0
        }
1443
0
        entry->mKey = propName;
1444
0
        nsString& slot = entry->mValue;
1445
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
1446
0
          return false;
1447
0
        }
1448
0
      }
1449
0
    } else {
1450
0
      ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'authenticatorExtensions' member of CollectedClientData");
1451
0
      return false;
1452
0
    }
1453
0
    mIsAnyMemberPresent = true;
1454
0
  }
1455
0
1456
0
  if (!isNull) {
1457
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->challenge_id, temp.ptr())) {
1458
0
      return false;
1459
0
    }
1460
0
  }
1461
0
  if (!isNull && !temp->isUndefined()) {
1462
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mChallenge)) {
1463
0
      return false;
1464
0
    }
1465
0
    mIsAnyMemberPresent = true;
1466
0
  } else if (cx) {
1467
0
    // Don't error out if we have no cx.  In that
1468
0
    // situation the caller is default-constructing us and we'll
1469
0
    // just assume they know what they're doing.
1470
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1471
0
                             "'challenge' member of CollectedClientData");
1472
0
  }
1473
0
1474
0
  if (!isNull) {
1475
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->clientExtensions_id, temp.ptr())) {
1476
0
      return false;
1477
0
    }
1478
0
  }
1479
0
  if (!mClientExtensions.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue,  "'clientExtensions' member of CollectedClientData", passedToJSImpl)) {
1480
0
    return false;
1481
0
  }
1482
0
  mIsAnyMemberPresent = true;
1483
0
1484
0
  if (!isNull) {
1485
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->hashAlgorithm_id, temp.ptr())) {
1486
0
      return false;
1487
0
    }
1488
0
  }
1489
0
  if (!isNull && !temp->isUndefined()) {
1490
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHashAlgorithm)) {
1491
0
      return false;
1492
0
    }
1493
0
    mIsAnyMemberPresent = true;
1494
0
  } else if (cx) {
1495
0
    // Don't error out if we have no cx.  In that
1496
0
    // situation the caller is default-constructing us and we'll
1497
0
    // just assume they know what they're doing.
1498
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1499
0
                             "'hashAlgorithm' member of CollectedClientData");
1500
0
  }
1501
0
1502
0
  if (!isNull) {
1503
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->origin_id, temp.ptr())) {
1504
0
      return false;
1505
0
    }
1506
0
  }
1507
0
  if (!isNull && !temp->isUndefined()) {
1508
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mOrigin)) {
1509
0
      return false;
1510
0
    }
1511
0
    mIsAnyMemberPresent = true;
1512
0
  } else if (cx) {
1513
0
    // Don't error out if we have no cx.  In that
1514
0
    // situation the caller is default-constructing us and we'll
1515
0
    // just assume they know what they're doing.
1516
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1517
0
                             "'origin' member of CollectedClientData");
1518
0
  }
1519
0
1520
0
  if (!isNull) {
1521
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->tokenBindingId_id, temp.ptr())) {
1522
0
      return false;
1523
0
    }
1524
0
  }
1525
0
  if (!isNull && !temp->isUndefined()) {
1526
0
    mTokenBindingId.Construct();
1527
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTokenBindingId.Value()))) {
1528
0
      return false;
1529
0
    }
1530
0
    mIsAnyMemberPresent = true;
1531
0
  }
1532
0
1533
0
  if (!isNull) {
1534
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
1535
0
      return false;
1536
0
    }
1537
0
  }
1538
0
  if (!isNull && !temp->isUndefined()) {
1539
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mType)) {
1540
0
      return false;
1541
0
    }
1542
0
    mIsAnyMemberPresent = true;
1543
0
  } else if (cx) {
1544
0
    // Don't error out if we have no cx.  In that
1545
0
    // situation the caller is default-constructing us and we'll
1546
0
    // just assume they know what they're doing.
1547
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1548
0
                             "'type' member of CollectedClientData");
1549
0
  }
1550
0
  return true;
1551
0
}
1552
1553
bool
1554
CollectedClientData::Init(const nsAString& aJSON)
1555
0
{
1556
0
  AutoJSAPI jsapi;
1557
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1558
0
  if (!cleanGlobal) {
1559
0
    return false;
1560
0
  }
1561
0
  if (!jsapi.Init(cleanGlobal)) {
1562
0
    return false;
1563
0
  }
1564
0
  JSContext* cx = jsapi.cx();
1565
0
  JS::Rooted<JS::Value> json(cx);
1566
0
  bool ok = ParseJSON(cx, aJSON, &json);
1567
0
  NS_ENSURE_TRUE(ok, false);
1568
0
  return Init(cx, json);
1569
0
}
1570
1571
bool
1572
CollectedClientData::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1573
0
{
1574
0
  CollectedClientDataAtoms* atomsCache = GetAtomCache<CollectedClientDataAtoms>(cx);
1575
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1576
0
    return false;
1577
0
  }
1578
0
1579
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1580
0
  if (!obj) {
1581
0
    return false;
1582
0
  }
1583
0
  rval.set(JS::ObjectValue(*obj));
1584
0
1585
0
  if (mAuthenticatorExtensions.WasPassed()) {
1586
0
    do {
1587
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1588
0
      JS::Rooted<JS::Value> temp(cx);
1589
0
      Record<nsString, nsString> const & currentValue = mAuthenticatorExtensions.InternalValue();
1590
0
1591
0
      JS::Rooted<JSObject*> returnObj(cx, JS_NewPlainObject(cx));
1592
0
      if (!returnObj) {
1593
0
        return false;
1594
0
      }
1595
0
      // Scope for 'tmp'
1596
0
      {
1597
0
        JS::Rooted<JS::Value> tmp(cx);
1598
0
        for (auto& entry : currentValue.Entries()) {
1599
0
          auto& recordValue0 = entry.mValue;
1600
0
          // Control block to let us common up the JS_DefineUCProperty calls when there
1601
0
          // are different ways to succeed at wrapping the value.
1602
0
          do {
1603
0
            if (!xpc::NonVoidStringToJsval(cx, recordValue0, &tmp)) {
1604
0
              return false;
1605
0
            }
1606
0
            break;
1607
0
          } while (false);
1608
0
          if (!JS_DefineUCProperty(cx, returnObj,
1609
0
                                   entry.mKey.BeginReading(),
1610
0
                                   entry.mKey.Length(), tmp,
1611
0
                                   JSPROP_ENUMERATE)) {
1612
0
            return false;
1613
0
          }
1614
0
        }
1615
0
      }
1616
0
      temp.setObject(*returnObj);
1617
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->authenticatorExtensions_id, temp, JSPROP_ENUMERATE)) {
1618
0
        return false;
1619
0
      }
1620
0
      break;
1621
0
    } while(false);
1622
0
  }
1623
0
1624
0
  do {
1625
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1626
0
    JS::Rooted<JS::Value> temp(cx);
1627
0
    nsString const & currentValue = mChallenge;
1628
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1629
0
      return false;
1630
0
    }
1631
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->challenge_id, temp, JSPROP_ENUMERATE)) {
1632
0
      return false;
1633
0
    }
1634
0
    break;
1635
0
  } while(false);
1636
0
1637
0
  do {
1638
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1639
0
    JS::Rooted<JS::Value> temp(cx);
1640
0
    AuthenticationExtensionsClientInputs const & currentValue = mClientExtensions;
1641
0
    if (!currentValue.ToObjectInternal(cx, &temp)) {
1642
0
      return false;
1643
0
    }
1644
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->clientExtensions_id, temp, JSPROP_ENUMERATE)) {
1645
0
      return false;
1646
0
    }
1647
0
    break;
1648
0
  } while(false);
1649
0
1650
0
  do {
1651
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1652
0
    JS::Rooted<JS::Value> temp(cx);
1653
0
    nsString const & currentValue = mHashAlgorithm;
1654
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1655
0
      return false;
1656
0
    }
1657
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->hashAlgorithm_id, temp, JSPROP_ENUMERATE)) {
1658
0
      return false;
1659
0
    }
1660
0
    break;
1661
0
  } while(false);
1662
0
1663
0
  do {
1664
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1665
0
    JS::Rooted<JS::Value> temp(cx);
1666
0
    nsString const & currentValue = mOrigin;
1667
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1668
0
      return false;
1669
0
    }
1670
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->origin_id, temp, JSPROP_ENUMERATE)) {
1671
0
      return false;
1672
0
    }
1673
0
    break;
1674
0
  } while(false);
1675
0
1676
0
  if (mTokenBindingId.WasPassed()) {
1677
0
    do {
1678
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1679
0
      JS::Rooted<JS::Value> temp(cx);
1680
0
      nsString const & currentValue = mTokenBindingId.InternalValue();
1681
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1682
0
        return false;
1683
0
      }
1684
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->tokenBindingId_id, temp, JSPROP_ENUMERATE)) {
1685
0
        return false;
1686
0
      }
1687
0
      break;
1688
0
    } while(false);
1689
0
  }
1690
0
1691
0
  do {
1692
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1693
0
    JS::Rooted<JS::Value> temp(cx);
1694
0
    nsString const & currentValue = mType;
1695
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1696
0
      return false;
1697
0
    }
1698
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->type_id, temp, JSPROP_ENUMERATE)) {
1699
0
      return false;
1700
0
    }
1701
0
    break;
1702
0
  } while(false);
1703
0
1704
0
  return true;
1705
0
}
1706
1707
bool
1708
CollectedClientData::ToJSON(nsAString& aJSON) const
1709
0
{
1710
0
  AutoJSAPI jsapi;
1711
0
  jsapi.Init();
1712
0
  JSContext *cx = jsapi.cx();
1713
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1714
0
  // because we'll only be creating objects, in ways that have no
1715
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1716
0
  // which likewise guarantees no side-effects for the sorts of
1717
0
  // things we will pass it.
1718
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1719
0
  JS::Rooted<JS::Value> val(cx);
1720
0
  if (!ToObjectInternal(cx, &val)) {
1721
0
    return false;
1722
0
  }
1723
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1724
0
  return StringifyToJSON(cx, obj, aJSON);
1725
0
}
1726
1727
void
1728
CollectedClientData::TraceDictionary(JSTracer* trc)
1729
0
{
1730
0
}
1731
1732
namespace binding_detail {
1733
} // namespace binding_detail
1734
1735
1736
1737
PublicKeyCredentialRequestOptions::PublicKeyCredentialRequestOptions()
1738
  : mExtensions(FastDictionaryInitializer())
1739
0
{
1740
0
  // Safe to pass a null context if we pass a null value
1741
0
  Init(nullptr, JS::NullHandleValue);
1742
0
}
1743
1744
1745
bool
1746
PublicKeyCredentialRequestOptions::InitIds(JSContext* cx, PublicKeyCredentialRequestOptionsAtoms* atomsCache)
1747
0
{
1748
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1749
0
1750
0
  // Initialize these in reverse order so that any failure leaves the first one
1751
0
  // uninitialized.
1752
0
  if (!atomsCache->userVerification_id.init(cx, "userVerification") ||
1753
0
      !atomsCache->timeout_id.init(cx, "timeout") ||
1754
0
      !atomsCache->rpId_id.init(cx, "rpId") ||
1755
0
      !atomsCache->extensions_id.init(cx, "extensions") ||
1756
0
      !atomsCache->challenge_id.init(cx, "challenge") ||
1757
0
      !atomsCache->allowCredentials_id.init(cx, "allowCredentials")) {
1758
0
    return false;
1759
0
  }
1760
0
  return true;
1761
0
}
1762
1763
bool
1764
PublicKeyCredentialRequestOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1765
0
{
1766
0
  // Passing a null JSContext is OK only if we're initing from null,
1767
0
  // Since in that case we will not have to do any property gets
1768
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1769
0
  // checkers by static analysis tools
1770
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1771
0
  PublicKeyCredentialRequestOptionsAtoms* atomsCache = nullptr;
1772
0
  if (cx) {
1773
0
    atomsCache = GetAtomCache<PublicKeyCredentialRequestOptionsAtoms>(cx);
1774
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1775
0
      return false;
1776
0
    }
1777
0
  }
1778
0
1779
0
  if (!IsConvertibleToDictionary(val)) {
1780
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1781
0
  }
1782
0
1783
0
  bool isNull = val.isNullOrUndefined();
1784
0
  // We only need these if !isNull, in which case we have |cx|.
1785
0
  Maybe<JS::Rooted<JSObject *> > object;
1786
0
  Maybe<JS::Rooted<JS::Value> > temp;
1787
0
  if (!isNull) {
1788
0
    MOZ_ASSERT(cx);
1789
0
    object.emplace(cx, &val.toObject());
1790
0
    temp.emplace(cx);
1791
0
  }
1792
0
  if (!isNull) {
1793
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->allowCredentials_id, temp.ptr())) {
1794
0
      return false;
1795
0
    }
1796
0
  }
1797
0
  if (!isNull && !temp->isUndefined()) {
1798
0
    if (temp.ref().isObject()) {
1799
0
      JS::ForOfIterator iter(cx);
1800
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
1801
0
        return false;
1802
0
      }
1803
0
      if (!iter.valueIsIterable()) {
1804
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'allowCredentials' member of PublicKeyCredentialRequestOptions");
1805
0
        return false;
1806
0
      }
1807
0
      Sequence<PublicKeyCredentialDescriptor> &arr = mAllowCredentials;
1808
0
      JS::Rooted<JS::Value> temp(cx);
1809
0
      while (true) {
1810
0
        bool done;
1811
0
        if (!iter.next(&temp, &done)) {
1812
0
          return false;
1813
0
        }
1814
0
        if (done) {
1815
0
          break;
1816
0
        }
1817
0
        PublicKeyCredentialDescriptor* slotPtr = arr.AppendElement(mozilla::fallible);
1818
0
        if (!slotPtr) {
1819
0
          JS_ReportOutOfMemory(cx);
1820
0
          return false;
1821
0
        }
1822
0
        PublicKeyCredentialDescriptor& slot = *slotPtr;
1823
0
        if (!slot.Init(cx, temp,  "Element of 'allowCredentials' member of PublicKeyCredentialRequestOptions", passedToJSImpl)) {
1824
0
          return false;
1825
0
        }
1826
0
      }
1827
0
    } else {
1828
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'allowCredentials' member of PublicKeyCredentialRequestOptions");
1829
0
      return false;
1830
0
    }
1831
0
  } else {
1832
0
    /* Array is already empty; nothing to do */
1833
0
  }
1834
0
  mIsAnyMemberPresent = true;
1835
0
1836
0
  if (!isNull) {
1837
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->challenge_id, temp.ptr())) {
1838
0
      return false;
1839
0
    }
1840
0
  }
1841
0
  if (!isNull && !temp->isUndefined()) {
1842
0
    {
1843
0
      bool done = false, failed = false, tryNext;
1844
0
      if (temp.ref().isObject()) {
1845
0
        done = (failed = !mChallenge.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
1846
0
               (failed = !mChallenge.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
1847
0
1848
0
      }
1849
0
      if (failed) {
1850
0
        return false;
1851
0
      }
1852
0
      if (!done) {
1853
0
        ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'challenge' member of PublicKeyCredentialRequestOptions", "ArrayBufferView, ArrayBuffer");
1854
0
        return false;
1855
0
      }
1856
0
    }
1857
0
    mIsAnyMemberPresent = true;
1858
0
  } else if (cx) {
1859
0
    // Don't error out if we have no cx.  In that
1860
0
    // situation the caller is default-constructing us and we'll
1861
0
    // just assume they know what they're doing.
1862
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
1863
0
                             "'challenge' member of PublicKeyCredentialRequestOptions");
1864
0
  }
1865
0
1866
0
  if (!isNull) {
1867
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->extensions_id, temp.ptr())) {
1868
0
      return false;
1869
0
    }
1870
0
  }
1871
0
  if (!mExtensions.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue,  "'extensions' member of PublicKeyCredentialRequestOptions", passedToJSImpl)) {
1872
0
    return false;
1873
0
  }
1874
0
  mIsAnyMemberPresent = true;
1875
0
1876
0
  if (!isNull) {
1877
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rpId_id, temp.ptr())) {
1878
0
      return false;
1879
0
    }
1880
0
  }
1881
0
  if (!isNull && !temp->isUndefined()) {
1882
0
    mRpId.Construct();
1883
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mRpId.Value()))) {
1884
0
      return false;
1885
0
    }
1886
0
    NormalizeUSVString((mRpId.Value()));
1887
0
    mIsAnyMemberPresent = true;
1888
0
  }
1889
0
1890
0
  if (!isNull) {
1891
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->timeout_id, temp.ptr())) {
1892
0
      return false;
1893
0
    }
1894
0
  }
1895
0
  if (!isNull && !temp->isUndefined()) {
1896
0
    mTimeout.Construct();
1897
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mTimeout.Value()))) {
1898
0
      return false;
1899
0
    }
1900
0
    mIsAnyMemberPresent = true;
1901
0
  }
1902
0
1903
0
  if (!isNull) {
1904
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->userVerification_id, temp.ptr())) {
1905
0
      return false;
1906
0
    }
1907
0
  }
1908
0
  if (!isNull && !temp->isUndefined()) {
1909
0
    {
1910
0
      int index;
1911
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), UserVerificationRequirementValues::strings, "UserVerificationRequirement", "'userVerification' member of PublicKeyCredentialRequestOptions", &index)) {
1912
0
        return false;
1913
0
      }
1914
0
      MOZ_ASSERT(index >= 0);
1915
0
      mUserVerification = static_cast<UserVerificationRequirement>(index);
1916
0
    }
1917
0
  } else {
1918
0
    mUserVerification = UserVerificationRequirement::Preferred;
1919
0
  }
1920
0
  mIsAnyMemberPresent = true;
1921
0
  return true;
1922
0
}
1923
1924
bool
1925
PublicKeyCredentialRequestOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1926
0
{
1927
0
  PublicKeyCredentialRequestOptionsAtoms* atomsCache = GetAtomCache<PublicKeyCredentialRequestOptionsAtoms>(cx);
1928
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1929
0
    return false;
1930
0
  }
1931
0
1932
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1933
0
  if (!obj) {
1934
0
    return false;
1935
0
  }
1936
0
  rval.set(JS::ObjectValue(*obj));
1937
0
1938
0
  do {
1939
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1940
0
    JS::Rooted<JS::Value> temp(cx);
1941
0
    Sequence<PublicKeyCredentialDescriptor> const & currentValue = mAllowCredentials;
1942
0
1943
0
    uint32_t length = currentValue.Length();
1944
0
    JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
1945
0
    if (!returnArray) {
1946
0
      return false;
1947
0
    }
1948
0
    // Scope for 'tmp'
1949
0
    {
1950
0
      JS::Rooted<JS::Value> tmp(cx);
1951
0
      for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
1952
0
        // Control block to let us common up the JS_DefineElement calls when there
1953
0
        // are different ways to succeed at wrapping the object.
1954
0
        do {
1955
0
          if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
1956
0
            return false;
1957
0
          }
1958
0
          break;
1959
0
        } while (false);
1960
0
        if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
1961
0
                              JSPROP_ENUMERATE)) {
1962
0
          return false;
1963
0
        }
1964
0
      }
1965
0
    }
1966
0
    temp.setObject(*returnArray);
1967
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->allowCredentials_id, temp, JSPROP_ENUMERATE)) {
1968
0
      return false;
1969
0
    }
1970
0
    break;
1971
0
  } while(false);
1972
0
1973
0
  do {
1974
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1975
0
    JS::Rooted<JS::Value> temp(cx);
1976
0
    OwningArrayBufferViewOrArrayBuffer const & currentValue = mChallenge;
1977
0
    if (!currentValue.ToJSVal(cx, obj, &temp)) {
1978
0
      return false;
1979
0
    }
1980
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->challenge_id, temp, JSPROP_ENUMERATE)) {
1981
0
      return false;
1982
0
    }
1983
0
    break;
1984
0
  } while(false);
1985
0
1986
0
  do {
1987
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1988
0
    JS::Rooted<JS::Value> temp(cx);
1989
0
    AuthenticationExtensionsClientInputs const & currentValue = mExtensions;
1990
0
    if (!currentValue.ToObjectInternal(cx, &temp)) {
1991
0
      return false;
1992
0
    }
1993
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->extensions_id, temp, JSPROP_ENUMERATE)) {
1994
0
      return false;
1995
0
    }
1996
0
    break;
1997
0
  } while(false);
1998
0
1999
0
  if (mRpId.WasPassed()) {
2000
0
    do {
2001
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2002
0
      JS::Rooted<JS::Value> temp(cx);
2003
0
      nsString const & currentValue = mRpId.InternalValue();
2004
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
2005
0
        return false;
2006
0
      }
2007
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->rpId_id, temp, JSPROP_ENUMERATE)) {
2008
0
        return false;
2009
0
      }
2010
0
      break;
2011
0
    } while(false);
2012
0
  }
2013
0
2014
0
  if (mTimeout.WasPassed()) {
2015
0
    do {
2016
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2017
0
      JS::Rooted<JS::Value> temp(cx);
2018
0
      uint32_t const & currentValue = mTimeout.InternalValue();
2019
0
      temp.setNumber(currentValue);
2020
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->timeout_id, temp, JSPROP_ENUMERATE)) {
2021
0
        return false;
2022
0
      }
2023
0
      break;
2024
0
    } while(false);
2025
0
  }
2026
0
2027
0
  do {
2028
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2029
0
    JS::Rooted<JS::Value> temp(cx);
2030
0
    UserVerificationRequirement const & currentValue = mUserVerification;
2031
0
    if (!ToJSValue(cx, currentValue, &temp)) {
2032
0
      return false;
2033
0
    }
2034
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->userVerification_id, temp, JSPROP_ENUMERATE)) {
2035
0
      return false;
2036
0
    }
2037
0
    break;
2038
0
  } while(false);
2039
0
2040
0
  return true;
2041
0
}
2042
2043
void
2044
PublicKeyCredentialRequestOptions::TraceDictionary(JSTracer* trc)
2045
0
{
2046
0
  DoTraceSequence(trc, mAllowCredentials);
2047
0
2048
0
  mChallenge.TraceUnion(trc);
2049
0
}
2050
2051
namespace binding_detail {
2052
} // namespace binding_detail
2053
2054
2055
2056
PublicKeyCredentialRpEntity::PublicKeyCredentialRpEntity()
2057
  : PublicKeyCredentialEntity(FastDictionaryInitializer())
2058
0
{
2059
0
  // Safe to pass a null context if we pass a null value
2060
0
  Init(nullptr, JS::NullHandleValue);
2061
0
}
2062
2063
2064
2065
bool
2066
PublicKeyCredentialRpEntity::InitIds(JSContext* cx, PublicKeyCredentialRpEntityAtoms* atomsCache)
2067
0
{
2068
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2069
0
2070
0
  // Initialize these in reverse order so that any failure leaves the first one
2071
0
  // uninitialized.
2072
0
  if (!atomsCache->id_id.init(cx, "id")) {
2073
0
    return false;
2074
0
  }
2075
0
  return true;
2076
0
}
2077
2078
bool
2079
PublicKeyCredentialRpEntity::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2080
0
{
2081
0
  // Passing a null JSContext is OK only if we're initing from null,
2082
0
  // Since in that case we will not have to do any property gets
2083
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2084
0
  // checkers by static analysis tools
2085
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2086
0
  PublicKeyCredentialRpEntityAtoms* atomsCache = nullptr;
2087
0
  if (cx) {
2088
0
    atomsCache = GetAtomCache<PublicKeyCredentialRpEntityAtoms>(cx);
2089
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2090
0
      return false;
2091
0
    }
2092
0
  }
2093
0
2094
0
  // Per spec, we init the parent's members first
2095
0
  if (!PublicKeyCredentialEntity::Init(cx, val)) {
2096
0
    return false;
2097
0
  }
2098
0
2099
0
  bool isNull = val.isNullOrUndefined();
2100
0
  // We only need these if !isNull, in which case we have |cx|.
2101
0
  Maybe<JS::Rooted<JSObject *> > object;
2102
0
  Maybe<JS::Rooted<JS::Value> > temp;
2103
0
  if (!isNull) {
2104
0
    MOZ_ASSERT(cx);
2105
0
    object.emplace(cx, &val.toObject());
2106
0
    temp.emplace(cx);
2107
0
  }
2108
0
  if (!isNull) {
2109
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->id_id, temp.ptr())) {
2110
0
      return false;
2111
0
    }
2112
0
  }
2113
0
  if (!isNull && !temp->isUndefined()) {
2114
0
    mId.Construct();
2115
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mId.Value()))) {
2116
0
      return false;
2117
0
    }
2118
0
    mIsAnyMemberPresent = true;
2119
0
  }
2120
0
  return true;
2121
0
}
2122
2123
bool
2124
PublicKeyCredentialRpEntity::Init(const nsAString& aJSON)
2125
0
{
2126
0
  AutoJSAPI jsapi;
2127
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
2128
0
  if (!cleanGlobal) {
2129
0
    return false;
2130
0
  }
2131
0
  if (!jsapi.Init(cleanGlobal)) {
2132
0
    return false;
2133
0
  }
2134
0
  JSContext* cx = jsapi.cx();
2135
0
  JS::Rooted<JS::Value> json(cx);
2136
0
  bool ok = ParseJSON(cx, aJSON, &json);
2137
0
  NS_ENSURE_TRUE(ok, false);
2138
0
  return Init(cx, json);
2139
0
}
2140
2141
bool
2142
PublicKeyCredentialRpEntity::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2143
0
{
2144
0
  PublicKeyCredentialRpEntityAtoms* atomsCache = GetAtomCache<PublicKeyCredentialRpEntityAtoms>(cx);
2145
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2146
0
    return false;
2147
0
  }
2148
0
2149
0
  // Per spec, we define the parent's members first
2150
0
  if (!PublicKeyCredentialEntity::ToObjectInternal(cx, rval)) {
2151
0
    return false;
2152
0
  }
2153
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
2154
0
2155
0
  if (mId.WasPassed()) {
2156
0
    do {
2157
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2158
0
      JS::Rooted<JS::Value> temp(cx);
2159
0
      nsString const & currentValue = mId.InternalValue();
2160
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
2161
0
        return false;
2162
0
      }
2163
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->id_id, temp, JSPROP_ENUMERATE)) {
2164
0
        return false;
2165
0
      }
2166
0
      break;
2167
0
    } while(false);
2168
0
  }
2169
0
2170
0
  return true;
2171
0
}
2172
2173
bool
2174
PublicKeyCredentialRpEntity::ToJSON(nsAString& aJSON) const
2175
0
{
2176
0
  AutoJSAPI jsapi;
2177
0
  jsapi.Init();
2178
0
  JSContext *cx = jsapi.cx();
2179
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
2180
0
  // because we'll only be creating objects, in ways that have no
2181
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
2182
0
  // which likewise guarantees no side-effects for the sorts of
2183
0
  // things we will pass it.
2184
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
2185
0
  JS::Rooted<JS::Value> val(cx);
2186
0
  if (!ToObjectInternal(cx, &val)) {
2187
0
    return false;
2188
0
  }
2189
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
2190
0
  return StringifyToJSON(cx, obj, aJSON);
2191
0
}
2192
2193
void
2194
PublicKeyCredentialRpEntity::TraceDictionary(JSTracer* trc)
2195
0
{
2196
0
  PublicKeyCredentialEntity::TraceDictionary(trc);
2197
0
}
2198
2199
PublicKeyCredentialRpEntity&
2200
PublicKeyCredentialRpEntity::operator=(const PublicKeyCredentialRpEntity& aOther)
2201
0
{
2202
0
  PublicKeyCredentialEntity::operator=(aOther);
2203
0
  mId.Reset();
2204
0
  if (aOther.mId.WasPassed()) {
2205
0
    mId.Construct(aOther.mId.Value());
2206
0
  }
2207
0
  return *this;
2208
0
}
2209
2210
namespace binding_detail {
2211
} // namespace binding_detail
2212
2213
2214
2215
PublicKeyCredentialUserEntity::PublicKeyCredentialUserEntity()
2216
  : PublicKeyCredentialEntity(FastDictionaryInitializer())
2217
0
{
2218
0
  // Safe to pass a null context if we pass a null value
2219
0
  Init(nullptr, JS::NullHandleValue);
2220
0
}
2221
2222
2223
bool
2224
PublicKeyCredentialUserEntity::InitIds(JSContext* cx, PublicKeyCredentialUserEntityAtoms* atomsCache)
2225
0
{
2226
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2227
0
2228
0
  // Initialize these in reverse order so that any failure leaves the first one
2229
0
  // uninitialized.
2230
0
  if (!atomsCache->id_id.init(cx, "id") ||
2231
0
      !atomsCache->displayName_id.init(cx, "displayName")) {
2232
0
    return false;
2233
0
  }
2234
0
  return true;
2235
0
}
2236
2237
bool
2238
PublicKeyCredentialUserEntity::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2239
0
{
2240
0
  // Passing a null JSContext is OK only if we're initing from null,
2241
0
  // Since in that case we will not have to do any property gets
2242
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2243
0
  // checkers by static analysis tools
2244
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2245
0
  PublicKeyCredentialUserEntityAtoms* atomsCache = nullptr;
2246
0
  if (cx) {
2247
0
    atomsCache = GetAtomCache<PublicKeyCredentialUserEntityAtoms>(cx);
2248
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2249
0
      return false;
2250
0
    }
2251
0
  }
2252
0
2253
0
  // Per spec, we init the parent's members first
2254
0
  if (!PublicKeyCredentialEntity::Init(cx, val)) {
2255
0
    return false;
2256
0
  }
2257
0
2258
0
  bool isNull = val.isNullOrUndefined();
2259
0
  // We only need these if !isNull, in which case we have |cx|.
2260
0
  Maybe<JS::Rooted<JSObject *> > object;
2261
0
  Maybe<JS::Rooted<JS::Value> > temp;
2262
0
  if (!isNull) {
2263
0
    MOZ_ASSERT(cx);
2264
0
    object.emplace(cx, &val.toObject());
2265
0
    temp.emplace(cx);
2266
0
  }
2267
0
  if (!isNull) {
2268
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->displayName_id, temp.ptr())) {
2269
0
      return false;
2270
0
    }
2271
0
  }
2272
0
  if (!isNull && !temp->isUndefined()) {
2273
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mDisplayName)) {
2274
0
      return false;
2275
0
    }
2276
0
    mIsAnyMemberPresent = true;
2277
0
  } else if (cx) {
2278
0
    // Don't error out if we have no cx.  In that
2279
0
    // situation the caller is default-constructing us and we'll
2280
0
    // just assume they know what they're doing.
2281
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
2282
0
                             "'displayName' member of PublicKeyCredentialUserEntity");
2283
0
  }
2284
0
2285
0
  if (!isNull) {
2286
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->id_id, temp.ptr())) {
2287
0
      return false;
2288
0
    }
2289
0
  }
2290
0
  if (!isNull && !temp->isUndefined()) {
2291
0
    {
2292
0
      bool done = false, failed = false, tryNext;
2293
0
      if (temp.ref().isObject()) {
2294
0
        done = (failed = !mId.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
2295
0
               (failed = !mId.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
2296
0
2297
0
      }
2298
0
      if (failed) {
2299
0
        return false;
2300
0
      }
2301
0
      if (!done) {
2302
0
        ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'id' member of PublicKeyCredentialUserEntity", "ArrayBufferView, ArrayBuffer");
2303
0
        return false;
2304
0
      }
2305
0
    }
2306
0
    mIsAnyMemberPresent = true;
2307
0
  } else if (cx) {
2308
0
    // Don't error out if we have no cx.  In that
2309
0
    // situation the caller is default-constructing us and we'll
2310
0
    // just assume they know what they're doing.
2311
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
2312
0
                             "'id' member of PublicKeyCredentialUserEntity");
2313
0
  }
2314
0
  return true;
2315
0
}
2316
2317
bool
2318
PublicKeyCredentialUserEntity::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2319
0
{
2320
0
  PublicKeyCredentialUserEntityAtoms* atomsCache = GetAtomCache<PublicKeyCredentialUserEntityAtoms>(cx);
2321
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2322
0
    return false;
2323
0
  }
2324
0
2325
0
  // Per spec, we define the parent's members first
2326
0
  if (!PublicKeyCredentialEntity::ToObjectInternal(cx, rval)) {
2327
0
    return false;
2328
0
  }
2329
0
  JS::Rooted<JSObject*> obj(cx, &rval.toObject());
2330
0
2331
0
  do {
2332
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2333
0
    JS::Rooted<JS::Value> temp(cx);
2334
0
    nsString const & currentValue = mDisplayName;
2335
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
2336
0
      return false;
2337
0
    }
2338
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->displayName_id, temp, JSPROP_ENUMERATE)) {
2339
0
      return false;
2340
0
    }
2341
0
    break;
2342
0
  } while(false);
2343
0
2344
0
  do {
2345
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2346
0
    JS::Rooted<JS::Value> temp(cx);
2347
0
    OwningArrayBufferViewOrArrayBuffer const & currentValue = mId;
2348
0
    if (!currentValue.ToJSVal(cx, obj, &temp)) {
2349
0
      return false;
2350
0
    }
2351
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->id_id, temp, JSPROP_ENUMERATE)) {
2352
0
      return false;
2353
0
    }
2354
0
    break;
2355
0
  } while(false);
2356
0
2357
0
  return true;
2358
0
}
2359
2360
void
2361
PublicKeyCredentialUserEntity::TraceDictionary(JSTracer* trc)
2362
0
{
2363
0
  PublicKeyCredentialEntity::TraceDictionary(trc);
2364
0
  mId.TraceUnion(trc);
2365
0
}
2366
2367
namespace binding_detail {
2368
} // namespace binding_detail
2369
2370
2371
2372
PublicKeyCredentialCreationOptions::PublicKeyCredentialCreationOptions()
2373
  : mAuthenticatorSelection(FastDictionaryInitializer()),
2374
    mExtensions(FastDictionaryInitializer()),
2375
    mRp(FastDictionaryInitializer()),
2376
    mUser(FastDictionaryInitializer())
2377
0
{
2378
0
  // Safe to pass a null context if we pass a null value
2379
0
  Init(nullptr, JS::NullHandleValue);
2380
0
}
2381
2382
2383
bool
2384
PublicKeyCredentialCreationOptions::InitIds(JSContext* cx, PublicKeyCredentialCreationOptionsAtoms* atomsCache)
2385
0
{
2386
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2387
0
2388
0
  // Initialize these in reverse order so that any failure leaves the first one
2389
0
  // uninitialized.
2390
0
  if (!atomsCache->user_id.init(cx, "user") ||
2391
0
      !atomsCache->timeout_id.init(cx, "timeout") ||
2392
0
      !atomsCache->rp_id.init(cx, "rp") ||
2393
0
      !atomsCache->pubKeyCredParams_id.init(cx, "pubKeyCredParams") ||
2394
0
      !atomsCache->extensions_id.init(cx, "extensions") ||
2395
0
      !atomsCache->excludeCredentials_id.init(cx, "excludeCredentials") ||
2396
0
      !atomsCache->challenge_id.init(cx, "challenge") ||
2397
0
      !atomsCache->authenticatorSelection_id.init(cx, "authenticatorSelection") ||
2398
0
      !atomsCache->attestation_id.init(cx, "attestation")) {
2399
0
    return false;
2400
0
  }
2401
0
  return true;
2402
0
}
2403
2404
bool
2405
PublicKeyCredentialCreationOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2406
0
{
2407
0
  // Passing a null JSContext is OK only if we're initing from null,
2408
0
  // Since in that case we will not have to do any property gets
2409
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2410
0
  // checkers by static analysis tools
2411
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2412
0
  PublicKeyCredentialCreationOptionsAtoms* atomsCache = nullptr;
2413
0
  if (cx) {
2414
0
    atomsCache = GetAtomCache<PublicKeyCredentialCreationOptionsAtoms>(cx);
2415
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2416
0
      return false;
2417
0
    }
2418
0
  }
2419
0
2420
0
  if (!IsConvertibleToDictionary(val)) {
2421
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
2422
0
  }
2423
0
2424
0
  bool isNull = val.isNullOrUndefined();
2425
0
  // We only need these if !isNull, in which case we have |cx|.
2426
0
  Maybe<JS::Rooted<JSObject *> > object;
2427
0
  Maybe<JS::Rooted<JS::Value> > temp;
2428
0
  if (!isNull) {
2429
0
    MOZ_ASSERT(cx);
2430
0
    object.emplace(cx, &val.toObject());
2431
0
    temp.emplace(cx);
2432
0
  }
2433
0
  if (!isNull) {
2434
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->attestation_id, temp.ptr())) {
2435
0
      return false;
2436
0
    }
2437
0
  }
2438
0
  if (!isNull && !temp->isUndefined()) {
2439
0
    {
2440
0
      int index;
2441
0
      if (!FindEnumStringIndex<true>(cx, temp.ref(), AttestationConveyancePreferenceValues::strings, "AttestationConveyancePreference", "'attestation' member of PublicKeyCredentialCreationOptions", &index)) {
2442
0
        return false;
2443
0
      }
2444
0
      MOZ_ASSERT(index >= 0);
2445
0
      mAttestation = static_cast<AttestationConveyancePreference>(index);
2446
0
    }
2447
0
  } else {
2448
0
    mAttestation = AttestationConveyancePreference::None;
2449
0
  }
2450
0
  mIsAnyMemberPresent = true;
2451
0
2452
0
  if (!isNull) {
2453
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->authenticatorSelection_id, temp.ptr())) {
2454
0
      return false;
2455
0
    }
2456
0
  }
2457
0
  if (!mAuthenticatorSelection.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue,  "'authenticatorSelection' member of PublicKeyCredentialCreationOptions", passedToJSImpl)) {
2458
0
    return false;
2459
0
  }
2460
0
  mIsAnyMemberPresent = true;
2461
0
2462
0
  if (!isNull) {
2463
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->challenge_id, temp.ptr())) {
2464
0
      return false;
2465
0
    }
2466
0
  }
2467
0
  if (!isNull && !temp->isUndefined()) {
2468
0
    {
2469
0
      bool done = false, failed = false, tryNext;
2470
0
      if (temp.ref().isObject()) {
2471
0
        done = (failed = !mChallenge.TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
2472
0
               (failed = !mChallenge.TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
2473
0
2474
0
      }
2475
0
      if (failed) {
2476
0
        return false;
2477
0
      }
2478
0
      if (!done) {
2479
0
        ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'challenge' member of PublicKeyCredentialCreationOptions", "ArrayBufferView, ArrayBuffer");
2480
0
        return false;
2481
0
      }
2482
0
    }
2483
0
    mIsAnyMemberPresent = true;
2484
0
  } else if (cx) {
2485
0
    // Don't error out if we have no cx.  In that
2486
0
    // situation the caller is default-constructing us and we'll
2487
0
    // just assume they know what they're doing.
2488
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
2489
0
                             "'challenge' member of PublicKeyCredentialCreationOptions");
2490
0
  }
2491
0
2492
0
  if (!isNull) {
2493
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->excludeCredentials_id, temp.ptr())) {
2494
0
      return false;
2495
0
    }
2496
0
  }
2497
0
  if (!isNull && !temp->isUndefined()) {
2498
0
    if (temp.ref().isObject()) {
2499
0
      JS::ForOfIterator iter(cx);
2500
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
2501
0
        return false;
2502
0
      }
2503
0
      if (!iter.valueIsIterable()) {
2504
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'excludeCredentials' member of PublicKeyCredentialCreationOptions");
2505
0
        return false;
2506
0
      }
2507
0
      Sequence<PublicKeyCredentialDescriptor> &arr = mExcludeCredentials;
2508
0
      JS::Rooted<JS::Value> temp(cx);
2509
0
      while (true) {
2510
0
        bool done;
2511
0
        if (!iter.next(&temp, &done)) {
2512
0
          return false;
2513
0
        }
2514
0
        if (done) {
2515
0
          break;
2516
0
        }
2517
0
        PublicKeyCredentialDescriptor* slotPtr = arr.AppendElement(mozilla::fallible);
2518
0
        if (!slotPtr) {
2519
0
          JS_ReportOutOfMemory(cx);
2520
0
          return false;
2521
0
        }
2522
0
        PublicKeyCredentialDescriptor& slot = *slotPtr;
2523
0
        if (!slot.Init(cx, temp,  "Element of 'excludeCredentials' member of PublicKeyCredentialCreationOptions", passedToJSImpl)) {
2524
0
          return false;
2525
0
        }
2526
0
      }
2527
0
    } else {
2528
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'excludeCredentials' member of PublicKeyCredentialCreationOptions");
2529
0
      return false;
2530
0
    }
2531
0
  } else {
2532
0
    /* Array is already empty; nothing to do */
2533
0
  }
2534
0
  mIsAnyMemberPresent = true;
2535
0
2536
0
  if (!isNull) {
2537
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->extensions_id, temp.ptr())) {
2538
0
      return false;
2539
0
    }
2540
0
  }
2541
0
  if (!mExtensions.Init(cx, (!isNull && !temp->isUndefined()) ? temp.ref() : JS::NullHandleValue,  "'extensions' member of PublicKeyCredentialCreationOptions", passedToJSImpl)) {
2542
0
    return false;
2543
0
  }
2544
0
  mIsAnyMemberPresent = true;
2545
0
2546
0
  if (!isNull) {
2547
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->pubKeyCredParams_id, temp.ptr())) {
2548
0
      return false;
2549
0
    }
2550
0
  }
2551
0
  if (!isNull && !temp->isUndefined()) {
2552
0
    if (temp.ref().isObject()) {
2553
0
      JS::ForOfIterator iter(cx);
2554
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
2555
0
        return false;
2556
0
      }
2557
0
      if (!iter.valueIsIterable()) {
2558
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'pubKeyCredParams' member of PublicKeyCredentialCreationOptions");
2559
0
        return false;
2560
0
      }
2561
0
      Sequence<PublicKeyCredentialParameters> &arr = mPubKeyCredParams;
2562
0
      JS::Rooted<JS::Value> temp(cx);
2563
0
      while (true) {
2564
0
        bool done;
2565
0
        if (!iter.next(&temp, &done)) {
2566
0
          return false;
2567
0
        }
2568
0
        if (done) {
2569
0
          break;
2570
0
        }
2571
0
        PublicKeyCredentialParameters* slotPtr = arr.AppendElement(mozilla::fallible);
2572
0
        if (!slotPtr) {
2573
0
          JS_ReportOutOfMemory(cx);
2574
0
          return false;
2575
0
        }
2576
0
        PublicKeyCredentialParameters& slot = *slotPtr;
2577
0
        if (!slot.Init(cx, temp,  "Element of 'pubKeyCredParams' member of PublicKeyCredentialCreationOptions", passedToJSImpl)) {
2578
0
          return false;
2579
0
        }
2580
0
      }
2581
0
    } else {
2582
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'pubKeyCredParams' member of PublicKeyCredentialCreationOptions");
2583
0
      return false;
2584
0
    }
2585
0
    mIsAnyMemberPresent = true;
2586
0
  } else if (cx) {
2587
0
    // Don't error out if we have no cx.  In that
2588
0
    // situation the caller is default-constructing us and we'll
2589
0
    // just assume they know what they're doing.
2590
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
2591
0
                             "'pubKeyCredParams' member of PublicKeyCredentialCreationOptions");
2592
0
  }
2593
0
2594
0
  if (!isNull) {
2595
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rp_id, temp.ptr())) {
2596
0
      return false;
2597
0
    }
2598
0
  }
2599
0
  if (!isNull && !temp->isUndefined()) {
2600
0
    if (!mRp.Init(cx, temp.ref(),  "'rp' member of PublicKeyCredentialCreationOptions", passedToJSImpl)) {
2601
0
      return false;
2602
0
    }
2603
0
    mIsAnyMemberPresent = true;
2604
0
  } else if (cx) {
2605
0
    // Don't error out if we have no cx.  In that
2606
0
    // situation the caller is default-constructing us and we'll
2607
0
    // just assume they know what they're doing.
2608
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
2609
0
                             "'rp' member of PublicKeyCredentialCreationOptions");
2610
0
  }
2611
0
2612
0
  if (!isNull) {
2613
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->timeout_id, temp.ptr())) {
2614
0
      return false;
2615
0
    }
2616
0
  }
2617
0
  if (!isNull && !temp->isUndefined()) {
2618
0
    mTimeout.Construct();
2619
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &(mTimeout.Value()))) {
2620
0
      return false;
2621
0
    }
2622
0
    mIsAnyMemberPresent = true;
2623
0
  }
2624
0
2625
0
  if (!isNull) {
2626
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->user_id, temp.ptr())) {
2627
0
      return false;
2628
0
    }
2629
0
  }
2630
0
  if (!isNull && !temp->isUndefined()) {
2631
0
    if (!mUser.Init(cx, temp.ref(),  "'user' member of PublicKeyCredentialCreationOptions", passedToJSImpl)) {
2632
0
      return false;
2633
0
    }
2634
0
    mIsAnyMemberPresent = true;
2635
0
  } else if (cx) {
2636
0
    // Don't error out if we have no cx.  In that
2637
0
    // situation the caller is default-constructing us and we'll
2638
0
    // just assume they know what they're doing.
2639
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
2640
0
                             "'user' member of PublicKeyCredentialCreationOptions");
2641
0
  }
2642
0
  return true;
2643
0
}
2644
2645
bool
2646
PublicKeyCredentialCreationOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2647
0
{
2648
0
  PublicKeyCredentialCreationOptionsAtoms* atomsCache = GetAtomCache<PublicKeyCredentialCreationOptionsAtoms>(cx);
2649
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2650
0
    return false;
2651
0
  }
2652
0
2653
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
2654
0
  if (!obj) {
2655
0
    return false;
2656
0
  }
2657
0
  rval.set(JS::ObjectValue(*obj));
2658
0
2659
0
  do {
2660
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2661
0
    JS::Rooted<JS::Value> temp(cx);
2662
0
    AttestationConveyancePreference const & currentValue = mAttestation;
2663
0
    if (!ToJSValue(cx, currentValue, &temp)) {
2664
0
      return false;
2665
0
    }
2666
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->attestation_id, temp, JSPROP_ENUMERATE)) {
2667
0
      return false;
2668
0
    }
2669
0
    break;
2670
0
  } while(false);
2671
0
2672
0
  do {
2673
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2674
0
    JS::Rooted<JS::Value> temp(cx);
2675
0
    AuthenticatorSelectionCriteria const & currentValue = mAuthenticatorSelection;
2676
0
    if (!currentValue.ToObjectInternal(cx, &temp)) {
2677
0
      return false;
2678
0
    }
2679
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->authenticatorSelection_id, temp, JSPROP_ENUMERATE)) {
2680
0
      return false;
2681
0
    }
2682
0
    break;
2683
0
  } while(false);
2684
0
2685
0
  do {
2686
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2687
0
    JS::Rooted<JS::Value> temp(cx);
2688
0
    OwningArrayBufferViewOrArrayBuffer const & currentValue = mChallenge;
2689
0
    if (!currentValue.ToJSVal(cx, obj, &temp)) {
2690
0
      return false;
2691
0
    }
2692
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->challenge_id, temp, JSPROP_ENUMERATE)) {
2693
0
      return false;
2694
0
    }
2695
0
    break;
2696
0
  } while(false);
2697
0
2698
0
  do {
2699
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2700
0
    JS::Rooted<JS::Value> temp(cx);
2701
0
    Sequence<PublicKeyCredentialDescriptor> const & currentValue = mExcludeCredentials;
2702
0
2703
0
    uint32_t length = currentValue.Length();
2704
0
    JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2705
0
    if (!returnArray) {
2706
0
      return false;
2707
0
    }
2708
0
    // Scope for 'tmp'
2709
0
    {
2710
0
      JS::Rooted<JS::Value> tmp(cx);
2711
0
      for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2712
0
        // Control block to let us common up the JS_DefineElement calls when there
2713
0
        // are different ways to succeed at wrapping the object.
2714
0
        do {
2715
0
          if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
2716
0
            return false;
2717
0
          }
2718
0
          break;
2719
0
        } while (false);
2720
0
        if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2721
0
                              JSPROP_ENUMERATE)) {
2722
0
          return false;
2723
0
        }
2724
0
      }
2725
0
    }
2726
0
    temp.setObject(*returnArray);
2727
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->excludeCredentials_id, temp, JSPROP_ENUMERATE)) {
2728
0
      return false;
2729
0
    }
2730
0
    break;
2731
0
  } while(false);
2732
0
2733
0
  do {
2734
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2735
0
    JS::Rooted<JS::Value> temp(cx);
2736
0
    AuthenticationExtensionsClientInputs const & currentValue = mExtensions;
2737
0
    if (!currentValue.ToObjectInternal(cx, &temp)) {
2738
0
      return false;
2739
0
    }
2740
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->extensions_id, temp, JSPROP_ENUMERATE)) {
2741
0
      return false;
2742
0
    }
2743
0
    break;
2744
0
  } while(false);
2745
0
2746
0
  do {
2747
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2748
0
    JS::Rooted<JS::Value> temp(cx);
2749
0
    Sequence<PublicKeyCredentialParameters> const & currentValue = mPubKeyCredParams;
2750
0
2751
0
    uint32_t length = currentValue.Length();
2752
0
    JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2753
0
    if (!returnArray) {
2754
0
      return false;
2755
0
    }
2756
0
    // Scope for 'tmp'
2757
0
    {
2758
0
      JS::Rooted<JS::Value> tmp(cx);
2759
0
      for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2760
0
        // Control block to let us common up the JS_DefineElement calls when there
2761
0
        // are different ways to succeed at wrapping the object.
2762
0
        do {
2763
0
          if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
2764
0
            return false;
2765
0
          }
2766
0
          break;
2767
0
        } while (false);
2768
0
        if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2769
0
                              JSPROP_ENUMERATE)) {
2770
0
          return false;
2771
0
        }
2772
0
      }
2773
0
    }
2774
0
    temp.setObject(*returnArray);
2775
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->pubKeyCredParams_id, temp, JSPROP_ENUMERATE)) {
2776
0
      return false;
2777
0
    }
2778
0
    break;
2779
0
  } while(false);
2780
0
2781
0
  do {
2782
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2783
0
    JS::Rooted<JS::Value> temp(cx);
2784
0
    PublicKeyCredentialRpEntity const & currentValue = mRp;
2785
0
    if (!currentValue.ToObjectInternal(cx, &temp)) {
2786
0
      return false;
2787
0
    }
2788
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->rp_id, temp, JSPROP_ENUMERATE)) {
2789
0
      return false;
2790
0
    }
2791
0
    break;
2792
0
  } while(false);
2793
0
2794
0
  if (mTimeout.WasPassed()) {
2795
0
    do {
2796
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2797
0
      JS::Rooted<JS::Value> temp(cx);
2798
0
      uint32_t const & currentValue = mTimeout.InternalValue();
2799
0
      temp.setNumber(currentValue);
2800
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->timeout_id, temp, JSPROP_ENUMERATE)) {
2801
0
        return false;
2802
0
      }
2803
0
      break;
2804
0
    } while(false);
2805
0
  }
2806
0
2807
0
  do {
2808
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2809
0
    JS::Rooted<JS::Value> temp(cx);
2810
0
    PublicKeyCredentialUserEntity const & currentValue = mUser;
2811
0
    if (!currentValue.ToObjectInternal(cx, &temp)) {
2812
0
      return false;
2813
0
    }
2814
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->user_id, temp, JSPROP_ENUMERATE)) {
2815
0
      return false;
2816
0
    }
2817
0
    break;
2818
0
  } while(false);
2819
0
2820
0
  return true;
2821
0
}
2822
2823
void
2824
PublicKeyCredentialCreationOptions::TraceDictionary(JSTracer* trc)
2825
0
{
2826
0
  mChallenge.TraceUnion(trc);
2827
0
2828
0
  DoTraceSequence(trc, mExcludeCredentials);
2829
0
2830
0
  mUser.TraceDictionary(trc);
2831
0
}
2832
2833
namespace binding_detail {
2834
} // namespace binding_detail
2835
2836
2837
namespace AuthenticatorAssertionResponse_Binding {
2838
2839
static_assert(IsRefcounted<NativeType>::value == IsRefcounted<AuthenticatorResponse_Binding::NativeType>::value,
2840
              "Can't inherit from an interface with a different ownership model.");
2841
2842
MOZ_CAN_RUN_SCRIPT static bool
2843
get_authenticatorData(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AuthenticatorAssertionResponse* self, JSJitGetterCallArgs args)
2844
0
{
2845
0
  AUTO_PROFILER_LABEL_FAST("get AuthenticatorAssertionResponse.authenticatorData", DOM, cx);
2846
0
2847
0
  JS::Rooted<JSObject*> result(cx);
2848
0
  self->GetAuthenticatorData(cx, &result);
2849
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
2850
0
  JS::ExposeObjectToActiveJS(result);
2851
0
  args.rval().setObject(*result);
2852
0
  if (!MaybeWrapNonDOMObjectValue(cx, args.rval())) {
2853
0
    return false;
2854
0
  }
2855
0
  return true;
2856
0
}
2857
2858
static const JSJitInfo authenticatorData_getterinfo = {
2859
  { (JSJitGetterOp)get_authenticatorData },
2860
  { prototypes::id::AuthenticatorAssertionResponse },
2861
  { PrototypeTraits<prototypes::id::AuthenticatorAssertionResponse>::Depth },
2862
  JSJitInfo::Getter,
2863
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
2864
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
2865
  false,  /* isInfallible. False in setters. */
2866
  true,  /* isMovable.  Not relevant for setters. */
2867
  true, /* isEliminatable.  Not relevant for setters. */
2868
  false, /* isAlwaysInSlot.  Only relevant for getters. */
2869
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
2870
  false,  /* isTypedMethod.  Only relevant for methods. */
2871
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
2872
};
2873
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
2874
static_assert(0 < 1, "There is no slot for us");
2875
2876
MOZ_CAN_RUN_SCRIPT static bool
2877
get_signature(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AuthenticatorAssertionResponse* self, JSJitGetterCallArgs args)
2878
0
{
2879
0
  AUTO_PROFILER_LABEL_FAST("get AuthenticatorAssertionResponse.signature", DOM, cx);
2880
0
2881
0
  JS::Rooted<JSObject*> result(cx);
2882
0
  self->GetSignature(cx, &result);
2883
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
2884
0
  JS::ExposeObjectToActiveJS(result);
2885
0
  args.rval().setObject(*result);
2886
0
  if (!MaybeWrapNonDOMObjectValue(cx, args.rval())) {
2887
0
    return false;
2888
0
  }
2889
0
  return true;
2890
0
}
2891
2892
static const JSJitInfo signature_getterinfo = {
2893
  { (JSJitGetterOp)get_signature },
2894
  { prototypes::id::AuthenticatorAssertionResponse },
2895
  { PrototypeTraits<prototypes::id::AuthenticatorAssertionResponse>::Depth },
2896
  JSJitInfo::Getter,
2897
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
2898
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
2899
  false,  /* isInfallible. False in setters. */
2900
  true,  /* isMovable.  Not relevant for setters. */
2901
  true, /* isEliminatable.  Not relevant for setters. */
2902
  false, /* isAlwaysInSlot.  Only relevant for getters. */
2903
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
2904
  false,  /* isTypedMethod.  Only relevant for methods. */
2905
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
2906
};
2907
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
2908
static_assert(0 < 1, "There is no slot for us");
2909
2910
MOZ_CAN_RUN_SCRIPT static bool
2911
get_userHandle(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AuthenticatorAssertionResponse* self, JSJitGetterCallArgs args)
2912
0
{
2913
0
  AUTO_PROFILER_LABEL_FAST("get AuthenticatorAssertionResponse.userHandle", DOM, cx);
2914
0
2915
0
  JS::Rooted<JSObject*> result(cx);
2916
0
  self->GetUserHandle(cx, &result);
2917
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
2918
0
  if (result) {
2919
0
                JS::ExposeObjectToActiveJS(result);
2920
0
              }
2921
0
              args.rval().setObjectOrNull(result);
2922
0
  if (!MaybeWrapNonDOMObjectOrNullValue(cx, args.rval())) {
2923
0
    return false;
2924
0
  }
2925
0
  return true;
2926
0
}
2927
2928
static const JSJitInfo userHandle_getterinfo = {
2929
  { (JSJitGetterOp)get_userHandle },
2930
  { prototypes::id::AuthenticatorAssertionResponse },
2931
  { PrototypeTraits<prototypes::id::AuthenticatorAssertionResponse>::Depth },
2932
  JSJitInfo::Getter,
2933
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
2934
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
2935
  false,  /* isInfallible. False in setters. */
2936
  true,  /* isMovable.  Not relevant for setters. */
2937
  true, /* isEliminatable.  Not relevant for setters. */
2938
  false, /* isAlwaysInSlot.  Only relevant for getters. */
2939
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
2940
  false,  /* isTypedMethod.  Only relevant for methods. */
2941
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
2942
};
2943
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
2944
static_assert(0 < 1, "There is no slot for us");
2945
2946
static bool
2947
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
2948
0
{
2949
0
  mozilla::dom::AuthenticatorAssertionResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorAssertionResponse>(obj);
2950
0
  // We don't want to preserve if we don't have a wrapper, and we
2951
0
  // obviously can't preserve if we're not initialized.
2952
0
  if (self && self->GetWrapperPreserveColor()) {
2953
0
    PreserveWrapper(self);
2954
0
  }
2955
0
  return true;
2956
0
}
2957
2958
static void
2959
_finalize(js::FreeOp* fop, JSObject* obj)
2960
0
{
2961
0
  mozilla::dom::AuthenticatorAssertionResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorAssertionResponse>(obj);
2962
0
  if (self) {
2963
0
    ClearWrapper(self, self, obj);
2964
0
    AddForDeferredFinalization<mozilla::dom::AuthenticatorAssertionResponse>(self);
2965
0
  }
2966
0
}
2967
2968
static size_t
2969
_objectMoved(JSObject* obj, JSObject* old)
2970
0
{
2971
0
  mozilla::dom::AuthenticatorAssertionResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorAssertionResponse>(obj);
2972
0
  if (self) {
2973
0
    UpdateWrapper(self, self, obj, old);
2974
0
  }
2975
0
2976
0
  return 0;
2977
0
}
2978
2979
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
2980
#if defined(__clang__)
2981
#pragma clang diagnostic push
2982
#pragma clang diagnostic ignored "-Wmissing-braces"
2983
#endif
2984
static const JSPropertySpec sAttributes_specs[] = {
2985
  { "authenticatorData", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &authenticatorData_getterinfo, nullptr, nullptr },
2986
  { "signature", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &signature_getterinfo, nullptr, nullptr },
2987
  { "userHandle", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &userHandle_getterinfo, nullptr, nullptr },
2988
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
2989
};
2990
#if defined(__clang__)
2991
#pragma clang diagnostic pop
2992
#endif
2993
2994
// Can't be const because the pref-enabled boolean needs to be writable
2995
static PrefableDisablers sAttributes_disablers0 = {
2996
  true, true, 0, nullptr
2997
};
2998
2999
static const Prefable<const JSPropertySpec> sAttributes[] = {
3000
  { &sAttributes_disablers0, &sAttributes_specs[0] },
3001
  { nullptr, nullptr }
3002
};
3003
3004
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
3005
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
3006
static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
3007
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
3008
3009
3010
static uint16_t sNativeProperties_sortedPropertyIndices[3];
3011
static PropertyInfo sNativeProperties_propertyInfos[3];
3012
3013
static const NativePropertiesN<1> sNativeProperties = {
3014
  false, 0,
3015
  false, 0,
3016
  false, 0,
3017
  true,  0 /* sAttributes */,
3018
  false, 0,
3019
  false, 0,
3020
  false, 0,
3021
  -1,
3022
  3,
3023
  sNativeProperties_sortedPropertyIndices,
3024
  {
3025
    { sAttributes, &sNativeProperties_propertyInfos[0] }
3026
  }
3027
};
3028
static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
3029
    "We have a property info count that is oversized");
3030
3031
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
3032
  {
3033
    "Function",
3034
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
3035
    &sBoringInterfaceObjectClassClassOps,
3036
    JS_NULL_CLASS_SPEC,
3037
    JS_NULL_CLASS_EXT,
3038
    &sInterfaceObjectClassObjectOps
3039
  },
3040
  eInterface,
3041
  true,
3042
  prototypes::id::AuthenticatorAssertionResponse,
3043
  PrototypeTraits<prototypes::id::AuthenticatorAssertionResponse>::Depth,
3044
  sNativePropertyHooks,
3045
  "function AuthenticatorAssertionResponse() {\n    [native code]\n}",
3046
  AuthenticatorResponse_Binding::GetConstructorObject
3047
};
3048
3049
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
3050
  {
3051
    "AuthenticatorAssertionResponsePrototype",
3052
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
3053
    JS_NULL_CLASS_OPS,
3054
    JS_NULL_CLASS_SPEC,
3055
    JS_NULL_CLASS_EXT,
3056
    JS_NULL_OBJECT_OPS
3057
  },
3058
  eInterfacePrototype,
3059
  false,
3060
  prototypes::id::AuthenticatorAssertionResponse,
3061
  PrototypeTraits<prototypes::id::AuthenticatorAssertionResponse>::Depth,
3062
  sNativePropertyHooks,
3063
  "[object AuthenticatorAssertionResponsePrototype]",
3064
  AuthenticatorResponse_Binding::GetProtoObject
3065
};
3066
3067
bool
3068
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
3069
0
{
3070
0
  static bool sPrefValue;
3071
0
  static bool sPrefCacheSetUp = false;
3072
0
  if (!sPrefCacheSetUp) {
3073
0
    sPrefCacheSetUp = true;
3074
0
    Preferences::AddBoolVarCache(&sPrefValue, "security.webauth.webauthn");
3075
0
  }
3076
0
3077
0
  return sPrefValue &&
3078
0
         mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx, aObj);
3079
0
}
3080
3081
static const js::ClassOps sClassOps = {
3082
  _addProperty, /* addProperty */
3083
  nullptr,               /* delProperty */
3084
  nullptr,               /* enumerate */
3085
  nullptr, /* newEnumerate */
3086
  nullptr, /* resolve */
3087
  nullptr, /* mayResolve */
3088
  _finalize, /* finalize */
3089
  nullptr, /* call */
3090
  nullptr,               /* hasInstance */
3091
  nullptr,               /* construct */
3092
  nullptr, /* trace */
3093
};
3094
3095
static const js::ClassExtension sClassExtension = {
3096
  nullptr, /* weakmapKeyDelegateOp */
3097
  _objectMoved /* objectMovedOp */
3098
};
3099
3100
static const DOMJSClass sClass = {
3101
  { "AuthenticatorAssertionResponse",
3102
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
3103
    &sClassOps,
3104
    JS_NULL_CLASS_SPEC,
3105
    &sClassExtension,
3106
    JS_NULL_OBJECT_OPS
3107
  },
3108
  { prototypes::id::AuthenticatorResponse, prototypes::id::AuthenticatorAssertionResponse, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
3109
  IsBaseOf<nsISupports, mozilla::dom::AuthenticatorAssertionResponse >::value,
3110
  sNativePropertyHooks,
3111
  FindAssociatedGlobalForNative<mozilla::dom::AuthenticatorAssertionResponse>::Get,
3112
  GetProtoObjectHandle,
3113
  GetCCParticipant<mozilla::dom::AuthenticatorAssertionResponse>::Get()
3114
};
3115
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
3116
              "Must have the right minimal number of reserved slots.");
3117
static_assert(1 >= 1,
3118
              "Must have enough reserved slots.");
3119
3120
const JSClass*
3121
GetJSClass()
3122
0
{
3123
0
  return sClass.ToJSClass();
3124
0
}
3125
3126
bool
3127
Wrap(JSContext* aCx, mozilla::dom::AuthenticatorAssertionResponse* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
3128
0
{
3129
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::AuthenticatorAssertionResponse>::value,
3130
0
                "Shouldn't have wrappercached things that are not refcounted.");
3131
0
  MOZ_ASSERT(static_cast<mozilla::dom::AuthenticatorAssertionResponse*>(aObject) ==
3132
0
             reinterpret_cast<mozilla::dom::AuthenticatorAssertionResponse*>(aObject),
3133
0
             "Multiple inheritance for mozilla::dom::AuthenticatorAssertionResponse is broken.");
3134
0
  MOZ_ASSERT(static_cast<mozilla::dom::AuthenticatorResponse*>(aObject) ==
3135
0
             reinterpret_cast<mozilla::dom::AuthenticatorResponse*>(aObject),
3136
0
             "Multiple inheritance for mozilla::dom::AuthenticatorResponse is broken.");
3137
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
3138
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
3139
0
  MOZ_ASSERT(!aCache->GetWrapper(),
3140
0
             "You should probably not be using Wrap() directly; use "
3141
0
             "GetOrCreateDOMReflector instead");
3142
0
3143
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
3144
0
             "nsISupports must be on our primary inheritance chain");
3145
0
3146
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
3147
0
  if (!global) {
3148
0
    return false;
3149
0
  }
3150
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
3151
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
3152
0
3153
0
  // That might have ended up wrapping us already, due to the wonders
3154
0
  // of XBL.  Check for that, and bail out as needed.
3155
0
  aReflector.set(aCache->GetWrapper());
3156
0
  if (aReflector) {
3157
#ifdef DEBUG
3158
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
3159
#endif // DEBUG
3160
    return true;
3161
0
  }
3162
0
3163
0
  JSAutoRealm ar(aCx, global);
3164
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
3165
0
  if (!canonicalProto) {
3166
0
    return false;
3167
0
  }
3168
0
  JS::Rooted<JSObject*> proto(aCx);
3169
0
  if (aGivenProto) {
3170
0
    proto = aGivenProto;
3171
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
3172
0
    // coming in, we changed compartments to that of "parent" so may need
3173
0
    // to wrap the proto here.
3174
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
3175
0
      if (!JS_WrapObject(aCx, &proto)) {
3176
0
        return false;
3177
0
      }
3178
0
    }
3179
0
  } else {
3180
0
    proto = canonicalProto;
3181
0
  }
3182
0
3183
0
  BindingJSObjectCreator<mozilla::dom::AuthenticatorAssertionResponse> creator(aCx);
3184
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
3185
0
  if (!aReflector) {
3186
0
    return false;
3187
0
  }
3188
0
3189
0
  aCache->SetWrapper(aReflector);
3190
0
  creator.InitializationSucceeded();
3191
0
3192
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
3193
0
             aCache->GetWrapperPreserveColor() == aReflector);
3194
0
  // If proto != canonicalProto, we have to preserve our wrapper;
3195
0
  // otherwise we won't be able to properly recreate it later, since
3196
0
  // we won't know what proto to use.  Note that we don't check
3197
0
  // aGivenProto here, since it's entirely possible (and even
3198
0
  // somewhat common) to have a non-null aGivenProto which is the
3199
0
  // same as canonicalProto.
3200
0
  if (proto != canonicalProto) {
3201
0
    PreserveWrapper(aObject);
3202
0
  }
3203
0
3204
0
  return true;
3205
0
}
3206
3207
const NativePropertyHooks sNativePropertyHooks[] = { {
3208
  nullptr,
3209
  nullptr,
3210
  nullptr,
3211
  { sNativeProperties.Upcast(), nullptr },
3212
  prototypes::id::AuthenticatorAssertionResponse,
3213
  constructors::id::AuthenticatorAssertionResponse,
3214
  AuthenticatorResponse_Binding::sNativePropertyHooks,
3215
  &DefaultXrayExpandoObjectClass
3216
} };
3217
3218
void
3219
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
3220
0
{
3221
0
  JS::Handle<JSObject*> parentProto(AuthenticatorResponse_Binding::GetProtoObjectHandle(aCx));
3222
0
  if (!parentProto) {
3223
0
    return;
3224
0
  }
3225
0
3226
0
  JS::Handle<JSObject*> constructorProto(AuthenticatorResponse_Binding::GetConstructorObjectHandle(aCx));
3227
0
  if (!constructorProto) {
3228
0
    return;
3229
0
  }
3230
0
3231
0
  static bool sIdsInited = false;
3232
0
  if (!sIdsInited && NS_IsMainThread()) {
3233
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
3234
0
      return;
3235
0
    }
3236
0
    sIdsInited = true;
3237
0
  }
3238
0
3239
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::AuthenticatorAssertionResponse);
3240
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::AuthenticatorAssertionResponse);
3241
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
3242
0
                              &sPrototypeClass.mBase, protoCache,
3243
0
                              nullptr,
3244
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
3245
0
                              interfaceCache,
3246
0
                              sNativeProperties.Upcast(),
3247
0
                              nullptr,
3248
0
                              "AuthenticatorAssertionResponse", aDefineOnGlobal,
3249
0
                              nullptr,
3250
0
                              false);
3251
0
}
3252
3253
JSObject*
3254
GetConstructorObject(JSContext* aCx)
3255
0
{
3256
0
  return GetConstructorObjectHandle(aCx);
3257
0
}
3258
3259
} // namespace AuthenticatorAssertionResponse_Binding
3260
3261
3262
3263
namespace AuthenticatorAttestationResponse_Binding {
3264
3265
static_assert(IsRefcounted<NativeType>::value == IsRefcounted<AuthenticatorResponse_Binding::NativeType>::value,
3266
              "Can't inherit from an interface with a different ownership model.");
3267
3268
MOZ_CAN_RUN_SCRIPT static bool
3269
get_attestationObject(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AuthenticatorAttestationResponse* self, JSJitGetterCallArgs args)
3270
0
{
3271
0
  AUTO_PROFILER_LABEL_FAST("get AuthenticatorAttestationResponse.attestationObject", DOM, cx);
3272
0
3273
0
  JS::Rooted<JSObject*> result(cx);
3274
0
  self->GetAttestationObject(cx, &result);
3275
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
3276
0
  JS::ExposeObjectToActiveJS(result);
3277
0
  args.rval().setObject(*result);
3278
0
  if (!MaybeWrapNonDOMObjectValue(cx, args.rval())) {
3279
0
    return false;
3280
0
  }
3281
0
  return true;
3282
0
}
3283
3284
static const JSJitInfo attestationObject_getterinfo = {
3285
  { (JSJitGetterOp)get_attestationObject },
3286
  { prototypes::id::AuthenticatorAttestationResponse },
3287
  { PrototypeTraits<prototypes::id::AuthenticatorAttestationResponse>::Depth },
3288
  JSJitInfo::Getter,
3289
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
3290
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
3291
  false,  /* isInfallible. False in setters. */
3292
  true,  /* isMovable.  Not relevant for setters. */
3293
  true, /* isEliminatable.  Not relevant for setters. */
3294
  false, /* isAlwaysInSlot.  Only relevant for getters. */
3295
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
3296
  false,  /* isTypedMethod.  Only relevant for methods. */
3297
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
3298
};
3299
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3300
static_assert(0 < 1, "There is no slot for us");
3301
3302
static bool
3303
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
3304
0
{
3305
0
  mozilla::dom::AuthenticatorAttestationResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorAttestationResponse>(obj);
3306
0
  // We don't want to preserve if we don't have a wrapper, and we
3307
0
  // obviously can't preserve if we're not initialized.
3308
0
  if (self && self->GetWrapperPreserveColor()) {
3309
0
    PreserveWrapper(self);
3310
0
  }
3311
0
  return true;
3312
0
}
3313
3314
static void
3315
_finalize(js::FreeOp* fop, JSObject* obj)
3316
0
{
3317
0
  mozilla::dom::AuthenticatorAttestationResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorAttestationResponse>(obj);
3318
0
  if (self) {
3319
0
    ClearWrapper(self, self, obj);
3320
0
    AddForDeferredFinalization<mozilla::dom::AuthenticatorAttestationResponse>(self);
3321
0
  }
3322
0
}
3323
3324
static size_t
3325
_objectMoved(JSObject* obj, JSObject* old)
3326
0
{
3327
0
  mozilla::dom::AuthenticatorAttestationResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorAttestationResponse>(obj);
3328
0
  if (self) {
3329
0
    UpdateWrapper(self, self, obj, old);
3330
0
  }
3331
0
3332
0
  return 0;
3333
0
}
3334
3335
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
3336
#if defined(__clang__)
3337
#pragma clang diagnostic push
3338
#pragma clang diagnostic ignored "-Wmissing-braces"
3339
#endif
3340
static const JSPropertySpec sAttributes_specs[] = {
3341
  { "attestationObject", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &attestationObject_getterinfo, nullptr, nullptr },
3342
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
3343
};
3344
#if defined(__clang__)
3345
#pragma clang diagnostic pop
3346
#endif
3347
3348
// Can't be const because the pref-enabled boolean needs to be writable
3349
static PrefableDisablers sAttributes_disablers0 = {
3350
  true, true, 0, nullptr
3351
};
3352
3353
static const Prefable<const JSPropertySpec> sAttributes[] = {
3354
  { &sAttributes_disablers0, &sAttributes_specs[0] },
3355
  { nullptr, nullptr }
3356
};
3357
3358
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
3359
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
3360
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
3361
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
3362
3363
3364
static uint16_t sNativeProperties_sortedPropertyIndices[1];
3365
static PropertyInfo sNativeProperties_propertyInfos[1];
3366
3367
static const NativePropertiesN<1> sNativeProperties = {
3368
  false, 0,
3369
  false, 0,
3370
  false, 0,
3371
  true,  0 /* sAttributes */,
3372
  false, 0,
3373
  false, 0,
3374
  false, 0,
3375
  -1,
3376
  1,
3377
  sNativeProperties_sortedPropertyIndices,
3378
  {
3379
    { sAttributes, &sNativeProperties_propertyInfos[0] }
3380
  }
3381
};
3382
static_assert(1 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
3383
    "We have a property info count that is oversized");
3384
3385
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
3386
  {
3387
    "Function",
3388
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
3389
    &sBoringInterfaceObjectClassClassOps,
3390
    JS_NULL_CLASS_SPEC,
3391
    JS_NULL_CLASS_EXT,
3392
    &sInterfaceObjectClassObjectOps
3393
  },
3394
  eInterface,
3395
  true,
3396
  prototypes::id::AuthenticatorAttestationResponse,
3397
  PrototypeTraits<prototypes::id::AuthenticatorAttestationResponse>::Depth,
3398
  sNativePropertyHooks,
3399
  "function AuthenticatorAttestationResponse() {\n    [native code]\n}",
3400
  AuthenticatorResponse_Binding::GetConstructorObject
3401
};
3402
3403
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
3404
  {
3405
    "AuthenticatorAttestationResponsePrototype",
3406
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
3407
    JS_NULL_CLASS_OPS,
3408
    JS_NULL_CLASS_SPEC,
3409
    JS_NULL_CLASS_EXT,
3410
    JS_NULL_OBJECT_OPS
3411
  },
3412
  eInterfacePrototype,
3413
  false,
3414
  prototypes::id::AuthenticatorAttestationResponse,
3415
  PrototypeTraits<prototypes::id::AuthenticatorAttestationResponse>::Depth,
3416
  sNativePropertyHooks,
3417
  "[object AuthenticatorAttestationResponsePrototype]",
3418
  AuthenticatorResponse_Binding::GetProtoObject
3419
};
3420
3421
bool
3422
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
3423
0
{
3424
0
  static bool sPrefValue;
3425
0
  static bool sPrefCacheSetUp = false;
3426
0
  if (!sPrefCacheSetUp) {
3427
0
    sPrefCacheSetUp = true;
3428
0
    Preferences::AddBoolVarCache(&sPrefValue, "security.webauth.webauthn");
3429
0
  }
3430
0
3431
0
  return sPrefValue &&
3432
0
         mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx, aObj);
3433
0
}
3434
3435
static const js::ClassOps sClassOps = {
3436
  _addProperty, /* addProperty */
3437
  nullptr,               /* delProperty */
3438
  nullptr,               /* enumerate */
3439
  nullptr, /* newEnumerate */
3440
  nullptr, /* resolve */
3441
  nullptr, /* mayResolve */
3442
  _finalize, /* finalize */
3443
  nullptr, /* call */
3444
  nullptr,               /* hasInstance */
3445
  nullptr,               /* construct */
3446
  nullptr, /* trace */
3447
};
3448
3449
static const js::ClassExtension sClassExtension = {
3450
  nullptr, /* weakmapKeyDelegateOp */
3451
  _objectMoved /* objectMovedOp */
3452
};
3453
3454
static const DOMJSClass sClass = {
3455
  { "AuthenticatorAttestationResponse",
3456
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
3457
    &sClassOps,
3458
    JS_NULL_CLASS_SPEC,
3459
    &sClassExtension,
3460
    JS_NULL_OBJECT_OPS
3461
  },
3462
  { prototypes::id::AuthenticatorResponse, prototypes::id::AuthenticatorAttestationResponse, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
3463
  IsBaseOf<nsISupports, mozilla::dom::AuthenticatorAttestationResponse >::value,
3464
  sNativePropertyHooks,
3465
  FindAssociatedGlobalForNative<mozilla::dom::AuthenticatorAttestationResponse>::Get,
3466
  GetProtoObjectHandle,
3467
  GetCCParticipant<mozilla::dom::AuthenticatorAttestationResponse>::Get()
3468
};
3469
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
3470
              "Must have the right minimal number of reserved slots.");
3471
static_assert(1 >= 1,
3472
              "Must have enough reserved slots.");
3473
3474
const JSClass*
3475
GetJSClass()
3476
0
{
3477
0
  return sClass.ToJSClass();
3478
0
}
3479
3480
bool
3481
Wrap(JSContext* aCx, mozilla::dom::AuthenticatorAttestationResponse* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
3482
0
{
3483
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::AuthenticatorAttestationResponse>::value,
3484
0
                "Shouldn't have wrappercached things that are not refcounted.");
3485
0
  MOZ_ASSERT(static_cast<mozilla::dom::AuthenticatorAttestationResponse*>(aObject) ==
3486
0
             reinterpret_cast<mozilla::dom::AuthenticatorAttestationResponse*>(aObject),
3487
0
             "Multiple inheritance for mozilla::dom::AuthenticatorAttestationResponse is broken.");
3488
0
  MOZ_ASSERT(static_cast<mozilla::dom::AuthenticatorResponse*>(aObject) ==
3489
0
             reinterpret_cast<mozilla::dom::AuthenticatorResponse*>(aObject),
3490
0
             "Multiple inheritance for mozilla::dom::AuthenticatorResponse is broken.");
3491
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
3492
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
3493
0
  MOZ_ASSERT(!aCache->GetWrapper(),
3494
0
             "You should probably not be using Wrap() directly; use "
3495
0
             "GetOrCreateDOMReflector instead");
3496
0
3497
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
3498
0
             "nsISupports must be on our primary inheritance chain");
3499
0
3500
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
3501
0
  if (!global) {
3502
0
    return false;
3503
0
  }
3504
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
3505
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
3506
0
3507
0
  // That might have ended up wrapping us already, due to the wonders
3508
0
  // of XBL.  Check for that, and bail out as needed.
3509
0
  aReflector.set(aCache->GetWrapper());
3510
0
  if (aReflector) {
3511
#ifdef DEBUG
3512
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
3513
#endif // DEBUG
3514
    return true;
3515
0
  }
3516
0
3517
0
  JSAutoRealm ar(aCx, global);
3518
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
3519
0
  if (!canonicalProto) {
3520
0
    return false;
3521
0
  }
3522
0
  JS::Rooted<JSObject*> proto(aCx);
3523
0
  if (aGivenProto) {
3524
0
    proto = aGivenProto;
3525
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
3526
0
    // coming in, we changed compartments to that of "parent" so may need
3527
0
    // to wrap the proto here.
3528
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
3529
0
      if (!JS_WrapObject(aCx, &proto)) {
3530
0
        return false;
3531
0
      }
3532
0
    }
3533
0
  } else {
3534
0
    proto = canonicalProto;
3535
0
  }
3536
0
3537
0
  BindingJSObjectCreator<mozilla::dom::AuthenticatorAttestationResponse> creator(aCx);
3538
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
3539
0
  if (!aReflector) {
3540
0
    return false;
3541
0
  }
3542
0
3543
0
  aCache->SetWrapper(aReflector);
3544
0
  creator.InitializationSucceeded();
3545
0
3546
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
3547
0
             aCache->GetWrapperPreserveColor() == aReflector);
3548
0
  // If proto != canonicalProto, we have to preserve our wrapper;
3549
0
  // otherwise we won't be able to properly recreate it later, since
3550
0
  // we won't know what proto to use.  Note that we don't check
3551
0
  // aGivenProto here, since it's entirely possible (and even
3552
0
  // somewhat common) to have a non-null aGivenProto which is the
3553
0
  // same as canonicalProto.
3554
0
  if (proto != canonicalProto) {
3555
0
    PreserveWrapper(aObject);
3556
0
  }
3557
0
3558
0
  return true;
3559
0
}
3560
3561
const NativePropertyHooks sNativePropertyHooks[] = { {
3562
  nullptr,
3563
  nullptr,
3564
  nullptr,
3565
  { sNativeProperties.Upcast(), nullptr },
3566
  prototypes::id::AuthenticatorAttestationResponse,
3567
  constructors::id::AuthenticatorAttestationResponse,
3568
  AuthenticatorResponse_Binding::sNativePropertyHooks,
3569
  &DefaultXrayExpandoObjectClass
3570
} };
3571
3572
void
3573
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
3574
0
{
3575
0
  JS::Handle<JSObject*> parentProto(AuthenticatorResponse_Binding::GetProtoObjectHandle(aCx));
3576
0
  if (!parentProto) {
3577
0
    return;
3578
0
  }
3579
0
3580
0
  JS::Handle<JSObject*> constructorProto(AuthenticatorResponse_Binding::GetConstructorObjectHandle(aCx));
3581
0
  if (!constructorProto) {
3582
0
    return;
3583
0
  }
3584
0
3585
0
  static bool sIdsInited = false;
3586
0
  if (!sIdsInited && NS_IsMainThread()) {
3587
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
3588
0
      return;
3589
0
    }
3590
0
    sIdsInited = true;
3591
0
  }
3592
0
3593
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::AuthenticatorAttestationResponse);
3594
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::AuthenticatorAttestationResponse);
3595
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
3596
0
                              &sPrototypeClass.mBase, protoCache,
3597
0
                              nullptr,
3598
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
3599
0
                              interfaceCache,
3600
0
                              sNativeProperties.Upcast(),
3601
0
                              nullptr,
3602
0
                              "AuthenticatorAttestationResponse", aDefineOnGlobal,
3603
0
                              nullptr,
3604
0
                              false);
3605
0
}
3606
3607
JSObject*
3608
GetConstructorObject(JSContext* aCx)
3609
0
{
3610
0
  return GetConstructorObjectHandle(aCx);
3611
0
}
3612
3613
} // namespace AuthenticatorAttestationResponse_Binding
3614
3615
3616
3617
namespace AuthenticatorResponse_Binding {
3618
3619
MOZ_CAN_RUN_SCRIPT static bool
3620
get_clientDataJSON(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::AuthenticatorResponse* self, JSJitGetterCallArgs args)
3621
0
{
3622
0
  AUTO_PROFILER_LABEL_FAST("get AuthenticatorResponse.clientDataJSON", DOM, cx);
3623
0
3624
0
  JS::Rooted<JSObject*> result(cx);
3625
0
  self->GetClientDataJSON(cx, &result);
3626
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
3627
0
  JS::ExposeObjectToActiveJS(result);
3628
0
  args.rval().setObject(*result);
3629
0
  if (!MaybeWrapNonDOMObjectValue(cx, args.rval())) {
3630
0
    return false;
3631
0
  }
3632
0
  return true;
3633
0
}
3634
3635
static const JSJitInfo clientDataJSON_getterinfo = {
3636
  { (JSJitGetterOp)get_clientDataJSON },
3637
  { prototypes::id::AuthenticatorResponse },
3638
  { PrototypeTraits<prototypes::id::AuthenticatorResponse>::Depth },
3639
  JSJitInfo::Getter,
3640
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
3641
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
3642
  false,  /* isInfallible. False in setters. */
3643
  true,  /* isMovable.  Not relevant for setters. */
3644
  true, /* isEliminatable.  Not relevant for setters. */
3645
  false, /* isAlwaysInSlot.  Only relevant for getters. */
3646
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
3647
  false,  /* isTypedMethod.  Only relevant for methods. */
3648
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
3649
};
3650
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3651
static_assert(0 < 1, "There is no slot for us");
3652
3653
static bool
3654
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
3655
0
{
3656
0
  mozilla::dom::AuthenticatorResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorResponse>(obj);
3657
0
  // We don't want to preserve if we don't have a wrapper, and we
3658
0
  // obviously can't preserve if we're not initialized.
3659
0
  if (self && self->GetWrapperPreserveColor()) {
3660
0
    PreserveWrapper(self);
3661
0
  }
3662
0
  return true;
3663
0
}
3664
3665
static void
3666
_finalize(js::FreeOp* fop, JSObject* obj)
3667
0
{
3668
0
  mozilla::dom::AuthenticatorResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorResponse>(obj);
3669
0
  if (self) {
3670
0
    ClearWrapper(self, self, obj);
3671
0
    AddForDeferredFinalization<mozilla::dom::AuthenticatorResponse>(self);
3672
0
  }
3673
0
}
3674
3675
static size_t
3676
_objectMoved(JSObject* obj, JSObject* old)
3677
0
{
3678
0
  mozilla::dom::AuthenticatorResponse* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AuthenticatorResponse>(obj);
3679
0
  if (self) {
3680
0
    UpdateWrapper(self, self, obj, old);
3681
0
  }
3682
0
3683
0
  return 0;
3684
0
}
3685
3686
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
3687
#if defined(__clang__)
3688
#pragma clang diagnostic push
3689
#pragma clang diagnostic ignored "-Wmissing-braces"
3690
#endif
3691
static const JSPropertySpec sAttributes_specs[] = {
3692
  { "clientDataJSON", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &clientDataJSON_getterinfo, nullptr, nullptr },
3693
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
3694
};
3695
#if defined(__clang__)
3696
#pragma clang diagnostic pop
3697
#endif
3698
3699
// Can't be const because the pref-enabled boolean needs to be writable
3700
static PrefableDisablers sAttributes_disablers0 = {
3701
  true, true, 0, nullptr
3702
};
3703
3704
static const Prefable<const JSPropertySpec> sAttributes[] = {
3705
  { &sAttributes_disablers0, &sAttributes_specs[0] },
3706
  { nullptr, nullptr }
3707
};
3708
3709
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
3710
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
3711
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
3712
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
3713
3714
3715
static uint16_t sNativeProperties_sortedPropertyIndices[1];
3716
static PropertyInfo sNativeProperties_propertyInfos[1];
3717
3718
static const NativePropertiesN<1> sNativeProperties = {
3719
  false, 0,
3720
  false, 0,
3721
  false, 0,
3722
  true,  0 /* sAttributes */,
3723
  false, 0,
3724
  false, 0,
3725
  false, 0,
3726
  -1,
3727
  1,
3728
  sNativeProperties_sortedPropertyIndices,
3729
  {
3730
    { sAttributes, &sNativeProperties_propertyInfos[0] }
3731
  }
3732
};
3733
static_assert(1 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
3734
    "We have a property info count that is oversized");
3735
3736
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
3737
  {
3738
    "Function",
3739
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
3740
    &sBoringInterfaceObjectClassClassOps,
3741
    JS_NULL_CLASS_SPEC,
3742
    JS_NULL_CLASS_EXT,
3743
    &sInterfaceObjectClassObjectOps
3744
  },
3745
  eInterface,
3746
  true,
3747
  prototypes::id::AuthenticatorResponse,
3748
  PrototypeTraits<prototypes::id::AuthenticatorResponse>::Depth,
3749
  sNativePropertyHooks,
3750
  "function AuthenticatorResponse() {\n    [native code]\n}",
3751
  JS::GetRealmFunctionPrototype
3752
};
3753
3754
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
3755
  {
3756
    "AuthenticatorResponsePrototype",
3757
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
3758
    JS_NULL_CLASS_OPS,
3759
    JS_NULL_CLASS_SPEC,
3760
    JS_NULL_CLASS_EXT,
3761
    JS_NULL_OBJECT_OPS
3762
  },
3763
  eInterfacePrototype,
3764
  false,
3765
  prototypes::id::AuthenticatorResponse,
3766
  PrototypeTraits<prototypes::id::AuthenticatorResponse>::Depth,
3767
  sNativePropertyHooks,
3768
  "[object AuthenticatorResponsePrototype]",
3769
  JS::GetRealmObjectPrototype
3770
};
3771
3772
bool
3773
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
3774
0
{
3775
0
  static bool sPrefValue;
3776
0
  static bool sPrefCacheSetUp = false;
3777
0
  if (!sPrefCacheSetUp) {
3778
0
    sPrefCacheSetUp = true;
3779
0
    Preferences::AddBoolVarCache(&sPrefValue, "security.webauth.webauthn");
3780
0
  }
3781
0
3782
0
  return sPrefValue &&
3783
0
         mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx, aObj);
3784
0
}
3785
3786
static const js::ClassOps sClassOps = {
3787
  _addProperty, /* addProperty */
3788
  nullptr,               /* delProperty */
3789
  nullptr,               /* enumerate */
3790
  nullptr, /* newEnumerate */
3791
  nullptr, /* resolve */
3792
  nullptr, /* mayResolve */
3793
  _finalize, /* finalize */
3794
  nullptr, /* call */
3795
  nullptr,               /* hasInstance */
3796
  nullptr,               /* construct */
3797
  nullptr, /* trace */
3798
};
3799
3800
static const js::ClassExtension sClassExtension = {
3801
  nullptr, /* weakmapKeyDelegateOp */
3802
  _objectMoved /* objectMovedOp */
3803
};
3804
3805
static const DOMJSClass sClass = {
3806
  { "AuthenticatorResponse",
3807
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
3808
    &sClassOps,
3809
    JS_NULL_CLASS_SPEC,
3810
    &sClassExtension,
3811
    JS_NULL_OBJECT_OPS
3812
  },
3813
  { prototypes::id::AuthenticatorResponse, 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 },
3814
  IsBaseOf<nsISupports, mozilla::dom::AuthenticatorResponse >::value,
3815
  sNativePropertyHooks,
3816
  FindAssociatedGlobalForNative<mozilla::dom::AuthenticatorResponse>::Get,
3817
  GetProtoObjectHandle,
3818
  GetCCParticipant<mozilla::dom::AuthenticatorResponse>::Get()
3819
};
3820
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
3821
              "Must have the right minimal number of reserved slots.");
3822
static_assert(1 >= 1,
3823
              "Must have enough reserved slots.");
3824
3825
const JSClass*
3826
GetJSClass()
3827
0
{
3828
0
  return sClass.ToJSClass();
3829
0
}
3830
3831
bool
3832
Wrap(JSContext* aCx, mozilla::dom::AuthenticatorResponse* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
3833
0
{
3834
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::AuthenticatorResponse>::value,
3835
0
                "Shouldn't have wrappercached things that are not refcounted.");
3836
0
  MOZ_ASSERT(static_cast<mozilla::dom::AuthenticatorResponse*>(aObject) ==
3837
0
             reinterpret_cast<mozilla::dom::AuthenticatorResponse*>(aObject),
3838
0
             "Multiple inheritance for mozilla::dom::AuthenticatorResponse is broken.");
3839
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
3840
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
3841
0
  MOZ_ASSERT(!aCache->GetWrapper(),
3842
0
             "You should probably not be using Wrap() directly; use "
3843
0
             "GetOrCreateDOMReflector instead");
3844
0
3845
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
3846
0
             "nsISupports must be on our primary inheritance chain");
3847
0
3848
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
3849
0
  if (!global) {
3850
0
    return false;
3851
0
  }
3852
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
3853
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
3854
0
3855
0
  // That might have ended up wrapping us already, due to the wonders
3856
0
  // of XBL.  Check for that, and bail out as needed.
3857
0
  aReflector.set(aCache->GetWrapper());
3858
0
  if (aReflector) {
3859
#ifdef DEBUG
3860
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
3861
#endif // DEBUG
3862
    return true;
3863
0
  }
3864
0
3865
0
  JSAutoRealm ar(aCx, global);
3866
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
3867
0
  if (!canonicalProto) {
3868
0
    return false;
3869
0
  }
3870
0
  JS::Rooted<JSObject*> proto(aCx);
3871
0
  if (aGivenProto) {
3872
0
    proto = aGivenProto;
3873
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
3874
0
    // coming in, we changed compartments to that of "parent" so may need
3875
0
    // to wrap the proto here.
3876
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
3877
0
      if (!JS_WrapObject(aCx, &proto)) {
3878
0
        return false;
3879
0
      }
3880
0
    }
3881
0
  } else {
3882
0
    proto = canonicalProto;
3883
0
  }
3884
0
3885
0
  BindingJSObjectCreator<mozilla::dom::AuthenticatorResponse> creator(aCx);
3886
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
3887
0
  if (!aReflector) {
3888
0
    return false;
3889
0
  }
3890
0
3891
0
  aCache->SetWrapper(aReflector);
3892
0
  creator.InitializationSucceeded();
3893
0
3894
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
3895
0
             aCache->GetWrapperPreserveColor() == aReflector);
3896
0
  // If proto != canonicalProto, we have to preserve our wrapper;
3897
0
  // otherwise we won't be able to properly recreate it later, since
3898
0
  // we won't know what proto to use.  Note that we don't check
3899
0
  // aGivenProto here, since it's entirely possible (and even
3900
0
  // somewhat common) to have a non-null aGivenProto which is the
3901
0
  // same as canonicalProto.
3902
0
  if (proto != canonicalProto) {
3903
0
    PreserveWrapper(aObject);
3904
0
  }
3905
0
3906
0
  return true;
3907
0
}
3908
3909
const NativePropertyHooks sNativePropertyHooks[] = { {
3910
  nullptr,
3911
  nullptr,
3912
  nullptr,
3913
  { sNativeProperties.Upcast(), nullptr },
3914
  prototypes::id::AuthenticatorResponse,
3915
  constructors::id::AuthenticatorResponse,
3916
  nullptr,
3917
  &DefaultXrayExpandoObjectClass
3918
} };
3919
3920
void
3921
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
3922
0
{
3923
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
3924
0
  if (!parentProto) {
3925
0
    return;
3926
0
  }
3927
0
3928
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
3929
0
  if (!constructorProto) {
3930
0
    return;
3931
0
  }
3932
0
3933
0
  static bool sIdsInited = false;
3934
0
  if (!sIdsInited && NS_IsMainThread()) {
3935
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
3936
0
      return;
3937
0
    }
3938
0
    sIdsInited = true;
3939
0
  }
3940
0
3941
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::AuthenticatorResponse);
3942
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::AuthenticatorResponse);
3943
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
3944
0
                              &sPrototypeClass.mBase, protoCache,
3945
0
                              nullptr,
3946
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
3947
0
                              interfaceCache,
3948
0
                              sNativeProperties.Upcast(),
3949
0
                              nullptr,
3950
0
                              "AuthenticatorResponse", aDefineOnGlobal,
3951
0
                              nullptr,
3952
0
                              false);
3953
0
}
3954
3955
JSObject*
3956
GetProtoObject(JSContext* aCx)
3957
0
{
3958
0
  return GetProtoObjectHandle(aCx);
3959
0
}
3960
3961
JSObject*
3962
GetConstructorObject(JSContext* aCx)
3963
0
{
3964
0
  return GetConstructorObjectHandle(aCx);
3965
0
}
3966
3967
} // namespace AuthenticatorResponse_Binding
3968
3969
3970
3971
namespace PublicKeyCredential_Binding {
3972
3973
static_assert(IsRefcounted<NativeType>::value == IsRefcounted<Credential_Binding::NativeType>::value,
3974
              "Can't inherit from an interface with a different ownership model.");
3975
3976
MOZ_CAN_RUN_SCRIPT static bool
3977
get_rawId(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PublicKeyCredential* self, JSJitGetterCallArgs args)
3978
0
{
3979
0
  AUTO_PROFILER_LABEL_FAST("get PublicKeyCredential.rawId", DOM, cx);
3980
0
3981
0
  JS::Rooted<JSObject*> result(cx);
3982
0
  self->GetRawId(cx, &result);
3983
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
3984
0
  JS::ExposeObjectToActiveJS(result);
3985
0
  args.rval().setObject(*result);
3986
0
  if (!MaybeWrapNonDOMObjectValue(cx, args.rval())) {
3987
0
    return false;
3988
0
  }
3989
0
  return true;
3990
0
}
3991
3992
static const JSJitInfo rawId_getterinfo = {
3993
  { (JSJitGetterOp)get_rawId },
3994
  { prototypes::id::PublicKeyCredential },
3995
  { PrototypeTraits<prototypes::id::PublicKeyCredential>::Depth },
3996
  JSJitInfo::Getter,
3997
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
3998
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
3999
  false,  /* isInfallible. False in setters. */
4000
  true,  /* isMovable.  Not relevant for setters. */
4001
  true, /* isEliminatable.  Not relevant for setters. */
4002
  false, /* isAlwaysInSlot.  Only relevant for getters. */
4003
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
4004
  false,  /* isTypedMethod.  Only relevant for methods. */
4005
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
4006
};
4007
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4008
static_assert(0 < 1, "There is no slot for us");
4009
4010
MOZ_CAN_RUN_SCRIPT static bool
4011
get_response(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PublicKeyCredential* self, JSJitGetterCallArgs args)
4012
0
{
4013
0
  AUTO_PROFILER_LABEL_FAST("get PublicKeyCredential.response", DOM, cx);
4014
0
4015
0
  auto result(StrongOrRawPtr<mozilla::dom::AuthenticatorResponse>(self->Response()));
4016
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
4017
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
4018
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
4019
0
    return false;
4020
0
  }
4021
0
  return true;
4022
0
}
4023
4024
static const JSJitInfo response_getterinfo = {
4025
  { (JSJitGetterOp)get_response },
4026
  { prototypes::id::PublicKeyCredential },
4027
  { PrototypeTraits<prototypes::id::PublicKeyCredential>::Depth },
4028
  JSJitInfo::Getter,
4029
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
4030
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
4031
  false,  /* isInfallible. False in setters. */
4032
  true,  /* isMovable.  Not relevant for setters. */
4033
  true, /* isEliminatable.  Not relevant for setters. */
4034
  false, /* isAlwaysInSlot.  Only relevant for getters. */
4035
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
4036
  false,  /* isTypedMethod.  Only relevant for methods. */
4037
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
4038
};
4039
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4040
static_assert(0 < 1, "There is no slot for us");
4041
4042
MOZ_CAN_RUN_SCRIPT static bool
4043
getClientExtensionResults(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PublicKeyCredential* self, const JSJitMethodCallArgs& args)
4044
0
{
4045
0
  AUTO_PROFILER_LABEL_FAST("PublicKeyCredential.getClientExtensionResults", DOM, cx);
4046
0
4047
0
  AuthenticationExtensionsClientOutputs result;
4048
0
  self->GetClientExtensionResults(result);
4049
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
4050
0
  if (!result.ToObjectInternal(cx, args.rval())) {
4051
0
    return false;
4052
0
  }
4053
0
  return true;
4054
0
}
4055
4056
static const JSJitInfo getClientExtensionResults_methodinfo = {
4057
  { (JSJitGetterOp)getClientExtensionResults },
4058
  { prototypes::id::PublicKeyCredential },
4059
  { PrototypeTraits<prototypes::id::PublicKeyCredential>::Depth },
4060
  JSJitInfo::Method,
4061
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
4062
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
4063
  false,  /* isInfallible. False in setters. */
4064
  false,  /* isMovable.  Not relevant for setters. */
4065
  false, /* isEliminatable.  Not relevant for setters. */
4066
  false, /* isAlwaysInSlot.  Only relevant for getters. */
4067
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
4068
  false,  /* isTypedMethod.  Only relevant for methods. */
4069
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
4070
};
4071
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4072
static_assert(0 < 1, "There is no slot for us");
4073
4074
static bool
4075
isUserVerifyingPlatformAuthenticatorAvailable(JSContext* cx, unsigned argc, JS::Value* vp)
4076
0
{
4077
0
  AUTO_PROFILER_LABEL_FAST("PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable", DOM, cx);
4078
0
4079
0
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
4080
0
  JS::Rooted<JSObject*> obj(cx, &args.callee());
4081
0
4082
0
  GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
4083
0
  if (global.Failed()) {
4084
0
    return false;
4085
0
  }
4086
0
4087
0
  auto result(StrongOrRawPtr<Promise>(mozilla::dom::PublicKeyCredential::IsUserVerifyingPlatformAuthenticatorAvailable(global)));
4088
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
4089
0
  if (!ToJSValue(cx, result, args.rval())) {
4090
0
    return false;
4091
0
  }
4092
0
  return true;
4093
0
}
4094
4095
4096
static const JSJitInfo isUserVerifyingPlatformAuthenticatorAvailable_methodinfo = {
4097
  { (JSJitGetterOp)isUserVerifyingPlatformAuthenticatorAvailable },
4098
  { prototypes::id::_ID_Count }, { 0 }, JSJitInfo::StaticMethod,
4099
  JSJitInfo::AliasEverything, JSVAL_TYPE_MISSING, false, false,
4100
  false, false, 0
4101
};
4102
4103
static bool
4104
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
4105
0
{
4106
0
  mozilla::dom::PublicKeyCredential* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PublicKeyCredential>(obj);
4107
0
  // We don't want to preserve if we don't have a wrapper, and we
4108
0
  // obviously can't preserve if we're not initialized.
4109
0
  if (self && self->GetWrapperPreserveColor()) {
4110
0
    PreserveWrapper(self);
4111
0
  }
4112
0
  return true;
4113
0
}
4114
4115
static void
4116
_finalize(js::FreeOp* fop, JSObject* obj)
4117
0
{
4118
0
  mozilla::dom::PublicKeyCredential* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PublicKeyCredential>(obj);
4119
0
  if (self) {
4120
0
    ClearWrapper(self, self, obj);
4121
0
    AddForDeferredFinalization<mozilla::dom::PublicKeyCredential>(self);
4122
0
  }
4123
0
}
4124
4125
static size_t
4126
_objectMoved(JSObject* obj, JSObject* old)
4127
0
{
4128
0
  mozilla::dom::PublicKeyCredential* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PublicKeyCredential>(obj);
4129
0
  if (self) {
4130
0
    UpdateWrapper(self, self, obj, old);
4131
0
  }
4132
0
4133
0
  return 0;
4134
0
}
4135
4136
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
4137
#if defined(__clang__)
4138
#pragma clang diagnostic push
4139
#pragma clang diagnostic ignored "-Wmissing-braces"
4140
#endif
4141
static const JSFunctionSpec sStaticMethods_specs[] = {
4142
  JS_FNSPEC("isUserVerifyingPlatformAuthenticatorAvailable", StaticMethodPromiseWrapper, &isUserVerifyingPlatformAuthenticatorAvailable_methodinfo, 0, JSPROP_ENUMERATE, nullptr),
4143
  JS_FS_END
4144
};
4145
#if defined(__clang__)
4146
#pragma clang diagnostic pop
4147
#endif
4148
4149
// Can't be const because the pref-enabled boolean needs to be writable
4150
static PrefableDisablers sStaticMethods_disablers0 = {
4151
  true, true, 0, nullptr
4152
};
4153
4154
static const Prefable<const JSFunctionSpec> sStaticMethods[] = {
4155
  { &sStaticMethods_disablers0, &sStaticMethods_specs[0] },
4156
  { nullptr, nullptr }
4157
};
4158
4159
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
4160
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
4161
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
4162
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
4163
4164
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
4165
#if defined(__clang__)
4166
#pragma clang diagnostic push
4167
#pragma clang diagnostic ignored "-Wmissing-braces"
4168
#endif
4169
static const JSFunctionSpec sMethods_specs[] = {
4170
  JS_FNSPEC("getClientExtensionResults", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&getClientExtensionResults_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
4171
  JS_FS_END
4172
};
4173
#if defined(__clang__)
4174
#pragma clang diagnostic pop
4175
#endif
4176
4177
// Can't be const because the pref-enabled boolean needs to be writable
4178
static PrefableDisablers sMethods_disablers0 = {
4179
  true, true, 0, nullptr
4180
};
4181
4182
static const Prefable<const JSFunctionSpec> sMethods[] = {
4183
  { &sMethods_disablers0, &sMethods_specs[0] },
4184
  { nullptr, nullptr }
4185
};
4186
4187
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
4188
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
4189
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
4190
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
4191
4192
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
4193
#if defined(__clang__)
4194
#pragma clang diagnostic push
4195
#pragma clang diagnostic ignored "-Wmissing-braces"
4196
#endif
4197
static const JSPropertySpec sAttributes_specs[] = {
4198
  { "rawId", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &rawId_getterinfo, nullptr, nullptr },
4199
  { "response", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &response_getterinfo, nullptr, nullptr },
4200
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
4201
};
4202
#if defined(__clang__)
4203
#pragma clang diagnostic pop
4204
#endif
4205
4206
// Can't be const because the pref-enabled boolean needs to be writable
4207
static PrefableDisablers sAttributes_disablers0 = {
4208
  true, true, 0, nullptr
4209
};
4210
4211
static const Prefable<const JSPropertySpec> sAttributes[] = {
4212
  { &sAttributes_disablers0, &sAttributes_specs[0] },
4213
  { nullptr, nullptr }
4214
};
4215
4216
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
4217
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
4218
static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
4219
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
4220
4221
4222
static uint16_t sNativeProperties_sortedPropertyIndices[4];
4223
static PropertyInfo sNativeProperties_propertyInfos[4];
4224
4225
static const NativePropertiesN<3> sNativeProperties = {
4226
  true,  0 /* sStaticMethods */,
4227
  false, 0,
4228
  true,  1 /* sMethods */,
4229
  true,  2 /* sAttributes */,
4230
  false, 0,
4231
  false, 0,
4232
  false, 0,
4233
  -1,
4234
  4,
4235
  sNativeProperties_sortedPropertyIndices,
4236
  {
4237
    { sStaticMethods, &sNativeProperties_propertyInfos[0] },
4238
    { sMethods, &sNativeProperties_propertyInfos[1] },
4239
    { sAttributes, &sNativeProperties_propertyInfos[2] }
4240
  }
4241
};
4242
static_assert(4 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
4243
    "We have a property info count that is oversized");
4244
4245
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
4246
  {
4247
    "Function",
4248
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
4249
    &sBoringInterfaceObjectClassClassOps,
4250
    JS_NULL_CLASS_SPEC,
4251
    JS_NULL_CLASS_EXT,
4252
    &sInterfaceObjectClassObjectOps
4253
  },
4254
  eInterface,
4255
  true,
4256
  prototypes::id::PublicKeyCredential,
4257
  PrototypeTraits<prototypes::id::PublicKeyCredential>::Depth,
4258
  sNativePropertyHooks,
4259
  "function PublicKeyCredential() {\n    [native code]\n}",
4260
  Credential_Binding::GetConstructorObject
4261
};
4262
4263
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
4264
  {
4265
    "PublicKeyCredentialPrototype",
4266
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
4267
    JS_NULL_CLASS_OPS,
4268
    JS_NULL_CLASS_SPEC,
4269
    JS_NULL_CLASS_EXT,
4270
    JS_NULL_OBJECT_OPS
4271
  },
4272
  eInterfacePrototype,
4273
  false,
4274
  prototypes::id::PublicKeyCredential,
4275
  PrototypeTraits<prototypes::id::PublicKeyCredential>::Depth,
4276
  sNativePropertyHooks,
4277
  "[object PublicKeyCredentialPrototype]",
4278
  Credential_Binding::GetProtoObject
4279
};
4280
4281
bool
4282
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
4283
0
{
4284
0
  static bool sPrefValue;
4285
0
  static bool sPrefCacheSetUp = false;
4286
0
  if (!sPrefCacheSetUp) {
4287
0
    sPrefCacheSetUp = true;
4288
0
    Preferences::AddBoolVarCache(&sPrefValue, "security.webauth.webauthn");
4289
0
  }
4290
0
4291
0
  return sPrefValue &&
4292
0
         mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx, aObj);
4293
0
}
4294
4295
static const js::ClassOps sClassOps = {
4296
  _addProperty, /* addProperty */
4297
  nullptr,               /* delProperty */
4298
  nullptr,               /* enumerate */
4299
  nullptr, /* newEnumerate */
4300
  nullptr, /* resolve */
4301
  nullptr, /* mayResolve */
4302
  _finalize, /* finalize */
4303
  nullptr, /* call */
4304
  nullptr,               /* hasInstance */
4305
  nullptr,               /* construct */
4306
  nullptr, /* trace */
4307
};
4308
4309
static const js::ClassExtension sClassExtension = {
4310
  nullptr, /* weakmapKeyDelegateOp */
4311
  _objectMoved /* objectMovedOp */
4312
};
4313
4314
static const DOMJSClass sClass = {
4315
  { "PublicKeyCredential",
4316
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
4317
    &sClassOps,
4318
    JS_NULL_CLASS_SPEC,
4319
    &sClassExtension,
4320
    JS_NULL_OBJECT_OPS
4321
  },
4322
  { prototypes::id::Credential, prototypes::id::PublicKeyCredential, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
4323
  IsBaseOf<nsISupports, mozilla::dom::PublicKeyCredential >::value,
4324
  sNativePropertyHooks,
4325
  FindAssociatedGlobalForNative<mozilla::dom::PublicKeyCredential>::Get,
4326
  GetProtoObjectHandle,
4327
  GetCCParticipant<mozilla::dom::PublicKeyCredential>::Get()
4328
};
4329
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
4330
              "Must have the right minimal number of reserved slots.");
4331
static_assert(1 >= 1,
4332
              "Must have enough reserved slots.");
4333
4334
const JSClass*
4335
GetJSClass()
4336
0
{
4337
0
  return sClass.ToJSClass();
4338
0
}
4339
4340
bool
4341
Wrap(JSContext* aCx, mozilla::dom::PublicKeyCredential* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
4342
0
{
4343
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::PublicKeyCredential>::value,
4344
0
                "Shouldn't have wrappercached things that are not refcounted.");
4345
0
  MOZ_ASSERT(static_cast<mozilla::dom::PublicKeyCredential*>(aObject) ==
4346
0
             reinterpret_cast<mozilla::dom::PublicKeyCredential*>(aObject),
4347
0
             "Multiple inheritance for mozilla::dom::PublicKeyCredential is broken.");
4348
0
  MOZ_ASSERT(static_cast<mozilla::dom::Credential*>(aObject) ==
4349
0
             reinterpret_cast<mozilla::dom::Credential*>(aObject),
4350
0
             "Multiple inheritance for mozilla::dom::Credential is broken.");
4351
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
4352
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
4353
0
  MOZ_ASSERT(!aCache->GetWrapper(),
4354
0
             "You should probably not be using Wrap() directly; use "
4355
0
             "GetOrCreateDOMReflector instead");
4356
0
4357
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
4358
0
             "nsISupports must be on our primary inheritance chain");
4359
0
4360
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
4361
0
  if (!global) {
4362
0
    return false;
4363
0
  }
4364
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
4365
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
4366
0
4367
0
  // That might have ended up wrapping us already, due to the wonders
4368
0
  // of XBL.  Check for that, and bail out as needed.
4369
0
  aReflector.set(aCache->GetWrapper());
4370
0
  if (aReflector) {
4371
#ifdef DEBUG
4372
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
4373
#endif // DEBUG
4374
    return true;
4375
0
  }
4376
0
4377
0
  JSAutoRealm ar(aCx, global);
4378
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
4379
0
  if (!canonicalProto) {
4380
0
    return false;
4381
0
  }
4382
0
  JS::Rooted<JSObject*> proto(aCx);
4383
0
  if (aGivenProto) {
4384
0
    proto = aGivenProto;
4385
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
4386
0
    // coming in, we changed compartments to that of "parent" so may need
4387
0
    // to wrap the proto here.
4388
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
4389
0
      if (!JS_WrapObject(aCx, &proto)) {
4390
0
        return false;
4391
0
      }
4392
0
    }
4393
0
  } else {
4394
0
    proto = canonicalProto;
4395
0
  }
4396
0
4397
0
  BindingJSObjectCreator<mozilla::dom::PublicKeyCredential> creator(aCx);
4398
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
4399
0
  if (!aReflector) {
4400
0
    return false;
4401
0
  }
4402
0
4403
0
  aCache->SetWrapper(aReflector);
4404
0
  creator.InitializationSucceeded();
4405
0
4406
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
4407
0
             aCache->GetWrapperPreserveColor() == aReflector);
4408
0
  // If proto != canonicalProto, we have to preserve our wrapper;
4409
0
  // otherwise we won't be able to properly recreate it later, since
4410
0
  // we won't know what proto to use.  Note that we don't check
4411
0
  // aGivenProto here, since it's entirely possible (and even
4412
0
  // somewhat common) to have a non-null aGivenProto which is the
4413
0
  // same as canonicalProto.
4414
0
  if (proto != canonicalProto) {
4415
0
    PreserveWrapper(aObject);
4416
0
  }
4417
0
4418
0
  return true;
4419
0
}
4420
4421
const NativePropertyHooks sNativePropertyHooks[] = { {
4422
  nullptr,
4423
  nullptr,
4424
  nullptr,
4425
  { sNativeProperties.Upcast(), nullptr },
4426
  prototypes::id::PublicKeyCredential,
4427
  constructors::id::PublicKeyCredential,
4428
  Credential_Binding::sNativePropertyHooks,
4429
  &DefaultXrayExpandoObjectClass
4430
} };
4431
4432
void
4433
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
4434
0
{
4435
0
  JS::Handle<JSObject*> parentProto(Credential_Binding::GetProtoObjectHandle(aCx));
4436
0
  if (!parentProto) {
4437
0
    return;
4438
0
  }
4439
0
4440
0
  JS::Handle<JSObject*> constructorProto(Credential_Binding::GetConstructorObjectHandle(aCx));
4441
0
  if (!constructorProto) {
4442
0
    return;
4443
0
  }
4444
0
4445
0
  static bool sIdsInited = false;
4446
0
  if (!sIdsInited && NS_IsMainThread()) {
4447
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
4448
0
      return;
4449
0
    }
4450
0
    sIdsInited = true;
4451
0
  }
4452
0
4453
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::PublicKeyCredential);
4454
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::PublicKeyCredential);
4455
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
4456
0
                              &sPrototypeClass.mBase, protoCache,
4457
0
                              nullptr,
4458
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
4459
0
                              interfaceCache,
4460
0
                              sNativeProperties.Upcast(),
4461
0
                              nullptr,
4462
0
                              "PublicKeyCredential", aDefineOnGlobal,
4463
0
                              nullptr,
4464
0
                              false);
4465
0
}
4466
4467
JSObject*
4468
GetConstructorObject(JSContext* aCx)
4469
0
{
4470
0
  return GetConstructorObjectHandle(aCx);
4471
0
}
4472
4473
} // namespace PublicKeyCredential_Binding
4474
4475
4476
4477
} // namespace dom
4478
} // namespace mozilla