Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/U2FBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM U2F.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "U2FBinding.h"
5
#include "WrapperFactory.h"
6
#include "jsapi.h"
7
#include "mozilla/OwningNonNull.h"
8
#include "mozilla/Preferences.h"
9
#include "mozilla/dom/BindingUtils.h"
10
#include "mozilla/dom/DOMJSClass.h"
11
#include "mozilla/dom/NonRefcountedDOMObject.h"
12
#include "mozilla/dom/Nullable.h"
13
#include "mozilla/dom/PrimitiveConversions.h"
14
#include "mozilla/dom/ScriptSettings.h"
15
#include "mozilla/dom/SimpleGlobalObject.h"
16
#include "mozilla/dom/U2F.h"
17
#include "mozilla/dom/XrayExpandoClass.h"
18
19
namespace mozilla {
20
namespace dom {
21
22
namespace binding_detail {}; // Just to make sure it's known as a namespace
23
using namespace mozilla::dom::binding_detail;
24
25
26
namespace TransportValues {
27
extern const EnumEntry strings[5] = {
28
  {"bt", 2},
29
  {"ble", 3},
30
  {"nfc", 3},
31
  {"usb", 3},
32
  { nullptr, 0 }
33
};
34
} // namespace TransportValues
35
36
bool
37
ToJSValue(JSContext* aCx, Transport aArgument, JS::MutableHandle<JS::Value> aValue)
38
0
{
39
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(TransportValues::strings));
40
0
  JSString* resultStr =
41
0
    JS_NewStringCopyN(aCx, TransportValues::strings[uint32_t(aArgument)].value,
42
0
                      TransportValues::strings[uint32_t(aArgument)].length);
43
0
  if (!resultStr) {
44
0
    return false;
45
0
  }
46
0
  aValue.setString(resultStr);
47
0
  return true;
48
0
}
49
50
51
52
RegisterRequest::RegisterRequest()
53
0
{
54
0
  // Safe to pass a null context if we pass a null value
55
0
  Init(nullptr, JS::NullHandleValue);
56
0
}
57
58
59
60
bool
61
RegisterRequest::InitIds(JSContext* cx, RegisterRequestAtoms* atomsCache)
62
0
{
63
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
64
0
65
0
  // Initialize these in reverse order so that any failure leaves the first one
66
0
  // uninitialized.
67
0
  if (!atomsCache->version_id.init(cx, "version") ||
68
0
      !atomsCache->challenge_id.init(cx, "challenge")) {
69
0
    return false;
70
0
  }
71
0
  return true;
72
0
}
73
74
bool
75
RegisterRequest::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
76
0
{
77
0
  // Passing a null JSContext is OK only if we're initing from null,
78
0
  // Since in that case we will not have to do any property gets
79
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
80
0
  // checkers by static analysis tools
81
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
82
0
  RegisterRequestAtoms* atomsCache = nullptr;
83
0
  if (cx) {
84
0
    atomsCache = GetAtomCache<RegisterRequestAtoms>(cx);
85
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
86
0
      return false;
87
0
    }
88
0
  }
89
0
90
0
  if (!IsConvertibleToDictionary(val)) {
91
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
92
0
  }
93
0
94
0
  bool isNull = val.isNullOrUndefined();
95
0
  // We only need these if !isNull, in which case we have |cx|.
96
0
  Maybe<JS::Rooted<JSObject *> > object;
97
0
  Maybe<JS::Rooted<JS::Value> > temp;
98
0
  if (!isNull) {
99
0
    MOZ_ASSERT(cx);
100
0
    object.emplace(cx, &val.toObject());
101
0
    temp.emplace(cx);
102
0
  }
103
0
  if (!isNull) {
104
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->challenge_id, temp.ptr())) {
105
0
      return false;
106
0
    }
107
0
  }
108
0
  if (!isNull && !temp->isUndefined()) {
109
0
    mChallenge.Construct();
110
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mChallenge.Value()))) {
111
0
      return false;
112
0
    }
113
0
    mIsAnyMemberPresent = true;
114
0
  }
115
0
116
0
  if (!isNull) {
117
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->version_id, temp.ptr())) {
118
0
      return false;
119
0
    }
120
0
  }
121
0
  if (!isNull && !temp->isUndefined()) {
122
0
    mVersion.Construct();
123
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mVersion.Value()))) {
124
0
      return false;
125
0
    }
126
0
    mIsAnyMemberPresent = true;
127
0
  }
128
0
  return true;
129
0
}
130
131
bool
132
RegisterRequest::Init(const nsAString& aJSON)
133
0
{
134
0
  AutoJSAPI jsapi;
135
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
136
0
  if (!cleanGlobal) {
137
0
    return false;
138
0
  }
139
0
  if (!jsapi.Init(cleanGlobal)) {
140
0
    return false;
141
0
  }
142
0
  JSContext* cx = jsapi.cx();
143
0
  JS::Rooted<JS::Value> json(cx);
144
0
  bool ok = ParseJSON(cx, aJSON, &json);
145
0
  NS_ENSURE_TRUE(ok, false);
146
0
  return Init(cx, json);
147
0
}
148
149
bool
150
RegisterRequest::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
151
0
{
152
0
  RegisterRequestAtoms* atomsCache = GetAtomCache<RegisterRequestAtoms>(cx);
153
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
154
0
    return false;
155
0
  }
156
0
157
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
158
0
  if (!obj) {
159
0
    return false;
160
0
  }
161
0
  rval.set(JS::ObjectValue(*obj));
162
0
163
0
  if (mChallenge.WasPassed()) {
164
0
    do {
165
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
166
0
      JS::Rooted<JS::Value> temp(cx);
167
0
      nsString const & currentValue = mChallenge.InternalValue();
168
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
169
0
        return false;
170
0
      }
171
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->challenge_id, temp, JSPROP_ENUMERATE)) {
172
0
        return false;
173
0
      }
174
0
      break;
175
0
    } while(false);
176
0
  }
177
0
178
0
  if (mVersion.WasPassed()) {
179
0
    do {
180
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
181
0
      JS::Rooted<JS::Value> temp(cx);
182
0
      nsString const & currentValue = mVersion.InternalValue();
183
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
184
0
        return false;
185
0
      }
186
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->version_id, temp, JSPROP_ENUMERATE)) {
187
0
        return false;
188
0
      }
189
0
      break;
190
0
    } while(false);
191
0
  }
192
0
193
0
  return true;
194
0
}
195
196
bool
197
RegisterRequest::ToJSON(nsAString& aJSON) const
198
0
{
199
0
  AutoJSAPI jsapi;
200
0
  jsapi.Init();
201
0
  JSContext *cx = jsapi.cx();
202
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
203
0
  // because we'll only be creating objects, in ways that have no
204
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
205
0
  // which likewise guarantees no side-effects for the sorts of
206
0
  // things we will pass it.
207
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
208
0
  JS::Rooted<JS::Value> val(cx);
209
0
  if (!ToObjectInternal(cx, &val)) {
210
0
    return false;
211
0
  }
212
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
213
0
  return StringifyToJSON(cx, obj, aJSON);
214
0
}
215
216
void
217
RegisterRequest::TraceDictionary(JSTracer* trc)
218
0
{
219
0
}
220
221
RegisterRequest&
222
RegisterRequest::operator=(const RegisterRequest& aOther)
223
0
{
224
0
  DictionaryBase::operator=(aOther);
225
0
  mChallenge.Reset();
226
0
  if (aOther.mChallenge.WasPassed()) {
227
0
    mChallenge.Construct(aOther.mChallenge.Value());
228
0
  }
229
0
  mVersion.Reset();
230
0
  if (aOther.mVersion.WasPassed()) {
231
0
    mVersion.Construct(aOther.mVersion.Value());
232
0
  }
233
0
  return *this;
234
0
}
235
236
namespace binding_detail {
237
} // namespace binding_detail
238
239
240
241
RegisterResponse::RegisterResponse()
242
0
{
243
0
  // Safe to pass a null context if we pass a null value
244
0
  Init(nullptr, JS::NullHandleValue);
245
0
}
246
247
248
249
bool
250
RegisterResponse::InitIds(JSContext* cx, RegisterResponseAtoms* atomsCache)
251
0
{
252
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
253
0
254
0
  // Initialize these in reverse order so that any failure leaves the first one
255
0
  // uninitialized.
256
0
  if (!atomsCache->version_id.init(cx, "version") ||
257
0
      !atomsCache->registrationData_id.init(cx, "registrationData") ||
258
0
      !atomsCache->errorMessage_id.init(cx, "errorMessage") ||
259
0
      !atomsCache->errorCode_id.init(cx, "errorCode") ||
260
0
      !atomsCache->clientData_id.init(cx, "clientData")) {
261
0
    return false;
262
0
  }
263
0
  return true;
264
0
}
265
266
bool
267
RegisterResponse::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
268
0
{
269
0
  // Passing a null JSContext is OK only if we're initing from null,
270
0
  // Since in that case we will not have to do any property gets
271
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
272
0
  // checkers by static analysis tools
273
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
274
0
  RegisterResponseAtoms* atomsCache = nullptr;
275
0
  if (cx) {
276
0
    atomsCache = GetAtomCache<RegisterResponseAtoms>(cx);
277
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
278
0
      return false;
279
0
    }
280
0
  }
281
0
282
0
  if (!IsConvertibleToDictionary(val)) {
283
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
284
0
  }
285
0
286
0
  bool isNull = val.isNullOrUndefined();
287
0
  // We only need these if !isNull, in which case we have |cx|.
288
0
  Maybe<JS::Rooted<JSObject *> > object;
289
0
  Maybe<JS::Rooted<JS::Value> > temp;
290
0
  if (!isNull) {
291
0
    MOZ_ASSERT(cx);
292
0
    object.emplace(cx, &val.toObject());
293
0
    temp.emplace(cx);
294
0
  }
295
0
  if (!isNull) {
296
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->clientData_id, temp.ptr())) {
297
0
      return false;
298
0
    }
299
0
  }
300
0
  if (!isNull && !temp->isUndefined()) {
301
0
    mClientData.Construct();
302
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mClientData.Value()))) {
303
0
      return false;
304
0
    }
305
0
    mIsAnyMemberPresent = true;
306
0
  }
307
0
308
0
  if (!isNull) {
309
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->errorCode_id, temp.ptr())) {
310
0
      return false;
311
0
    }
312
0
  }
313
0
  if (!isNull && !temp->isUndefined()) {
314
0
    mErrorCode.Construct();
315
0
    if (temp.ref().isNullOrUndefined()) {
316
0
      (mErrorCode.Value()).SetNull();
317
0
    } else if (!ValueToPrimitive<uint16_t, eDefault>(cx, temp.ref(), &(mErrorCode.Value()).SetValue())) {
318
0
      return false;
319
0
    }
320
0
    mIsAnyMemberPresent = true;
321
0
  }
322
0
323
0
  if (!isNull) {
324
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->errorMessage_id, temp.ptr())) {
325
0
      return false;
326
0
    }
327
0
  }
328
0
  if (!isNull && !temp->isUndefined()) {
329
0
    mErrorMessage.Construct();
330
0
    if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, (mErrorMessage.Value()))) {
331
0
      return false;
332
0
    }
333
0
    mIsAnyMemberPresent = true;
334
0
  }
335
0
336
0
  if (!isNull) {
337
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->registrationData_id, temp.ptr())) {
338
0
      return false;
339
0
    }
340
0
  }
341
0
  if (!isNull && !temp->isUndefined()) {
342
0
    mRegistrationData.Construct();
343
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mRegistrationData.Value()))) {
344
0
      return false;
345
0
    }
346
0
    mIsAnyMemberPresent = true;
347
0
  }
348
0
349
0
  if (!isNull) {
350
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->version_id, temp.ptr())) {
351
0
      return false;
352
0
    }
353
0
  }
354
0
  if (!isNull && !temp->isUndefined()) {
355
0
    mVersion.Construct();
356
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mVersion.Value()))) {
357
0
      return false;
358
0
    }
359
0
    mIsAnyMemberPresent = true;
360
0
  }
361
0
  return true;
362
0
}
363
364
bool
365
RegisterResponse::Init(const nsAString& aJSON)
366
0
{
367
0
  AutoJSAPI jsapi;
368
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
369
0
  if (!cleanGlobal) {
370
0
    return false;
371
0
  }
372
0
  if (!jsapi.Init(cleanGlobal)) {
373
0
    return false;
374
0
  }
375
0
  JSContext* cx = jsapi.cx();
376
0
  JS::Rooted<JS::Value> json(cx);
377
0
  bool ok = ParseJSON(cx, aJSON, &json);
378
0
  NS_ENSURE_TRUE(ok, false);
379
0
  return Init(cx, json);
380
0
}
381
382
bool
383
RegisterResponse::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
384
0
{
385
0
  RegisterResponseAtoms* atomsCache = GetAtomCache<RegisterResponseAtoms>(cx);
386
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
387
0
    return false;
388
0
  }
389
0
390
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
391
0
  if (!obj) {
392
0
    return false;
393
0
  }
394
0
  rval.set(JS::ObjectValue(*obj));
395
0
396
0
  if (mClientData.WasPassed()) {
397
0
    do {
398
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
399
0
      JS::Rooted<JS::Value> temp(cx);
400
0
      nsString const & currentValue = mClientData.InternalValue();
401
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
402
0
        return false;
403
0
      }
404
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->clientData_id, temp, JSPROP_ENUMERATE)) {
405
0
        return false;
406
0
      }
407
0
      break;
408
0
    } while(false);
409
0
  }
410
0
411
0
  if (mErrorCode.WasPassed()) {
412
0
    do {
413
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
414
0
      JS::Rooted<JS::Value> temp(cx);
415
0
      Nullable<uint16_t> const & currentValue = mErrorCode.InternalValue();
416
0
      if (currentValue.IsNull()) {
417
0
        temp.setNull();
418
0
        if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
419
0
          return false;
420
0
        }
421
0
        break;
422
0
      }
423
0
      temp.setInt32(int32_t(currentValue.Value()));
424
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
425
0
        return false;
426
0
      }
427
0
      break;
428
0
    } while(false);
429
0
  }
430
0
431
0
  if (mErrorMessage.WasPassed()) {
432
0
    do {
433
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
434
0
      JS::Rooted<JS::Value> temp(cx);
435
0
      nsString const & currentValue = mErrorMessage.InternalValue();
436
0
      if (!xpc::StringToJsval(cx, currentValue, &temp)) {
437
0
        return false;
438
0
      }
439
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->errorMessage_id, temp, JSPROP_ENUMERATE)) {
440
0
        return false;
441
0
      }
442
0
      break;
443
0
    } while(false);
444
0
  }
445
0
446
0
  if (mRegistrationData.WasPassed()) {
447
0
    do {
448
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
449
0
      JS::Rooted<JS::Value> temp(cx);
450
0
      nsString const & currentValue = mRegistrationData.InternalValue();
451
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
452
0
        return false;
453
0
      }
454
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->registrationData_id, temp, JSPROP_ENUMERATE)) {
455
0
        return false;
456
0
      }
457
0
      break;
458
0
    } while(false);
459
0
  }
460
0
461
0
  if (mVersion.WasPassed()) {
462
0
    do {
463
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
464
0
      JS::Rooted<JS::Value> temp(cx);
465
0
      nsString const & currentValue = mVersion.InternalValue();
466
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
467
0
        return false;
468
0
      }
469
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->version_id, temp, JSPROP_ENUMERATE)) {
470
0
        return false;
471
0
      }
472
0
      break;
473
0
    } while(false);
474
0
  }
475
0
476
0
  return true;
477
0
}
478
479
bool
480
RegisterResponse::ToJSON(nsAString& aJSON) const
481
0
{
482
0
  AutoJSAPI jsapi;
483
0
  jsapi.Init();
484
0
  JSContext *cx = jsapi.cx();
485
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
486
0
  // because we'll only be creating objects, in ways that have no
487
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
488
0
  // which likewise guarantees no side-effects for the sorts of
489
0
  // things we will pass it.
490
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
491
0
  JS::Rooted<JS::Value> val(cx);
492
0
  if (!ToObjectInternal(cx, &val)) {
493
0
    return false;
494
0
  }
495
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
496
0
  return StringifyToJSON(cx, obj, aJSON);
497
0
}
498
499
void
500
RegisterResponse::TraceDictionary(JSTracer* trc)
501
0
{
502
0
}
503
504
RegisterResponse&
505
RegisterResponse::operator=(const RegisterResponse& aOther)
506
0
{
507
0
  DictionaryBase::operator=(aOther);
508
0
  mClientData.Reset();
509
0
  if (aOther.mClientData.WasPassed()) {
510
0
    mClientData.Construct(aOther.mClientData.Value());
511
0
  }
512
0
  mErrorCode.Reset();
513
0
  if (aOther.mErrorCode.WasPassed()) {
514
0
    mErrorCode.Construct(aOther.mErrorCode.Value());
515
0
  }
516
0
  mErrorMessage.Reset();
517
0
  if (aOther.mErrorMessage.WasPassed()) {
518
0
    mErrorMessage.Construct(aOther.mErrorMessage.Value());
519
0
  }
520
0
  mRegistrationData.Reset();
521
0
  if (aOther.mRegistrationData.WasPassed()) {
522
0
    mRegistrationData.Construct(aOther.mRegistrationData.Value());
523
0
  }
524
0
  mVersion.Reset();
525
0
  if (aOther.mVersion.WasPassed()) {
526
0
    mVersion.Construct(aOther.mVersion.Value());
527
0
  }
528
0
  return *this;
529
0
}
530
531
namespace binding_detail {
532
} // namespace binding_detail
533
534
535
536
RegisteredKey::RegisteredKey()
537
0
{
538
0
  // Safe to pass a null context if we pass a null value
539
0
  Init(nullptr, JS::NullHandleValue);
540
0
}
541
542
543
544
bool
545
RegisteredKey::InitIds(JSContext* cx, RegisteredKeyAtoms* atomsCache)
546
0
{
547
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
548
0
549
0
  // Initialize these in reverse order so that any failure leaves the first one
550
0
  // uninitialized.
551
0
  if (!atomsCache->version_id.init(cx, "version") ||
552
0
      !atomsCache->transports_id.init(cx, "transports") ||
553
0
      !atomsCache->keyHandle_id.init(cx, "keyHandle") ||
554
0
      !atomsCache->appId_id.init(cx, "appId")) {
555
0
    return false;
556
0
  }
557
0
  return true;
558
0
}
559
560
bool
561
RegisteredKey::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
562
0
{
563
0
  // Passing a null JSContext is OK only if we're initing from null,
564
0
  // Since in that case we will not have to do any property gets
565
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
566
0
  // checkers by static analysis tools
567
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
568
0
  RegisteredKeyAtoms* atomsCache = nullptr;
569
0
  if (cx) {
570
0
    atomsCache = GetAtomCache<RegisteredKeyAtoms>(cx);
571
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
572
0
      return false;
573
0
    }
574
0
  }
575
0
576
0
  if (!IsConvertibleToDictionary(val)) {
577
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
578
0
  }
579
0
580
0
  bool isNull = val.isNullOrUndefined();
581
0
  // We only need these if !isNull, in which case we have |cx|.
582
0
  Maybe<JS::Rooted<JSObject *> > object;
583
0
  Maybe<JS::Rooted<JS::Value> > temp;
584
0
  if (!isNull) {
585
0
    MOZ_ASSERT(cx);
586
0
    object.emplace(cx, &val.toObject());
587
0
    temp.emplace(cx);
588
0
  }
589
0
  if (!isNull) {
590
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->appId_id, temp.ptr())) {
591
0
      return false;
592
0
    }
593
0
  }
594
0
  if (!isNull && !temp->isUndefined()) {
595
0
    mAppId.Construct();
596
0
    if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, (mAppId.Value()))) {
597
0
      return false;
598
0
    }
599
0
    mIsAnyMemberPresent = true;
600
0
  }
601
0
602
0
  if (!isNull) {
603
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->keyHandle_id, temp.ptr())) {
604
0
      return false;
605
0
    }
606
0
  }
607
0
  if (!isNull && !temp->isUndefined()) {
608
0
    mKeyHandle.Construct();
609
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mKeyHandle.Value()))) {
610
0
      return false;
611
0
    }
612
0
    mIsAnyMemberPresent = true;
613
0
  }
614
0
615
0
  if (!isNull) {
616
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->transports_id, temp.ptr())) {
617
0
      return false;
618
0
    }
619
0
  }
620
0
  if (!isNull && !temp->isUndefined()) {
621
0
    mTransports.Construct();
622
0
    if (temp.ref().isObject()) {
623
0
      JS::ForOfIterator iter(cx);
624
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
625
0
        return false;
626
0
      }
627
0
      if (!iter.valueIsIterable()) {
628
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transports' member of RegisteredKey");
629
0
        return false;
630
0
      }
631
0
      Sequence<Transport> &arr = (mTransports.Value()).SetValue();
632
0
      JS::Rooted<JS::Value> temp(cx);
633
0
      while (true) {
634
0
        bool done;
635
0
        if (!iter.next(&temp, &done)) {
636
0
          return false;
637
0
        }
638
0
        if (done) {
639
0
          break;
640
0
        }
641
0
        Transport* slotPtr = arr.AppendElement(mozilla::fallible);
642
0
        if (!slotPtr) {
643
0
          JS_ReportOutOfMemory(cx);
644
0
          return false;
645
0
        }
646
0
        Transport& slot = *slotPtr;
647
0
        {
648
0
          int index;
649
0
          if (!FindEnumStringIndex<true>(cx, temp, TransportValues::strings, "Transport", "Element of 'transports' member of RegisteredKey", &index)) {
650
0
            return false;
651
0
          }
652
0
          MOZ_ASSERT(index >= 0);
653
0
          slot = static_cast<Transport>(index);
654
0
        }
655
0
      }
656
0
    } else if (temp.ref().isNullOrUndefined()) {
657
0
      (mTransports.Value()).SetNull();
658
0
    } else {
659
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'transports' member of RegisteredKey");
660
0
      return false;
661
0
    }
662
0
    mIsAnyMemberPresent = true;
663
0
  }
664
0
665
0
  if (!isNull) {
666
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->version_id, temp.ptr())) {
667
0
      return false;
668
0
    }
669
0
  }
670
0
  if (!isNull && !temp->isUndefined()) {
671
0
    mVersion.Construct();
672
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mVersion.Value()))) {
673
0
      return false;
674
0
    }
675
0
    mIsAnyMemberPresent = true;
676
0
  }
677
0
  return true;
678
0
}
679
680
bool
681
RegisteredKey::Init(const nsAString& aJSON)
682
0
{
683
0
  AutoJSAPI jsapi;
684
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
685
0
  if (!cleanGlobal) {
686
0
    return false;
687
0
  }
688
0
  if (!jsapi.Init(cleanGlobal)) {
689
0
    return false;
690
0
  }
691
0
  JSContext* cx = jsapi.cx();
692
0
  JS::Rooted<JS::Value> json(cx);
693
0
  bool ok = ParseJSON(cx, aJSON, &json);
694
0
  NS_ENSURE_TRUE(ok, false);
695
0
  return Init(cx, json);
696
0
}
697
698
bool
699
RegisteredKey::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
700
0
{
701
0
  RegisteredKeyAtoms* atomsCache = GetAtomCache<RegisteredKeyAtoms>(cx);
702
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
703
0
    return false;
704
0
  }
705
0
706
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
707
0
  if (!obj) {
708
0
    return false;
709
0
  }
710
0
  rval.set(JS::ObjectValue(*obj));
711
0
712
0
  if (mAppId.WasPassed()) {
713
0
    do {
714
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
715
0
      JS::Rooted<JS::Value> temp(cx);
716
0
      nsString const & currentValue = mAppId.InternalValue();
717
0
      if (!xpc::StringToJsval(cx, currentValue, &temp)) {
718
0
        return false;
719
0
      }
720
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->appId_id, temp, JSPROP_ENUMERATE)) {
721
0
        return false;
722
0
      }
723
0
      break;
724
0
    } while(false);
725
0
  }
726
0
727
0
  if (mKeyHandle.WasPassed()) {
728
0
    do {
729
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
730
0
      JS::Rooted<JS::Value> temp(cx);
731
0
      nsString const & currentValue = mKeyHandle.InternalValue();
732
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
733
0
        return false;
734
0
      }
735
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->keyHandle_id, temp, JSPROP_ENUMERATE)) {
736
0
        return false;
737
0
      }
738
0
      break;
739
0
    } while(false);
740
0
  }
741
0
742
0
  if (mTransports.WasPassed()) {
743
0
    do {
744
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
745
0
      JS::Rooted<JS::Value> temp(cx);
746
0
      Nullable<Sequence<Transport>> const & currentValue = mTransports.InternalValue();
747
0
748
0
      if (currentValue.IsNull()) {
749
0
        temp.setNull();
750
0
        if (!JS_DefinePropertyById(cx, obj, atomsCache->transports_id, temp, JSPROP_ENUMERATE)) {
751
0
          return false;
752
0
        }
753
0
        break;
754
0
      }
755
0
756
0
      uint32_t length = currentValue.Value().Length();
757
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
758
0
      if (!returnArray) {
759
0
        return false;
760
0
      }
761
0
      // Scope for 'tmp'
762
0
      {
763
0
        JS::Rooted<JS::Value> tmp(cx);
764
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
765
0
          // Control block to let us common up the JS_DefineElement calls when there
766
0
          // are different ways to succeed at wrapping the object.
767
0
          do {
768
0
            if (!ToJSValue(cx, currentValue.Value()[sequenceIdx0], &tmp)) {
769
0
              return false;
770
0
            }
771
0
            break;
772
0
          } while (false);
773
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
774
0
                                JSPROP_ENUMERATE)) {
775
0
            return false;
776
0
          }
777
0
        }
778
0
      }
779
0
      temp.setObject(*returnArray);
780
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->transports_id, temp, JSPROP_ENUMERATE)) {
781
0
        return false;
782
0
      }
783
0
      break;
784
0
    } while(false);
785
0
  }
786
0
787
0
  if (mVersion.WasPassed()) {
788
0
    do {
789
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
790
0
      JS::Rooted<JS::Value> temp(cx);
791
0
      nsString const & currentValue = mVersion.InternalValue();
792
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
793
0
        return false;
794
0
      }
795
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->version_id, temp, JSPROP_ENUMERATE)) {
796
0
        return false;
797
0
      }
798
0
      break;
799
0
    } while(false);
800
0
  }
801
0
802
0
  return true;
803
0
}
804
805
bool
806
RegisteredKey::ToJSON(nsAString& aJSON) const
807
0
{
808
0
  AutoJSAPI jsapi;
809
0
  jsapi.Init();
810
0
  JSContext *cx = jsapi.cx();
811
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
812
0
  // because we'll only be creating objects, in ways that have no
813
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
814
0
  // which likewise guarantees no side-effects for the sorts of
815
0
  // things we will pass it.
816
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
817
0
  JS::Rooted<JS::Value> val(cx);
818
0
  if (!ToObjectInternal(cx, &val)) {
819
0
    return false;
820
0
  }
821
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
822
0
  return StringifyToJSON(cx, obj, aJSON);
823
0
}
824
825
void
826
RegisteredKey::TraceDictionary(JSTracer* trc)
827
0
{
828
0
}
829
830
RegisteredKey&
831
RegisteredKey::operator=(const RegisteredKey& aOther)
832
0
{
833
0
  DictionaryBase::operator=(aOther);
834
0
  mAppId.Reset();
835
0
  if (aOther.mAppId.WasPassed()) {
836
0
    mAppId.Construct(aOther.mAppId.Value());
837
0
  }
838
0
  mKeyHandle.Reset();
839
0
  if (aOther.mKeyHandle.WasPassed()) {
840
0
    mKeyHandle.Construct(aOther.mKeyHandle.Value());
841
0
  }
842
0
  mTransports.Reset();
843
0
  if (aOther.mTransports.WasPassed()) {
844
0
    mTransports.Construct(aOther.mTransports.Value());
845
0
  }
846
0
  mVersion.Reset();
847
0
  if (aOther.mVersion.WasPassed()) {
848
0
    mVersion.Construct(aOther.mVersion.Value());
849
0
  }
850
0
  return *this;
851
0
}
852
853
namespace binding_detail {
854
} // namespace binding_detail
855
856
857
858
SignResponse::SignResponse()
859
0
{
860
0
  // Safe to pass a null context if we pass a null value
861
0
  Init(nullptr, JS::NullHandleValue);
862
0
}
863
864
865
866
bool
867
SignResponse::InitIds(JSContext* cx, SignResponseAtoms* atomsCache)
868
0
{
869
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
870
0
871
0
  // Initialize these in reverse order so that any failure leaves the first one
872
0
  // uninitialized.
873
0
  if (!atomsCache->signatureData_id.init(cx, "signatureData") ||
874
0
      !atomsCache->keyHandle_id.init(cx, "keyHandle") ||
875
0
      !atomsCache->errorMessage_id.init(cx, "errorMessage") ||
876
0
      !atomsCache->errorCode_id.init(cx, "errorCode") ||
877
0
      !atomsCache->clientData_id.init(cx, "clientData")) {
878
0
    return false;
879
0
  }
880
0
  return true;
881
0
}
882
883
bool
884
SignResponse::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
885
0
{
886
0
  // Passing a null JSContext is OK only if we're initing from null,
887
0
  // Since in that case we will not have to do any property gets
888
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
889
0
  // checkers by static analysis tools
890
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
891
0
  SignResponseAtoms* atomsCache = nullptr;
892
0
  if (cx) {
893
0
    atomsCache = GetAtomCache<SignResponseAtoms>(cx);
894
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
895
0
      return false;
896
0
    }
897
0
  }
898
0
899
0
  if (!IsConvertibleToDictionary(val)) {
900
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
901
0
  }
902
0
903
0
  bool isNull = val.isNullOrUndefined();
904
0
  // We only need these if !isNull, in which case we have |cx|.
905
0
  Maybe<JS::Rooted<JSObject *> > object;
906
0
  Maybe<JS::Rooted<JS::Value> > temp;
907
0
  if (!isNull) {
908
0
    MOZ_ASSERT(cx);
909
0
    object.emplace(cx, &val.toObject());
910
0
    temp.emplace(cx);
911
0
  }
912
0
  if (!isNull) {
913
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->clientData_id, temp.ptr())) {
914
0
      return false;
915
0
    }
916
0
  }
917
0
  if (!isNull && !temp->isUndefined()) {
918
0
    mClientData.Construct();
919
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mClientData.Value()))) {
920
0
      return false;
921
0
    }
922
0
    mIsAnyMemberPresent = true;
923
0
  }
924
0
925
0
  if (!isNull) {
926
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->errorCode_id, temp.ptr())) {
927
0
      return false;
928
0
    }
929
0
  }
930
0
  if (!isNull && !temp->isUndefined()) {
931
0
    mErrorCode.Construct();
932
0
    if (temp.ref().isNullOrUndefined()) {
933
0
      (mErrorCode.Value()).SetNull();
934
0
    } else if (!ValueToPrimitive<uint16_t, eDefault>(cx, temp.ref(), &(mErrorCode.Value()).SetValue())) {
935
0
      return false;
936
0
    }
937
0
    mIsAnyMemberPresent = true;
938
0
  }
939
0
940
0
  if (!isNull) {
941
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->errorMessage_id, temp.ptr())) {
942
0
      return false;
943
0
    }
944
0
  }
945
0
  if (!isNull && !temp->isUndefined()) {
946
0
    mErrorMessage.Construct();
947
0
    if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, (mErrorMessage.Value()))) {
948
0
      return false;
949
0
    }
950
0
    mIsAnyMemberPresent = true;
951
0
  }
952
0
953
0
  if (!isNull) {
954
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->keyHandle_id, temp.ptr())) {
955
0
      return false;
956
0
    }
957
0
  }
958
0
  if (!isNull && !temp->isUndefined()) {
959
0
    mKeyHandle.Construct();
960
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mKeyHandle.Value()))) {
961
0
      return false;
962
0
    }
963
0
    mIsAnyMemberPresent = true;
964
0
  }
965
0
966
0
  if (!isNull) {
967
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->signatureData_id, temp.ptr())) {
968
0
      return false;
969
0
    }
970
0
  }
971
0
  if (!isNull && !temp->isUndefined()) {
972
0
    mSignatureData.Construct();
973
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mSignatureData.Value()))) {
974
0
      return false;
975
0
    }
976
0
    mIsAnyMemberPresent = true;
977
0
  }
978
0
  return true;
979
0
}
980
981
bool
982
SignResponse::Init(const nsAString& aJSON)
983
0
{
984
0
  AutoJSAPI jsapi;
985
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
986
0
  if (!cleanGlobal) {
987
0
    return false;
988
0
  }
989
0
  if (!jsapi.Init(cleanGlobal)) {
990
0
    return false;
991
0
  }
992
0
  JSContext* cx = jsapi.cx();
993
0
  JS::Rooted<JS::Value> json(cx);
994
0
  bool ok = ParseJSON(cx, aJSON, &json);
995
0
  NS_ENSURE_TRUE(ok, false);
996
0
  return Init(cx, json);
997
0
}
998
999
bool
1000
SignResponse::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1001
0
{
1002
0
  SignResponseAtoms* atomsCache = GetAtomCache<SignResponseAtoms>(cx);
1003
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1004
0
    return false;
1005
0
  }
1006
0
1007
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1008
0
  if (!obj) {
1009
0
    return false;
1010
0
  }
1011
0
  rval.set(JS::ObjectValue(*obj));
1012
0
1013
0
  if (mClientData.WasPassed()) {
1014
0
    do {
1015
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1016
0
      JS::Rooted<JS::Value> temp(cx);
1017
0
      nsString const & currentValue = mClientData.InternalValue();
1018
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1019
0
        return false;
1020
0
      }
1021
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->clientData_id, temp, JSPROP_ENUMERATE)) {
1022
0
        return false;
1023
0
      }
1024
0
      break;
1025
0
    } while(false);
1026
0
  }
1027
0
1028
0
  if (mErrorCode.WasPassed()) {
1029
0
    do {
1030
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1031
0
      JS::Rooted<JS::Value> temp(cx);
1032
0
      Nullable<uint16_t> const & currentValue = mErrorCode.InternalValue();
1033
0
      if (currentValue.IsNull()) {
1034
0
        temp.setNull();
1035
0
        if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
1036
0
          return false;
1037
0
        }
1038
0
        break;
1039
0
      }
1040
0
      temp.setInt32(int32_t(currentValue.Value()));
1041
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->errorCode_id, temp, JSPROP_ENUMERATE)) {
1042
0
        return false;
1043
0
      }
1044
0
      break;
1045
0
    } while(false);
1046
0
  }
1047
0
1048
0
  if (mErrorMessage.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 = mErrorMessage.InternalValue();
1053
0
      if (!xpc::StringToJsval(cx, currentValue, &temp)) {
1054
0
        return false;
1055
0
      }
1056
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->errorMessage_id, temp, JSPROP_ENUMERATE)) {
1057
0
        return false;
1058
0
      }
1059
0
      break;
1060
0
    } while(false);
1061
0
  }
1062
0
1063
0
  if (mKeyHandle.WasPassed()) {
1064
0
    do {
1065
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1066
0
      JS::Rooted<JS::Value> temp(cx);
1067
0
      nsString const & currentValue = mKeyHandle.InternalValue();
1068
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1069
0
        return false;
1070
0
      }
1071
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->keyHandle_id, temp, JSPROP_ENUMERATE)) {
1072
0
        return false;
1073
0
      }
1074
0
      break;
1075
0
    } while(false);
1076
0
  }
1077
0
1078
0
  if (mSignatureData.WasPassed()) {
1079
0
    do {
1080
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1081
0
      JS::Rooted<JS::Value> temp(cx);
1082
0
      nsString const & currentValue = mSignatureData.InternalValue();
1083
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1084
0
        return false;
1085
0
      }
1086
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->signatureData_id, temp, JSPROP_ENUMERATE)) {
1087
0
        return false;
1088
0
      }
1089
0
      break;
1090
0
    } while(false);
1091
0
  }
1092
0
1093
0
  return true;
1094
0
}
1095
1096
bool
1097
SignResponse::ToJSON(nsAString& aJSON) const
1098
0
{
1099
0
  AutoJSAPI jsapi;
1100
0
  jsapi.Init();
1101
0
  JSContext *cx = jsapi.cx();
1102
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1103
0
  // because we'll only be creating objects, in ways that have no
1104
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1105
0
  // which likewise guarantees no side-effects for the sorts of
1106
0
  // things we will pass it.
1107
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1108
0
  JS::Rooted<JS::Value> val(cx);
1109
0
  if (!ToObjectInternal(cx, &val)) {
1110
0
    return false;
1111
0
  }
1112
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1113
0
  return StringifyToJSON(cx, obj, aJSON);
1114
0
}
1115
1116
void
1117
SignResponse::TraceDictionary(JSTracer* trc)
1118
0
{
1119
0
}
1120
1121
SignResponse&
1122
SignResponse::operator=(const SignResponse& aOther)
1123
0
{
1124
0
  DictionaryBase::operator=(aOther);
1125
0
  mClientData.Reset();
1126
0
  if (aOther.mClientData.WasPassed()) {
1127
0
    mClientData.Construct(aOther.mClientData.Value());
1128
0
  }
1129
0
  mErrorCode.Reset();
1130
0
  if (aOther.mErrorCode.WasPassed()) {
1131
0
    mErrorCode.Construct(aOther.mErrorCode.Value());
1132
0
  }
1133
0
  mErrorMessage.Reset();
1134
0
  if (aOther.mErrorMessage.WasPassed()) {
1135
0
    mErrorMessage.Construct(aOther.mErrorMessage.Value());
1136
0
  }
1137
0
  mKeyHandle.Reset();
1138
0
  if (aOther.mKeyHandle.WasPassed()) {
1139
0
    mKeyHandle.Construct(aOther.mKeyHandle.Value());
1140
0
  }
1141
0
  mSignatureData.Reset();
1142
0
  if (aOther.mSignatureData.WasPassed()) {
1143
0
    mSignatureData.Construct(aOther.mSignatureData.Value());
1144
0
  }
1145
0
  return *this;
1146
0
}
1147
1148
namespace binding_detail {
1149
} // namespace binding_detail
1150
1151
1152
1153
U2FClientData::U2FClientData()
1154
0
{
1155
0
  // Safe to pass a null context if we pass a null value
1156
0
  Init(nullptr, JS::NullHandleValue);
1157
0
}
1158
1159
1160
1161
bool
1162
U2FClientData::InitIds(JSContext* cx, U2FClientDataAtoms* atomsCache)
1163
0
{
1164
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1165
0
1166
0
  // Initialize these in reverse order so that any failure leaves the first one
1167
0
  // uninitialized.
1168
0
  if (!atomsCache->typ_id.init(cx, "typ") ||
1169
0
      !atomsCache->origin_id.init(cx, "origin") ||
1170
0
      !atomsCache->challenge_id.init(cx, "challenge")) {
1171
0
    return false;
1172
0
  }
1173
0
  return true;
1174
0
}
1175
1176
bool
1177
U2FClientData::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1178
0
{
1179
0
  // Passing a null JSContext is OK only if we're initing from null,
1180
0
  // Since in that case we will not have to do any property gets
1181
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1182
0
  // checkers by static analysis tools
1183
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1184
0
  U2FClientDataAtoms* atomsCache = nullptr;
1185
0
  if (cx) {
1186
0
    atomsCache = GetAtomCache<U2FClientDataAtoms>(cx);
1187
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1188
0
      return false;
1189
0
    }
1190
0
  }
1191
0
1192
0
  if (!IsConvertibleToDictionary(val)) {
1193
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1194
0
  }
1195
0
1196
0
  bool isNull = val.isNullOrUndefined();
1197
0
  // We only need these if !isNull, in which case we have |cx|.
1198
0
  Maybe<JS::Rooted<JSObject *> > object;
1199
0
  Maybe<JS::Rooted<JS::Value> > temp;
1200
0
  if (!isNull) {
1201
0
    MOZ_ASSERT(cx);
1202
0
    object.emplace(cx, &val.toObject());
1203
0
    temp.emplace(cx);
1204
0
  }
1205
0
  if (!isNull) {
1206
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->challenge_id, temp.ptr())) {
1207
0
      return false;
1208
0
    }
1209
0
  }
1210
0
  if (!isNull && !temp->isUndefined()) {
1211
0
    mChallenge.Construct();
1212
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mChallenge.Value()))) {
1213
0
      return false;
1214
0
    }
1215
0
    mIsAnyMemberPresent = true;
1216
0
  }
1217
0
1218
0
  if (!isNull) {
1219
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->origin_id, temp.ptr())) {
1220
0
      return false;
1221
0
    }
1222
0
  }
1223
0
  if (!isNull && !temp->isUndefined()) {
1224
0
    mOrigin.Construct();
1225
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mOrigin.Value()))) {
1226
0
      return false;
1227
0
    }
1228
0
    mIsAnyMemberPresent = true;
1229
0
  }
1230
0
1231
0
  if (!isNull) {
1232
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->typ_id, temp.ptr())) {
1233
0
      return false;
1234
0
    }
1235
0
  }
1236
0
  if (!isNull && !temp->isUndefined()) {
1237
0
    mTyp.Construct();
1238
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mTyp.Value()))) {
1239
0
      return false;
1240
0
    }
1241
0
    mIsAnyMemberPresent = true;
1242
0
  }
1243
0
  return true;
1244
0
}
1245
1246
bool
1247
U2FClientData::Init(const nsAString& aJSON)
1248
0
{
1249
0
  AutoJSAPI jsapi;
1250
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1251
0
  if (!cleanGlobal) {
1252
0
    return false;
1253
0
  }
1254
0
  if (!jsapi.Init(cleanGlobal)) {
1255
0
    return false;
1256
0
  }
1257
0
  JSContext* cx = jsapi.cx();
1258
0
  JS::Rooted<JS::Value> json(cx);
1259
0
  bool ok = ParseJSON(cx, aJSON, &json);
1260
0
  NS_ENSURE_TRUE(ok, false);
1261
0
  return Init(cx, json);
1262
0
}
1263
1264
bool
1265
U2FClientData::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1266
0
{
1267
0
  U2FClientDataAtoms* atomsCache = GetAtomCache<U2FClientDataAtoms>(cx);
1268
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1269
0
    return false;
1270
0
  }
1271
0
1272
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1273
0
  if (!obj) {
1274
0
    return false;
1275
0
  }
1276
0
  rval.set(JS::ObjectValue(*obj));
1277
0
1278
0
  if (mChallenge.WasPassed()) {
1279
0
    do {
1280
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1281
0
      JS::Rooted<JS::Value> temp(cx);
1282
0
      nsString const & currentValue = mChallenge.InternalValue();
1283
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1284
0
        return false;
1285
0
      }
1286
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->challenge_id, temp, JSPROP_ENUMERATE)) {
1287
0
        return false;
1288
0
      }
1289
0
      break;
1290
0
    } while(false);
1291
0
  }
1292
0
1293
0
  if (mOrigin.WasPassed()) {
1294
0
    do {
1295
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1296
0
      JS::Rooted<JS::Value> temp(cx);
1297
0
      nsString const & currentValue = mOrigin.InternalValue();
1298
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1299
0
        return false;
1300
0
      }
1301
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->origin_id, temp, JSPROP_ENUMERATE)) {
1302
0
        return false;
1303
0
      }
1304
0
      break;
1305
0
    } while(false);
1306
0
  }
1307
0
1308
0
  if (mTyp.WasPassed()) {
1309
0
    do {
1310
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1311
0
      JS::Rooted<JS::Value> temp(cx);
1312
0
      nsString const & currentValue = mTyp.InternalValue();
1313
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1314
0
        return false;
1315
0
      }
1316
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->typ_id, temp, JSPROP_ENUMERATE)) {
1317
0
        return false;
1318
0
      }
1319
0
      break;
1320
0
    } while(false);
1321
0
  }
1322
0
1323
0
  return true;
1324
0
}
1325
1326
bool
1327
U2FClientData::ToJSON(nsAString& aJSON) const
1328
0
{
1329
0
  AutoJSAPI jsapi;
1330
0
  jsapi.Init();
1331
0
  JSContext *cx = jsapi.cx();
1332
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1333
0
  // because we'll only be creating objects, in ways that have no
1334
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1335
0
  // which likewise guarantees no side-effects for the sorts of
1336
0
  // things we will pass it.
1337
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1338
0
  JS::Rooted<JS::Value> val(cx);
1339
0
  if (!ToObjectInternal(cx, &val)) {
1340
0
    return false;
1341
0
  }
1342
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1343
0
  return StringifyToJSON(cx, obj, aJSON);
1344
0
}
1345
1346
void
1347
U2FClientData::TraceDictionary(JSTracer* trc)
1348
0
{
1349
0
}
1350
1351
U2FClientData&
1352
U2FClientData::operator=(const U2FClientData& aOther)
1353
0
{
1354
0
  DictionaryBase::operator=(aOther);
1355
0
  mChallenge.Reset();
1356
0
  if (aOther.mChallenge.WasPassed()) {
1357
0
    mChallenge.Construct(aOther.mChallenge.Value());
1358
0
  }
1359
0
  mOrigin.Reset();
1360
0
  if (aOther.mOrigin.WasPassed()) {
1361
0
    mOrigin.Construct(aOther.mOrigin.Value());
1362
0
  }
1363
0
  mTyp.Reset();
1364
0
  if (aOther.mTyp.WasPassed()) {
1365
0
    mTyp.Construct(aOther.mTyp.Value());
1366
0
  }
1367
0
  return *this;
1368
0
}
1369
1370
namespace binding_detail {
1371
} // namespace binding_detail
1372
1373
1374
void
1375
U2FRegisterCallback::Call(JSContext* cx, JS::Handle<JS::Value> aThisVal, const RegisterResponse& response, ErrorResult& aRv)
1376
0
{
1377
0
  JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
1378
0
  JS::AutoValueVector argv(cx);
1379
0
  if (!argv.resize(1)) {
1380
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
1381
0
    return;
1382
0
  }
1383
0
  unsigned argc = 1;
1384
0
1385
0
  do {
1386
0
    if (!response.ToObjectInternal(cx, argv[0])) {
1387
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
1388
0
      return;
1389
0
    }
1390
0
    break;
1391
0
  } while (false);
1392
0
1393
0
  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
1394
0
  if (!JS::Call(cx, aThisVal, callable,
1395
0
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
1396
0
    aRv.NoteJSContextException(cx);
1397
0
    return;
1398
0
  }
1399
0
}
1400
1401
1402
1403
void
1404
U2FSignCallback::Call(JSContext* cx, JS::Handle<JS::Value> aThisVal, const SignResponse& response, ErrorResult& aRv)
1405
0
{
1406
0
  JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
1407
0
  JS::AutoValueVector argv(cx);
1408
0
  if (!argv.resize(1)) {
1409
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
1410
0
    return;
1411
0
  }
1412
0
  unsigned argc = 1;
1413
0
1414
0
  do {
1415
0
    if (!response.ToObjectInternal(cx, argv[0])) {
1416
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
1417
0
      return;
1418
0
    }
1419
0
    break;
1420
0
  } while (false);
1421
0
1422
0
  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
1423
0
  if (!JS::Call(cx, aThisVal, callable,
1424
0
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
1425
0
    aRv.NoteJSContextException(cx);
1426
0
    return;
1427
0
  }
1428
0
}
1429
1430
1431
1432
namespace binding_detail {
1433
} // namespace binding_detail
1434
1435
1436
namespace binding_detail {
1437
} // namespace binding_detail
1438
1439
1440
namespace U2F_Binding {
1441
1442
MOZ_CAN_RUN_SCRIPT static bool
1443
_register_(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::U2F* self, const JSJitMethodCallArgs& args)
1444
0
{
1445
0
  AUTO_PROFILER_LABEL_FAST("U2F.register", DOM, cx);
1446
0
1447
0
  if (MOZ_UNLIKELY(args.length() < 4)) {
1448
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "U2F.register");
1449
0
  }
1450
0
  binding_detail::FakeString arg0;
1451
0
  if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
1452
0
    return false;
1453
0
  }
1454
0
  binding_detail::AutoSequence<RegisterRequest> arg1;
1455
0
  if (args[1].isObject()) {
1456
0
    JS::ForOfIterator iter(cx);
1457
0
    if (!iter.init(args[1], JS::ForOfIterator::AllowNonIterable)) {
1458
0
      return false;
1459
0
    }
1460
0
    if (!iter.valueIsIterable()) {
1461
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 2 of U2F.register");
1462
0
      return false;
1463
0
    }
1464
0
    binding_detail::AutoSequence<RegisterRequest> &arr = arg1;
1465
0
    JS::Rooted<JS::Value> temp(cx);
1466
0
    while (true) {
1467
0
      bool done;
1468
0
      if (!iter.next(&temp, &done)) {
1469
0
        return false;
1470
0
      }
1471
0
      if (done) {
1472
0
        break;
1473
0
      }
1474
0
      RegisterRequest* slotPtr = arr.AppendElement(mozilla::fallible);
1475
0
      if (!slotPtr) {
1476
0
        JS_ReportOutOfMemory(cx);
1477
0
        return false;
1478
0
      }
1479
0
      RegisterRequest& slot = *slotPtr;
1480
0
      if (!slot.Init(cx, temp,  "Element of argument 2 of U2F.register", false)) {
1481
0
        return false;
1482
0
      }
1483
0
    }
1484
0
  } else {
1485
0
    ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 2 of U2F.register");
1486
0
    return false;
1487
0
  }
1488
0
  binding_detail::AutoSequence<RegisteredKey> arg2;
1489
0
  if (args[2].isObject()) {
1490
0
    JS::ForOfIterator iter(cx);
1491
0
    if (!iter.init(args[2], JS::ForOfIterator::AllowNonIterable)) {
1492
0
      return false;
1493
0
    }
1494
0
    if (!iter.valueIsIterable()) {
1495
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.register");
1496
0
      return false;
1497
0
    }
1498
0
    binding_detail::AutoSequence<RegisteredKey> &arr = arg2;
1499
0
    JS::Rooted<JS::Value> temp(cx);
1500
0
    while (true) {
1501
0
      bool done;
1502
0
      if (!iter.next(&temp, &done)) {
1503
0
        return false;
1504
0
      }
1505
0
      if (done) {
1506
0
        break;
1507
0
      }
1508
0
      RegisteredKey* slotPtr = arr.AppendElement(mozilla::fallible);
1509
0
      if (!slotPtr) {
1510
0
        JS_ReportOutOfMemory(cx);
1511
0
        return false;
1512
0
      }
1513
0
      RegisteredKey& slot = *slotPtr;
1514
0
      if (!slot.Init(cx, temp,  "Element of argument 3 of U2F.register", false)) {
1515
0
        return false;
1516
0
      }
1517
0
    }
1518
0
  } else {
1519
0
    ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.register");
1520
0
    return false;
1521
0
  }
1522
0
  RootedCallback<OwningNonNull<binding_detail::FastU2FRegisterCallback>> arg3(cx);
1523
0
  if (args[3].isObject()) {
1524
0
    if (JS::IsCallable(&args[3].toObject())) {
1525
0
    { // scope for tempRoot and tempGlobalRoot if needed
1526
0
      arg3 = new binding_detail::FastU2FRegisterCallback(&args[3].toObject(), JS::CurrentGlobalOrNull(cx));
1527
0
    }
1528
0
    } else {
1529
0
      ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 4 of U2F.register");
1530
0
      return false;
1531
0
    }
1532
0
  } else {
1533
0
    ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 4 of U2F.register");
1534
0
    return false;
1535
0
  }
1536
0
  Optional<Nullable<int32_t>> arg4;
1537
0
  if (args.hasDefined(4)) {
1538
0
    arg4.Construct();
1539
0
    if (args[4].isNullOrUndefined()) {
1540
0
      arg4.Value().SetNull();
1541
0
    } else if (!ValueToPrimitive<int32_t, eDefault>(cx, args[4], &arg4.Value().SetValue())) {
1542
0
      return false;
1543
0
    }
1544
0
  }
1545
0
  FastErrorResult rv;
1546
0
  self->Register(NonNullHelper(Constify(arg0)), Constify(arg1), Constify(arg2), NonNullHelper(arg3), Constify(arg4), rv);
1547
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
1548
0
    return false;
1549
0
  }
1550
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1551
0
  args.rval().setUndefined();
1552
0
  return true;
1553
0
}
1554
1555
static const JSJitInfo register_methodinfo = {
1556
  { (JSJitGetterOp)_register_ },
1557
  { prototypes::id::U2F },
1558
  { PrototypeTraits<prototypes::id::U2F>::Depth },
1559
  JSJitInfo::Method,
1560
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
1561
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
1562
  false,  /* isInfallible. False in setters. */
1563
  false,  /* isMovable.  Not relevant for setters. */
1564
  false, /* isEliminatable.  Not relevant for setters. */
1565
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1566
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1567
  false,  /* isTypedMethod.  Only relevant for methods. */
1568
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1569
};
1570
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1571
static_assert(0 < 1, "There is no slot for us");
1572
1573
MOZ_CAN_RUN_SCRIPT static bool
1574
sign(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::U2F* self, const JSJitMethodCallArgs& args)
1575
0
{
1576
0
  AUTO_PROFILER_LABEL_FAST("U2F.sign", DOM, cx);
1577
0
1578
0
  if (MOZ_UNLIKELY(args.length() < 4)) {
1579
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "U2F.sign");
1580
0
  }
1581
0
  binding_detail::FakeString arg0;
1582
0
  if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
1583
0
    return false;
1584
0
  }
1585
0
  binding_detail::FakeString arg1;
1586
0
  if (!ConvertJSValueToString(cx, args[1], eStringify, eStringify, arg1)) {
1587
0
    return false;
1588
0
  }
1589
0
  binding_detail::AutoSequence<RegisteredKey> arg2;
1590
0
  if (args[2].isObject()) {
1591
0
    JS::ForOfIterator iter(cx);
1592
0
    if (!iter.init(args[2], JS::ForOfIterator::AllowNonIterable)) {
1593
0
      return false;
1594
0
    }
1595
0
    if (!iter.valueIsIterable()) {
1596
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.sign");
1597
0
      return false;
1598
0
    }
1599
0
    binding_detail::AutoSequence<RegisteredKey> &arr = arg2;
1600
0
    JS::Rooted<JS::Value> temp(cx);
1601
0
    while (true) {
1602
0
      bool done;
1603
0
      if (!iter.next(&temp, &done)) {
1604
0
        return false;
1605
0
      }
1606
0
      if (done) {
1607
0
        break;
1608
0
      }
1609
0
      RegisteredKey* slotPtr = arr.AppendElement(mozilla::fallible);
1610
0
      if (!slotPtr) {
1611
0
        JS_ReportOutOfMemory(cx);
1612
0
        return false;
1613
0
      }
1614
0
      RegisteredKey& slot = *slotPtr;
1615
0
      if (!slot.Init(cx, temp,  "Element of argument 3 of U2F.sign", false)) {
1616
0
        return false;
1617
0
      }
1618
0
    }
1619
0
  } else {
1620
0
    ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 3 of U2F.sign");
1621
0
    return false;
1622
0
  }
1623
0
  RootedCallback<OwningNonNull<binding_detail::FastU2FSignCallback>> arg3(cx);
1624
0
  if (args[3].isObject()) {
1625
0
    if (JS::IsCallable(&args[3].toObject())) {
1626
0
    { // scope for tempRoot and tempGlobalRoot if needed
1627
0
      arg3 = new binding_detail::FastU2FSignCallback(&args[3].toObject(), JS::CurrentGlobalOrNull(cx));
1628
0
    }
1629
0
    } else {
1630
0
      ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 4 of U2F.sign");
1631
0
      return false;
1632
0
    }
1633
0
  } else {
1634
0
    ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 4 of U2F.sign");
1635
0
    return false;
1636
0
  }
1637
0
  Optional<Nullable<int32_t>> arg4;
1638
0
  if (args.hasDefined(4)) {
1639
0
    arg4.Construct();
1640
0
    if (args[4].isNullOrUndefined()) {
1641
0
      arg4.Value().SetNull();
1642
0
    } else if (!ValueToPrimitive<int32_t, eDefault>(cx, args[4], &arg4.Value().SetValue())) {
1643
0
      return false;
1644
0
    }
1645
0
  }
1646
0
  FastErrorResult rv;
1647
0
  self->Sign(NonNullHelper(Constify(arg0)), NonNullHelper(Constify(arg1)), Constify(arg2), NonNullHelper(arg3), Constify(arg4), rv);
1648
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
1649
0
    return false;
1650
0
  }
1651
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1652
0
  args.rval().setUndefined();
1653
0
  return true;
1654
0
}
1655
1656
static const JSJitInfo sign_methodinfo = {
1657
  { (JSJitGetterOp)sign },
1658
  { prototypes::id::U2F },
1659
  { PrototypeTraits<prototypes::id::U2F>::Depth },
1660
  JSJitInfo::Method,
1661
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
1662
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
1663
  false,  /* isInfallible. False in setters. */
1664
  false,  /* isMovable.  Not relevant for setters. */
1665
  false, /* isEliminatable.  Not relevant for setters. */
1666
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1667
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1668
  false,  /* isTypedMethod.  Only relevant for methods. */
1669
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1670
};
1671
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1672
static_assert(0 < 1, "There is no slot for us");
1673
1674
static bool
1675
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
1676
0
{
1677
0
  mozilla::dom::U2F* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::U2F>(obj);
1678
0
  // We don't want to preserve if we don't have a wrapper, and we
1679
0
  // obviously can't preserve if we're not initialized.
1680
0
  if (self && self->GetWrapperPreserveColor()) {
1681
0
    PreserveWrapper(self);
1682
0
  }
1683
0
  return true;
1684
0
}
1685
1686
static void
1687
_finalize(js::FreeOp* fop, JSObject* obj)
1688
0
{
1689
0
  mozilla::dom::U2F* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::U2F>(obj);
1690
0
  if (self) {
1691
0
    ClearWrapper(self, self, obj);
1692
0
    AddForDeferredFinalization<mozilla::dom::U2F>(self);
1693
0
  }
1694
0
}
1695
1696
static size_t
1697
_objectMoved(JSObject* obj, JSObject* old)
1698
0
{
1699
0
  mozilla::dom::U2F* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::U2F>(obj);
1700
0
  if (self) {
1701
0
    UpdateWrapper(self, self, obj, old);
1702
0
  }
1703
0
1704
0
  return 0;
1705
0
}
1706
1707
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
1708
#if defined(__clang__)
1709
#pragma clang diagnostic push
1710
#pragma clang diagnostic ignored "-Wmissing-braces"
1711
#endif
1712
static const JSFunctionSpec sMethods_specs[] = {
1713
  JS_FNSPEC("register", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&register_methodinfo), 4, JSPROP_ENUMERATE, nullptr),
1714
  JS_FNSPEC("sign", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&sign_methodinfo), 4, JSPROP_ENUMERATE, nullptr),
1715
  JS_FS_END
1716
};
1717
#if defined(__clang__)
1718
#pragma clang diagnostic pop
1719
#endif
1720
1721
// Can't be const because the pref-enabled boolean needs to be writable
1722
static PrefableDisablers sMethods_disablers0 = {
1723
  true, true, 0, nullptr
1724
};
1725
1726
static const Prefable<const JSFunctionSpec> sMethods[] = {
1727
  { &sMethods_disablers0, &sMethods_specs[0] },
1728
  { nullptr, nullptr }
1729
};
1730
1731
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1732
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1733
static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1734
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1735
1736
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
1737
#if defined(__clang__)
1738
#pragma clang diagnostic push
1739
#pragma clang diagnostic ignored "-Wmissing-braces"
1740
#endif
1741
static const ConstantSpec sConstants_specs[] = {
1742
  { "OK", JS::Int32Value(0) },
1743
  { "OTHER_ERROR", JS::Int32Value(1) },
1744
  { "BAD_REQUEST", JS::Int32Value(2) },
1745
  { "CONFIGURATION_UNSUPPORTED", JS::Int32Value(3) },
1746
  { "DEVICE_INELIGIBLE", JS::Int32Value(4) },
1747
  { "TIMEOUT", JS::Int32Value(5) },
1748
  { 0, JS::UndefinedValue() }
1749
};
1750
#if defined(__clang__)
1751
#pragma clang diagnostic pop
1752
#endif
1753
1754
// Can't be const because the pref-enabled boolean needs to be writable
1755
static PrefableDisablers sConstants_disablers0 = {
1756
  true, true, 0, nullptr
1757
};
1758
1759
static const Prefable<const ConstantSpec> sConstants[] = {
1760
  { &sConstants_disablers0, &sConstants_specs[0] },
1761
  { nullptr, nullptr }
1762
};
1763
1764
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1765
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1766
static_assert(6 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1767
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1768
1769
1770
static uint16_t sNativeProperties_sortedPropertyIndices[8];
1771
static PropertyInfo sNativeProperties_propertyInfos[8];
1772
1773
static const NativePropertiesN<2> sNativeProperties = {
1774
  false, 0,
1775
  false, 0,
1776
  true,  0 /* sMethods */,
1777
  false, 0,
1778
  false, 0,
1779
  false, 0,
1780
  true,  1 /* sConstants */,
1781
  -1,
1782
  8,
1783
  sNativeProperties_sortedPropertyIndices,
1784
  {
1785
    { sMethods, &sNativeProperties_propertyInfos[0] },
1786
    { sConstants, &sNativeProperties_propertyInfos[2] }
1787
  }
1788
};
1789
static_assert(8 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
1790
    "We have a property info count that is oversized");
1791
1792
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
1793
  {
1794
    "Function",
1795
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
1796
    &sBoringInterfaceObjectClassClassOps,
1797
    JS_NULL_CLASS_SPEC,
1798
    JS_NULL_CLASS_EXT,
1799
    &sInterfaceObjectClassObjectOps
1800
  },
1801
  eInterface,
1802
  true,
1803
  prototypes::id::U2F,
1804
  PrototypeTraits<prototypes::id::U2F>::Depth,
1805
  sNativePropertyHooks,
1806
  "function U2F() {\n    [native code]\n}",
1807
  JS::GetRealmFunctionPrototype
1808
};
1809
1810
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
1811
  {
1812
    "U2FPrototype",
1813
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
1814
    JS_NULL_CLASS_OPS,
1815
    JS_NULL_CLASS_SPEC,
1816
    JS_NULL_CLASS_EXT,
1817
    JS_NULL_OBJECT_OPS
1818
  },
1819
  eInterfacePrototype,
1820
  false,
1821
  prototypes::id::U2F,
1822
  PrototypeTraits<prototypes::id::U2F>::Depth,
1823
  sNativePropertyHooks,
1824
  "[object U2FPrototype]",
1825
  JS::GetRealmObjectPrototype
1826
};
1827
1828
bool
1829
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
1830
0
{
1831
0
  static bool sPrefValue;
1832
0
  static bool sPrefCacheSetUp = false;
1833
0
  if (!sPrefCacheSetUp) {
1834
0
    sPrefCacheSetUp = true;
1835
0
    Preferences::AddBoolVarCache(&sPrefValue, "security.webauth.u2f");
1836
0
  }
1837
0
1838
0
  return sPrefValue &&
1839
0
         mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx, aObj);
1840
0
}
1841
1842
static const js::ClassOps sClassOps = {
1843
  _addProperty, /* addProperty */
1844
  nullptr,               /* delProperty */
1845
  nullptr,               /* enumerate */
1846
  nullptr, /* newEnumerate */
1847
  nullptr, /* resolve */
1848
  nullptr, /* mayResolve */
1849
  _finalize, /* finalize */
1850
  nullptr, /* call */
1851
  nullptr,               /* hasInstance */
1852
  nullptr,               /* construct */
1853
  nullptr, /* trace */
1854
};
1855
1856
static const js::ClassExtension sClassExtension = {
1857
  nullptr, /* weakmapKeyDelegateOp */
1858
  _objectMoved /* objectMovedOp */
1859
};
1860
1861
static const DOMJSClass sClass = {
1862
  { "U2F",
1863
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1864
    &sClassOps,
1865
    JS_NULL_CLASS_SPEC,
1866
    &sClassExtension,
1867
    JS_NULL_OBJECT_OPS
1868
  },
1869
  { prototypes::id::U2F, 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 },
1870
  IsBaseOf<nsISupports, mozilla::dom::U2F >::value,
1871
  sNativePropertyHooks,
1872
  FindAssociatedGlobalForNative<mozilla::dom::U2F>::Get,
1873
  GetProtoObjectHandle,
1874
  GetCCParticipant<mozilla::dom::U2F>::Get()
1875
};
1876
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1877
              "Must have the right minimal number of reserved slots.");
1878
static_assert(1 >= 1,
1879
              "Must have enough reserved slots.");
1880
1881
const JSClass*
1882
GetJSClass()
1883
0
{
1884
0
  return sClass.ToJSClass();
1885
0
}
1886
1887
bool
1888
Wrap(JSContext* aCx, mozilla::dom::U2F* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1889
0
{
1890
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::U2F>::value,
1891
0
                "Shouldn't have wrappercached things that are not refcounted.");
1892
0
  MOZ_ASSERT(static_cast<mozilla::dom::U2F*>(aObject) ==
1893
0
             reinterpret_cast<mozilla::dom::U2F*>(aObject),
1894
0
             "Multiple inheritance for mozilla::dom::U2F is broken.");
1895
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1896
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1897
0
  MOZ_ASSERT(!aCache->GetWrapper(),
1898
0
             "You should probably not be using Wrap() directly; use "
1899
0
             "GetOrCreateDOMReflector instead");
1900
0
1901
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1902
0
             "nsISupports must be on our primary inheritance chain");
1903
0
1904
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1905
0
  if (!global) {
1906
0
    return false;
1907
0
  }
1908
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
1909
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
1910
0
1911
0
  // That might have ended up wrapping us already, due to the wonders
1912
0
  // of XBL.  Check for that, and bail out as needed.
1913
0
  aReflector.set(aCache->GetWrapper());
1914
0
  if (aReflector) {
1915
#ifdef DEBUG
1916
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1917
#endif // DEBUG
1918
    return true;
1919
0
  }
1920
0
1921
0
  JSAutoRealm ar(aCx, global);
1922
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1923
0
  if (!canonicalProto) {
1924
0
    return false;
1925
0
  }
1926
0
  JS::Rooted<JSObject*> proto(aCx);
1927
0
  if (aGivenProto) {
1928
0
    proto = aGivenProto;
1929
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
1930
0
    // coming in, we changed compartments to that of "parent" so may need
1931
0
    // to wrap the proto here.
1932
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1933
0
      if (!JS_WrapObject(aCx, &proto)) {
1934
0
        return false;
1935
0
      }
1936
0
    }
1937
0
  } else {
1938
0
    proto = canonicalProto;
1939
0
  }
1940
0
1941
0
  BindingJSObjectCreator<mozilla::dom::U2F> creator(aCx);
1942
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1943
0
  if (!aReflector) {
1944
0
    return false;
1945
0
  }
1946
0
1947
0
  aCache->SetWrapper(aReflector);
1948
0
  creator.InitializationSucceeded();
1949
0
1950
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1951
0
             aCache->GetWrapperPreserveColor() == aReflector);
1952
0
  // If proto != canonicalProto, we have to preserve our wrapper;
1953
0
  // otherwise we won't be able to properly recreate it later, since
1954
0
  // we won't know what proto to use.  Note that we don't check
1955
0
  // aGivenProto here, since it's entirely possible (and even
1956
0
  // somewhat common) to have a non-null aGivenProto which is the
1957
0
  // same as canonicalProto.
1958
0
  if (proto != canonicalProto) {
1959
0
    PreserveWrapper(aObject);
1960
0
  }
1961
0
1962
0
  return true;
1963
0
}
1964
1965
const NativePropertyHooks sNativePropertyHooks[] = { {
1966
  nullptr,
1967
  nullptr,
1968
  nullptr,
1969
  { sNativeProperties.Upcast(), nullptr },
1970
  prototypes::id::U2F,
1971
  constructors::id::U2F,
1972
  nullptr,
1973
  &DefaultXrayExpandoObjectClass
1974
} };
1975
1976
void
1977
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1978
0
{
1979
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
1980
0
  if (!parentProto) {
1981
0
    return;
1982
0
  }
1983
0
1984
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
1985
0
  if (!constructorProto) {
1986
0
    return;
1987
0
  }
1988
0
1989
0
  static bool sIdsInited = false;
1990
0
  if (!sIdsInited && NS_IsMainThread()) {
1991
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
1992
0
      return;
1993
0
    }
1994
0
    sIdsInited = true;
1995
0
  }
1996
0
1997
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::U2F);
1998
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::U2F);
1999
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
2000
0
                              &sPrototypeClass.mBase, protoCache,
2001
0
                              nullptr,
2002
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
2003
0
                              interfaceCache,
2004
0
                              sNativeProperties.Upcast(),
2005
0
                              nullptr,
2006
0
                              "U2F", aDefineOnGlobal,
2007
0
                              nullptr,
2008
0
                              false);
2009
0
}
2010
2011
JSObject*
2012
GetConstructorObject(JSContext* aCx)
2013
0
{
2014
0
  return GetConstructorObjectHandle(aCx);
2015
0
}
2016
2017
} // namespace U2F_Binding
2018
2019
2020
2021
} // namespace dom
2022
} // namespace mozilla