Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/NetDashboardBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM NetDashboard.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "NetDashboardBinding.h"
5
#include "mozilla/FloatingPoint.h"
6
#include "mozilla/OwningNonNull.h"
7
#include "mozilla/dom/BindingUtils.h"
8
#include "mozilla/dom/NonRefcountedDOMObject.h"
9
#include "mozilla/dom/PrimitiveConversions.h"
10
#include "mozilla/dom/ScriptSettings.h"
11
#include "mozilla/dom/SimpleGlobalObject.h"
12
13
namespace mozilla {
14
namespace dom {
15
16
namespace binding_detail {}; // Just to make sure it's known as a namespace
17
using namespace mozilla::dom::binding_detail;
18
19
20
21
ConnStatusDict::ConnStatusDict()
22
0
{
23
0
  // Safe to pass a null context if we pass a null value
24
0
  Init(nullptr, JS::NullHandleValue);
25
0
}
26
27
28
29
bool
30
ConnStatusDict::InitIds(JSContext* cx, ConnStatusDictAtoms* atomsCache)
31
0
{
32
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
33
0
34
0
  // Initialize these in reverse order so that any failure leaves the first one
35
0
  // uninitialized.
36
0
  if (!atomsCache->status_id.init(cx, "status")) {
37
0
    return false;
38
0
  }
39
0
  return true;
40
0
}
41
42
bool
43
ConnStatusDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
44
0
{
45
0
  // Passing a null JSContext is OK only if we're initing from null,
46
0
  // Since in that case we will not have to do any property gets
47
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
48
0
  // checkers by static analysis tools
49
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
50
0
  ConnStatusDictAtoms* atomsCache = nullptr;
51
0
  if (cx) {
52
0
    atomsCache = GetAtomCache<ConnStatusDictAtoms>(cx);
53
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
54
0
      return false;
55
0
    }
56
0
  }
57
0
58
0
  if (!IsConvertibleToDictionary(val)) {
59
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
60
0
  }
61
0
62
0
  bool isNull = val.isNullOrUndefined();
63
0
  // We only need these if !isNull, in which case we have |cx|.
64
0
  Maybe<JS::Rooted<JSObject *> > object;
65
0
  Maybe<JS::Rooted<JS::Value> > temp;
66
0
  if (!isNull) {
67
0
    MOZ_ASSERT(cx);
68
0
    object.emplace(cx, &val.toObject());
69
0
    temp.emplace(cx);
70
0
  }
71
0
  if (!isNull) {
72
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->status_id, temp.ptr())) {
73
0
      return false;
74
0
    }
75
0
  }
76
0
  if (!isNull && !temp->isUndefined()) {
77
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mStatus)) {
78
0
      return false;
79
0
    }
80
0
  } else {
81
0
    static const char16_t data[] = { 0 };
82
0
    mStatus.Rebind(data, ArrayLength(data) - 1);
83
0
  }
84
0
  mIsAnyMemberPresent = true;
85
0
  return true;
86
0
}
87
88
bool
89
ConnStatusDict::Init(const nsAString& aJSON)
90
0
{
91
0
  AutoJSAPI jsapi;
92
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
93
0
  if (!cleanGlobal) {
94
0
    return false;
95
0
  }
96
0
  if (!jsapi.Init(cleanGlobal)) {
97
0
    return false;
98
0
  }
99
0
  JSContext* cx = jsapi.cx();
100
0
  JS::Rooted<JS::Value> json(cx);
101
0
  bool ok = ParseJSON(cx, aJSON, &json);
102
0
  NS_ENSURE_TRUE(ok, false);
103
0
  return Init(cx, json);
104
0
}
105
106
bool
107
ConnStatusDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
108
0
{
109
0
  ConnStatusDictAtoms* atomsCache = GetAtomCache<ConnStatusDictAtoms>(cx);
110
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
111
0
    return false;
112
0
  }
113
0
114
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
115
0
  if (!obj) {
116
0
    return false;
117
0
  }
118
0
  rval.set(JS::ObjectValue(*obj));
119
0
120
0
  do {
121
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
122
0
    JS::Rooted<JS::Value> temp(cx);
123
0
    nsString const & currentValue = mStatus;
124
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
125
0
      return false;
126
0
    }
127
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->status_id, temp, JSPROP_ENUMERATE)) {
128
0
      return false;
129
0
    }
130
0
    break;
131
0
  } while(false);
132
0
133
0
  return true;
134
0
}
135
136
bool
137
ConnStatusDict::ToJSON(nsAString& aJSON) const
138
0
{
139
0
  AutoJSAPI jsapi;
140
0
  jsapi.Init();
141
0
  JSContext *cx = jsapi.cx();
142
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
143
0
  // because we'll only be creating objects, in ways that have no
144
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
145
0
  // which likewise guarantees no side-effects for the sorts of
146
0
  // things we will pass it.
147
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
148
0
  JS::Rooted<JS::Value> val(cx);
149
0
  if (!ToObjectInternal(cx, &val)) {
150
0
    return false;
151
0
  }
152
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
153
0
  return StringifyToJSON(cx, obj, aJSON);
154
0
}
155
156
void
157
ConnStatusDict::TraceDictionary(JSTracer* trc)
158
0
{
159
0
}
160
161
ConnStatusDict&
162
ConnStatusDict::operator=(const ConnStatusDict& aOther)
163
0
{
164
0
  DictionaryBase::operator=(aOther);
165
0
  mStatus = aOther.mStatus;
166
0
  return *this;
167
0
}
168
169
namespace binding_detail {
170
} // namespace binding_detail
171
172
173
174
DNSLookupDict::DNSLookupDict()
175
0
{
176
0
  // Safe to pass a null context if we pass a null value
177
0
  Init(nullptr, JS::NullHandleValue);
178
0
}
179
180
181
182
bool
183
DNSLookupDict::InitIds(JSContext* cx, DNSLookupDictAtoms* atomsCache)
184
0
{
185
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
186
0
187
0
  // Initialize these in reverse order so that any failure leaves the first one
188
0
  // uninitialized.
189
0
  if (!atomsCache->error_id.init(cx, "error") ||
190
0
      !atomsCache->answer_id.init(cx, "answer") ||
191
0
      !atomsCache->address_id.init(cx, "address")) {
192
0
    return false;
193
0
  }
194
0
  return true;
195
0
}
196
197
bool
198
DNSLookupDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
199
0
{
200
0
  // Passing a null JSContext is OK only if we're initing from null,
201
0
  // Since in that case we will not have to do any property gets
202
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
203
0
  // checkers by static analysis tools
204
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
205
0
  DNSLookupDictAtoms* atomsCache = nullptr;
206
0
  if (cx) {
207
0
    atomsCache = GetAtomCache<DNSLookupDictAtoms>(cx);
208
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
209
0
      return false;
210
0
    }
211
0
  }
212
0
213
0
  if (!IsConvertibleToDictionary(val)) {
214
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
215
0
  }
216
0
217
0
  bool isNull = val.isNullOrUndefined();
218
0
  // We only need these if !isNull, in which case we have |cx|.
219
0
  Maybe<JS::Rooted<JSObject *> > object;
220
0
  Maybe<JS::Rooted<JS::Value> > temp;
221
0
  if (!isNull) {
222
0
    MOZ_ASSERT(cx);
223
0
    object.emplace(cx, &val.toObject());
224
0
    temp.emplace(cx);
225
0
  }
226
0
  if (!isNull) {
227
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->address_id, temp.ptr())) {
228
0
      return false;
229
0
    }
230
0
  }
231
0
  if (!isNull && !temp->isUndefined()) {
232
0
    mAddress.Construct();
233
0
    if (temp.ref().isObject()) {
234
0
      JS::ForOfIterator iter(cx);
235
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
236
0
        return false;
237
0
      }
238
0
      if (!iter.valueIsIterable()) {
239
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'address' member of DNSLookupDict");
240
0
        return false;
241
0
      }
242
0
      Sequence<nsString> &arr = (mAddress.Value());
243
0
      JS::Rooted<JS::Value> temp(cx);
244
0
      while (true) {
245
0
        bool done;
246
0
        if (!iter.next(&temp, &done)) {
247
0
          return false;
248
0
        }
249
0
        if (done) {
250
0
          break;
251
0
        }
252
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
253
0
        if (!slotPtr) {
254
0
          JS_ReportOutOfMemory(cx);
255
0
          return false;
256
0
        }
257
0
        nsString& slot = *slotPtr;
258
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
259
0
          return false;
260
0
        }
261
0
      }
262
0
    } else {
263
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'address' member of DNSLookupDict");
264
0
      return false;
265
0
    }
266
0
    mIsAnyMemberPresent = true;
267
0
  }
268
0
269
0
  if (!isNull) {
270
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->answer_id, temp.ptr())) {
271
0
      return false;
272
0
    }
273
0
  }
274
0
  if (!isNull && !temp->isUndefined()) {
275
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mAnswer)) {
276
0
      return false;
277
0
    }
278
0
  } else {
279
0
    mAnswer = false;
280
0
  }
281
0
  mIsAnyMemberPresent = true;
282
0
283
0
  if (!isNull) {
284
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->error_id, temp.ptr())) {
285
0
      return false;
286
0
    }
287
0
  }
288
0
  if (!isNull && !temp->isUndefined()) {
289
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mError)) {
290
0
      return false;
291
0
    }
292
0
  } else {
293
0
    static const char16_t data[] = { 0 };
294
0
    mError.Rebind(data, ArrayLength(data) - 1);
295
0
  }
296
0
  mIsAnyMemberPresent = true;
297
0
  return true;
298
0
}
299
300
bool
301
DNSLookupDict::Init(const nsAString& aJSON)
302
0
{
303
0
  AutoJSAPI jsapi;
304
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
305
0
  if (!cleanGlobal) {
306
0
    return false;
307
0
  }
308
0
  if (!jsapi.Init(cleanGlobal)) {
309
0
    return false;
310
0
  }
311
0
  JSContext* cx = jsapi.cx();
312
0
  JS::Rooted<JS::Value> json(cx);
313
0
  bool ok = ParseJSON(cx, aJSON, &json);
314
0
  NS_ENSURE_TRUE(ok, false);
315
0
  return Init(cx, json);
316
0
}
317
318
bool
319
DNSLookupDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
320
0
{
321
0
  DNSLookupDictAtoms* atomsCache = GetAtomCache<DNSLookupDictAtoms>(cx);
322
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
323
0
    return false;
324
0
  }
325
0
326
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
327
0
  if (!obj) {
328
0
    return false;
329
0
  }
330
0
  rval.set(JS::ObjectValue(*obj));
331
0
332
0
  if (mAddress.WasPassed()) {
333
0
    do {
334
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
335
0
      JS::Rooted<JS::Value> temp(cx);
336
0
      Sequence<nsString> const & currentValue = mAddress.InternalValue();
337
0
338
0
      uint32_t length = currentValue.Length();
339
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
340
0
      if (!returnArray) {
341
0
        return false;
342
0
      }
343
0
      // Scope for 'tmp'
344
0
      {
345
0
        JS::Rooted<JS::Value> tmp(cx);
346
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
347
0
          // Control block to let us common up the JS_DefineElement calls when there
348
0
          // are different ways to succeed at wrapping the object.
349
0
          do {
350
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
351
0
              return false;
352
0
            }
353
0
            break;
354
0
          } while (false);
355
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
356
0
                                JSPROP_ENUMERATE)) {
357
0
            return false;
358
0
          }
359
0
        }
360
0
      }
361
0
      temp.setObject(*returnArray);
362
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->address_id, temp, JSPROP_ENUMERATE)) {
363
0
        return false;
364
0
      }
365
0
      break;
366
0
    } while(false);
367
0
  }
368
0
369
0
  do {
370
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
371
0
    JS::Rooted<JS::Value> temp(cx);
372
0
    bool const & currentValue = mAnswer;
373
0
    temp.setBoolean(currentValue);
374
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->answer_id, temp, JSPROP_ENUMERATE)) {
375
0
      return false;
376
0
    }
377
0
    break;
378
0
  } while(false);
379
0
380
0
  do {
381
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
382
0
    JS::Rooted<JS::Value> temp(cx);
383
0
    nsString const & currentValue = mError;
384
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
385
0
      return false;
386
0
    }
387
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->error_id, temp, JSPROP_ENUMERATE)) {
388
0
      return false;
389
0
    }
390
0
    break;
391
0
  } while(false);
392
0
393
0
  return true;
394
0
}
395
396
bool
397
DNSLookupDict::ToJSON(nsAString& aJSON) const
398
0
{
399
0
  AutoJSAPI jsapi;
400
0
  jsapi.Init();
401
0
  JSContext *cx = jsapi.cx();
402
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
403
0
  // because we'll only be creating objects, in ways that have no
404
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
405
0
  // which likewise guarantees no side-effects for the sorts of
406
0
  // things we will pass it.
407
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
408
0
  JS::Rooted<JS::Value> val(cx);
409
0
  if (!ToObjectInternal(cx, &val)) {
410
0
    return false;
411
0
  }
412
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
413
0
  return StringifyToJSON(cx, obj, aJSON);
414
0
}
415
416
void
417
DNSLookupDict::TraceDictionary(JSTracer* trc)
418
0
{
419
0
}
420
421
DNSLookupDict&
422
DNSLookupDict::operator=(const DNSLookupDict& aOther)
423
0
{
424
0
  DictionaryBase::operator=(aOther);
425
0
  mAddress.Reset();
426
0
  if (aOther.mAddress.WasPassed()) {
427
0
    mAddress.Construct(aOther.mAddress.Value());
428
0
  }
429
0
  mAnswer = aOther.mAnswer;
430
0
  mError = aOther.mError;
431
0
  return *this;
432
0
}
433
434
namespace binding_detail {
435
} // namespace binding_detail
436
437
438
439
DnsCacheEntry::DnsCacheEntry()
440
0
{
441
0
  // Safe to pass a null context if we pass a null value
442
0
  Init(nullptr, JS::NullHandleValue);
443
0
}
444
445
446
447
bool
448
DnsCacheEntry::InitIds(JSContext* cx, DnsCacheEntryAtoms* atomsCache)
449
0
{
450
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
451
0
452
0
  // Initialize these in reverse order so that any failure leaves the first one
453
0
  // uninitialized.
454
0
  if (!atomsCache->trr_id.init(cx, "trr") ||
455
0
      !atomsCache->hostname_id.init(cx, "hostname") ||
456
0
      !atomsCache->hostaddr_id.init(cx, "hostaddr") ||
457
0
      !atomsCache->family_id.init(cx, "family") ||
458
0
      !atomsCache->expiration_id.init(cx, "expiration")) {
459
0
    return false;
460
0
  }
461
0
  return true;
462
0
}
463
464
bool
465
DnsCacheEntry::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
466
0
{
467
0
  // Passing a null JSContext is OK only if we're initing from null,
468
0
  // Since in that case we will not have to do any property gets
469
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
470
0
  // checkers by static analysis tools
471
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
472
0
  DnsCacheEntryAtoms* atomsCache = nullptr;
473
0
  if (cx) {
474
0
    atomsCache = GetAtomCache<DnsCacheEntryAtoms>(cx);
475
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
476
0
      return false;
477
0
    }
478
0
  }
479
0
480
0
  if (!IsConvertibleToDictionary(val)) {
481
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
482
0
  }
483
0
484
0
  bool isNull = val.isNullOrUndefined();
485
0
  // We only need these if !isNull, in which case we have |cx|.
486
0
  Maybe<JS::Rooted<JSObject *> > object;
487
0
  Maybe<JS::Rooted<JS::Value> > temp;
488
0
  if (!isNull) {
489
0
    MOZ_ASSERT(cx);
490
0
    object.emplace(cx, &val.toObject());
491
0
    temp.emplace(cx);
492
0
  }
493
0
  if (!isNull) {
494
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->expiration_id, temp.ptr())) {
495
0
      return false;
496
0
    }
497
0
  }
498
0
  if (!isNull && !temp->isUndefined()) {
499
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mExpiration)) {
500
0
      return false;
501
0
    } else if (!mozilla::IsFinite(mExpiration)) {
502
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'expiration' member of DnsCacheEntry");
503
0
      return false;
504
0
    }
505
0
  } else {
506
0
    mExpiration = 0.0;
507
0
  }
508
0
  mIsAnyMemberPresent = true;
509
0
510
0
  if (!isNull) {
511
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->family_id, temp.ptr())) {
512
0
      return false;
513
0
    }
514
0
  }
515
0
  if (!isNull && !temp->isUndefined()) {
516
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mFamily)) {
517
0
      return false;
518
0
    }
519
0
  } else {
520
0
    static const char16_t data[] = { 0 };
521
0
    mFamily.Rebind(data, ArrayLength(data) - 1);
522
0
  }
523
0
  mIsAnyMemberPresent = true;
524
0
525
0
  if (!isNull) {
526
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->hostaddr_id, temp.ptr())) {
527
0
      return false;
528
0
    }
529
0
  }
530
0
  if (!isNull && !temp->isUndefined()) {
531
0
    mHostaddr.Construct();
532
0
    if (temp.ref().isObject()) {
533
0
      JS::ForOfIterator iter(cx);
534
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
535
0
        return false;
536
0
      }
537
0
      if (!iter.valueIsIterable()) {
538
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'hostaddr' member of DnsCacheEntry");
539
0
        return false;
540
0
      }
541
0
      Sequence<nsString> &arr = (mHostaddr.Value());
542
0
      JS::Rooted<JS::Value> temp(cx);
543
0
      while (true) {
544
0
        bool done;
545
0
        if (!iter.next(&temp, &done)) {
546
0
          return false;
547
0
        }
548
0
        if (done) {
549
0
          break;
550
0
        }
551
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
552
0
        if (!slotPtr) {
553
0
          JS_ReportOutOfMemory(cx);
554
0
          return false;
555
0
        }
556
0
        nsString& slot = *slotPtr;
557
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
558
0
          return false;
559
0
        }
560
0
      }
561
0
    } else {
562
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'hostaddr' member of DnsCacheEntry");
563
0
      return false;
564
0
    }
565
0
    mIsAnyMemberPresent = true;
566
0
  }
567
0
568
0
  if (!isNull) {
569
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->hostname_id, temp.ptr())) {
570
0
      return false;
571
0
    }
572
0
  }
573
0
  if (!isNull && !temp->isUndefined()) {
574
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHostname)) {
575
0
      return false;
576
0
    }
577
0
  } else {
578
0
    static const char16_t data[] = { 0 };
579
0
    mHostname.Rebind(data, ArrayLength(data) - 1);
580
0
  }
581
0
  mIsAnyMemberPresent = true;
582
0
583
0
  if (!isNull) {
584
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->trr_id, temp.ptr())) {
585
0
      return false;
586
0
    }
587
0
  }
588
0
  if (!isNull && !temp->isUndefined()) {
589
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mTrr)) {
590
0
      return false;
591
0
    }
592
0
  } else {
593
0
    mTrr = false;
594
0
  }
595
0
  mIsAnyMemberPresent = true;
596
0
  return true;
597
0
}
598
599
bool
600
DnsCacheEntry::Init(const nsAString& aJSON)
601
0
{
602
0
  AutoJSAPI jsapi;
603
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
604
0
  if (!cleanGlobal) {
605
0
    return false;
606
0
  }
607
0
  if (!jsapi.Init(cleanGlobal)) {
608
0
    return false;
609
0
  }
610
0
  JSContext* cx = jsapi.cx();
611
0
  JS::Rooted<JS::Value> json(cx);
612
0
  bool ok = ParseJSON(cx, aJSON, &json);
613
0
  NS_ENSURE_TRUE(ok, false);
614
0
  return Init(cx, json);
615
0
}
616
617
bool
618
DnsCacheEntry::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
619
0
{
620
0
  DnsCacheEntryAtoms* atomsCache = GetAtomCache<DnsCacheEntryAtoms>(cx);
621
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
622
0
    return false;
623
0
  }
624
0
625
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
626
0
  if (!obj) {
627
0
    return false;
628
0
  }
629
0
  rval.set(JS::ObjectValue(*obj));
630
0
631
0
  do {
632
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
633
0
    JS::Rooted<JS::Value> temp(cx);
634
0
    double const & currentValue = mExpiration;
635
0
    temp.set(JS_NumberValue(double(currentValue)));
636
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->expiration_id, temp, JSPROP_ENUMERATE)) {
637
0
      return false;
638
0
    }
639
0
    break;
640
0
  } while(false);
641
0
642
0
  do {
643
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
644
0
    JS::Rooted<JS::Value> temp(cx);
645
0
    nsString const & currentValue = mFamily;
646
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
647
0
      return false;
648
0
    }
649
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->family_id, temp, JSPROP_ENUMERATE)) {
650
0
      return false;
651
0
    }
652
0
    break;
653
0
  } while(false);
654
0
655
0
  if (mHostaddr.WasPassed()) {
656
0
    do {
657
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
658
0
      JS::Rooted<JS::Value> temp(cx);
659
0
      Sequence<nsString> const & currentValue = mHostaddr.InternalValue();
660
0
661
0
      uint32_t length = currentValue.Length();
662
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
663
0
      if (!returnArray) {
664
0
        return false;
665
0
      }
666
0
      // Scope for 'tmp'
667
0
      {
668
0
        JS::Rooted<JS::Value> tmp(cx);
669
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
670
0
          // Control block to let us common up the JS_DefineElement calls when there
671
0
          // are different ways to succeed at wrapping the object.
672
0
          do {
673
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
674
0
              return false;
675
0
            }
676
0
            break;
677
0
          } while (false);
678
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
679
0
                                JSPROP_ENUMERATE)) {
680
0
            return false;
681
0
          }
682
0
        }
683
0
      }
684
0
      temp.setObject(*returnArray);
685
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->hostaddr_id, temp, JSPROP_ENUMERATE)) {
686
0
        return false;
687
0
      }
688
0
      break;
689
0
    } while(false);
690
0
  }
691
0
692
0
  do {
693
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
694
0
    JS::Rooted<JS::Value> temp(cx);
695
0
    nsString const & currentValue = mHostname;
696
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
697
0
      return false;
698
0
    }
699
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->hostname_id, temp, JSPROP_ENUMERATE)) {
700
0
      return false;
701
0
    }
702
0
    break;
703
0
  } while(false);
704
0
705
0
  do {
706
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
707
0
    JS::Rooted<JS::Value> temp(cx);
708
0
    bool const & currentValue = mTrr;
709
0
    temp.setBoolean(currentValue);
710
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->trr_id, temp, JSPROP_ENUMERATE)) {
711
0
      return false;
712
0
    }
713
0
    break;
714
0
  } while(false);
715
0
716
0
  return true;
717
0
}
718
719
bool
720
DnsCacheEntry::ToJSON(nsAString& aJSON) const
721
0
{
722
0
  AutoJSAPI jsapi;
723
0
  jsapi.Init();
724
0
  JSContext *cx = jsapi.cx();
725
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
726
0
  // because we'll only be creating objects, in ways that have no
727
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
728
0
  // which likewise guarantees no side-effects for the sorts of
729
0
  // things we will pass it.
730
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
731
0
  JS::Rooted<JS::Value> val(cx);
732
0
  if (!ToObjectInternal(cx, &val)) {
733
0
    return false;
734
0
  }
735
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
736
0
  return StringifyToJSON(cx, obj, aJSON);
737
0
}
738
739
void
740
DnsCacheEntry::TraceDictionary(JSTracer* trc)
741
0
{
742
0
}
743
744
DnsCacheEntry&
745
DnsCacheEntry::operator=(const DnsCacheEntry& aOther)
746
0
{
747
0
  DictionaryBase::operator=(aOther);
748
0
  mExpiration = aOther.mExpiration;
749
0
  mFamily = aOther.mFamily;
750
0
  mHostaddr.Reset();
751
0
  if (aOther.mHostaddr.WasPassed()) {
752
0
    mHostaddr.Construct(aOther.mHostaddr.Value());
753
0
  }
754
0
  mHostname = aOther.mHostname;
755
0
  mTrr = aOther.mTrr;
756
0
  return *this;
757
0
}
758
759
namespace binding_detail {
760
} // namespace binding_detail
761
762
763
764
HalfOpenInfoDict::HalfOpenInfoDict()
765
0
{
766
0
  // Safe to pass a null context if we pass a null value
767
0
  Init(nullptr, JS::NullHandleValue);
768
0
}
769
770
771
772
bool
773
HalfOpenInfoDict::InitIds(JSContext* cx, HalfOpenInfoDictAtoms* atomsCache)
774
0
{
775
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
776
0
777
0
  // Initialize these in reverse order so that any failure leaves the first one
778
0
  // uninitialized.
779
0
  if (!atomsCache->speculative_id.init(cx, "speculative")) {
780
0
    return false;
781
0
  }
782
0
  return true;
783
0
}
784
785
bool
786
HalfOpenInfoDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
787
0
{
788
0
  // Passing a null JSContext is OK only if we're initing from null,
789
0
  // Since in that case we will not have to do any property gets
790
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
791
0
  // checkers by static analysis tools
792
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
793
0
  HalfOpenInfoDictAtoms* atomsCache = nullptr;
794
0
  if (cx) {
795
0
    atomsCache = GetAtomCache<HalfOpenInfoDictAtoms>(cx);
796
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
797
0
      return false;
798
0
    }
799
0
  }
800
0
801
0
  if (!IsConvertibleToDictionary(val)) {
802
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
803
0
  }
804
0
805
0
  bool isNull = val.isNullOrUndefined();
806
0
  // We only need these if !isNull, in which case we have |cx|.
807
0
  Maybe<JS::Rooted<JSObject *> > object;
808
0
  Maybe<JS::Rooted<JS::Value> > temp;
809
0
  if (!isNull) {
810
0
    MOZ_ASSERT(cx);
811
0
    object.emplace(cx, &val.toObject());
812
0
    temp.emplace(cx);
813
0
  }
814
0
  if (!isNull) {
815
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->speculative_id, temp.ptr())) {
816
0
      return false;
817
0
    }
818
0
  }
819
0
  if (!isNull && !temp->isUndefined()) {
820
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mSpeculative)) {
821
0
      return false;
822
0
    }
823
0
  } else {
824
0
    mSpeculative = false;
825
0
  }
826
0
  mIsAnyMemberPresent = true;
827
0
  return true;
828
0
}
829
830
bool
831
HalfOpenInfoDict::Init(const nsAString& aJSON)
832
0
{
833
0
  AutoJSAPI jsapi;
834
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
835
0
  if (!cleanGlobal) {
836
0
    return false;
837
0
  }
838
0
  if (!jsapi.Init(cleanGlobal)) {
839
0
    return false;
840
0
  }
841
0
  JSContext* cx = jsapi.cx();
842
0
  JS::Rooted<JS::Value> json(cx);
843
0
  bool ok = ParseJSON(cx, aJSON, &json);
844
0
  NS_ENSURE_TRUE(ok, false);
845
0
  return Init(cx, json);
846
0
}
847
848
bool
849
HalfOpenInfoDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
850
0
{
851
0
  HalfOpenInfoDictAtoms* atomsCache = GetAtomCache<HalfOpenInfoDictAtoms>(cx);
852
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
853
0
    return false;
854
0
  }
855
0
856
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
857
0
  if (!obj) {
858
0
    return false;
859
0
  }
860
0
  rval.set(JS::ObjectValue(*obj));
861
0
862
0
  do {
863
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
864
0
    JS::Rooted<JS::Value> temp(cx);
865
0
    bool const & currentValue = mSpeculative;
866
0
    temp.setBoolean(currentValue);
867
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->speculative_id, temp, JSPROP_ENUMERATE)) {
868
0
      return false;
869
0
    }
870
0
    break;
871
0
  } while(false);
872
0
873
0
  return true;
874
0
}
875
876
bool
877
HalfOpenInfoDict::ToJSON(nsAString& aJSON) const
878
0
{
879
0
  AutoJSAPI jsapi;
880
0
  jsapi.Init();
881
0
  JSContext *cx = jsapi.cx();
882
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
883
0
  // because we'll only be creating objects, in ways that have no
884
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
885
0
  // which likewise guarantees no side-effects for the sorts of
886
0
  // things we will pass it.
887
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
888
0
  JS::Rooted<JS::Value> val(cx);
889
0
  if (!ToObjectInternal(cx, &val)) {
890
0
    return false;
891
0
  }
892
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
893
0
  return StringifyToJSON(cx, obj, aJSON);
894
0
}
895
896
void
897
HalfOpenInfoDict::TraceDictionary(JSTracer* trc)
898
0
{
899
0
}
900
901
HalfOpenInfoDict&
902
HalfOpenInfoDict::operator=(const HalfOpenInfoDict& aOther)
903
0
{
904
0
  DictionaryBase::operator=(aOther);
905
0
  mSpeculative = aOther.mSpeculative;
906
0
  return *this;
907
0
}
908
909
namespace binding_detail {
910
} // namespace binding_detail
911
912
913
914
HttpConnInfo::HttpConnInfo()
915
0
{
916
0
  // Safe to pass a null context if we pass a null value
917
0
  Init(nullptr, JS::NullHandleValue);
918
0
}
919
920
921
922
bool
923
HttpConnInfo::InitIds(JSContext* cx, HttpConnInfoAtoms* atomsCache)
924
0
{
925
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
926
0
927
0
  // Initialize these in reverse order so that any failure leaves the first one
928
0
  // uninitialized.
929
0
  if (!atomsCache->ttl_id.init(cx, "ttl") ||
930
0
      !atomsCache->rtt_id.init(cx, "rtt") ||
931
0
      !atomsCache->protocolVersion_id.init(cx, "protocolVersion")) {
932
0
    return false;
933
0
  }
934
0
  return true;
935
0
}
936
937
bool
938
HttpConnInfo::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
939
0
{
940
0
  // Passing a null JSContext is OK only if we're initing from null,
941
0
  // Since in that case we will not have to do any property gets
942
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
943
0
  // checkers by static analysis tools
944
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
945
0
  HttpConnInfoAtoms* atomsCache = nullptr;
946
0
  if (cx) {
947
0
    atomsCache = GetAtomCache<HttpConnInfoAtoms>(cx);
948
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
949
0
      return false;
950
0
    }
951
0
  }
952
0
953
0
  if (!IsConvertibleToDictionary(val)) {
954
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
955
0
  }
956
0
957
0
  bool isNull = val.isNullOrUndefined();
958
0
  // We only need these if !isNull, in which case we have |cx|.
959
0
  Maybe<JS::Rooted<JSObject *> > object;
960
0
  Maybe<JS::Rooted<JS::Value> > temp;
961
0
  if (!isNull) {
962
0
    MOZ_ASSERT(cx);
963
0
    object.emplace(cx, &val.toObject());
964
0
    temp.emplace(cx);
965
0
  }
966
0
  if (!isNull) {
967
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->protocolVersion_id, temp.ptr())) {
968
0
      return false;
969
0
    }
970
0
  }
971
0
  if (!isNull && !temp->isUndefined()) {
972
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mProtocolVersion)) {
973
0
      return false;
974
0
    }
975
0
  } else {
976
0
    static const char16_t data[] = { 0 };
977
0
    mProtocolVersion.Rebind(data, ArrayLength(data) - 1);
978
0
  }
979
0
  mIsAnyMemberPresent = true;
980
0
981
0
  if (!isNull) {
982
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rtt_id, temp.ptr())) {
983
0
      return false;
984
0
    }
985
0
  }
986
0
  if (!isNull && !temp->isUndefined()) {
987
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mRtt)) {
988
0
      return false;
989
0
    }
990
0
  } else {
991
0
    mRtt = 0U;
992
0
  }
993
0
  mIsAnyMemberPresent = true;
994
0
995
0
  if (!isNull) {
996
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->ttl_id, temp.ptr())) {
997
0
      return false;
998
0
    }
999
0
  }
1000
0
  if (!isNull && !temp->isUndefined()) {
1001
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mTtl)) {
1002
0
      return false;
1003
0
    }
1004
0
  } else {
1005
0
    mTtl = 0U;
1006
0
  }
1007
0
  mIsAnyMemberPresent = true;
1008
0
  return true;
1009
0
}
1010
1011
bool
1012
HttpConnInfo::Init(const nsAString& aJSON)
1013
0
{
1014
0
  AutoJSAPI jsapi;
1015
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1016
0
  if (!cleanGlobal) {
1017
0
    return false;
1018
0
  }
1019
0
  if (!jsapi.Init(cleanGlobal)) {
1020
0
    return false;
1021
0
  }
1022
0
  JSContext* cx = jsapi.cx();
1023
0
  JS::Rooted<JS::Value> json(cx);
1024
0
  bool ok = ParseJSON(cx, aJSON, &json);
1025
0
  NS_ENSURE_TRUE(ok, false);
1026
0
  return Init(cx, json);
1027
0
}
1028
1029
bool
1030
HttpConnInfo::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1031
0
{
1032
0
  HttpConnInfoAtoms* atomsCache = GetAtomCache<HttpConnInfoAtoms>(cx);
1033
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1034
0
    return false;
1035
0
  }
1036
0
1037
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1038
0
  if (!obj) {
1039
0
    return false;
1040
0
  }
1041
0
  rval.set(JS::ObjectValue(*obj));
1042
0
1043
0
  do {
1044
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1045
0
    JS::Rooted<JS::Value> temp(cx);
1046
0
    nsString const & currentValue = mProtocolVersion;
1047
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1048
0
      return false;
1049
0
    }
1050
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->protocolVersion_id, temp, JSPROP_ENUMERATE)) {
1051
0
      return false;
1052
0
    }
1053
0
    break;
1054
0
  } while(false);
1055
0
1056
0
  do {
1057
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1058
0
    JS::Rooted<JS::Value> temp(cx);
1059
0
    uint32_t const & currentValue = mRtt;
1060
0
    temp.setNumber(currentValue);
1061
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->rtt_id, temp, JSPROP_ENUMERATE)) {
1062
0
      return false;
1063
0
    }
1064
0
    break;
1065
0
  } while(false);
1066
0
1067
0
  do {
1068
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1069
0
    JS::Rooted<JS::Value> temp(cx);
1070
0
    uint32_t const & currentValue = mTtl;
1071
0
    temp.setNumber(currentValue);
1072
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->ttl_id, temp, JSPROP_ENUMERATE)) {
1073
0
      return false;
1074
0
    }
1075
0
    break;
1076
0
  } while(false);
1077
0
1078
0
  return true;
1079
0
}
1080
1081
bool
1082
HttpConnInfo::ToJSON(nsAString& aJSON) const
1083
0
{
1084
0
  AutoJSAPI jsapi;
1085
0
  jsapi.Init();
1086
0
  JSContext *cx = jsapi.cx();
1087
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1088
0
  // because we'll only be creating objects, in ways that have no
1089
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1090
0
  // which likewise guarantees no side-effects for the sorts of
1091
0
  // things we will pass it.
1092
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1093
0
  JS::Rooted<JS::Value> val(cx);
1094
0
  if (!ToObjectInternal(cx, &val)) {
1095
0
    return false;
1096
0
  }
1097
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1098
0
  return StringifyToJSON(cx, obj, aJSON);
1099
0
}
1100
1101
void
1102
HttpConnInfo::TraceDictionary(JSTracer* trc)
1103
0
{
1104
0
}
1105
1106
HttpConnInfo&
1107
HttpConnInfo::operator=(const HttpConnInfo& aOther)
1108
0
{
1109
0
  DictionaryBase::operator=(aOther);
1110
0
  mProtocolVersion = aOther.mProtocolVersion;
1111
0
  mRtt = aOther.mRtt;
1112
0
  mTtl = aOther.mTtl;
1113
0
  return *this;
1114
0
}
1115
1116
namespace binding_detail {
1117
} // namespace binding_detail
1118
1119
1120
1121
RcwnPerfStats::RcwnPerfStats()
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
RcwnPerfStats::InitIds(JSContext* cx, RcwnPerfStatsAtoms* 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->stddevLong_id.init(cx, "stddevLong") ||
1137
0
      !atomsCache->avgShort_id.init(cx, "avgShort") ||
1138
0
      !atomsCache->avgLong_id.init(cx, "avgLong")) {
1139
0
    return false;
1140
0
  }
1141
0
  return true;
1142
0
}
1143
1144
bool
1145
RcwnPerfStats::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1146
0
{
1147
0
  // Passing a null JSContext is OK only if we're initing from null,
1148
0
  // Since in that case we will not have to do any property gets
1149
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1150
0
  // checkers by static analysis tools
1151
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1152
0
  RcwnPerfStatsAtoms* atomsCache = nullptr;
1153
0
  if (cx) {
1154
0
    atomsCache = GetAtomCache<RcwnPerfStatsAtoms>(cx);
1155
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1156
0
      return false;
1157
0
    }
1158
0
  }
1159
0
1160
0
  if (!IsConvertibleToDictionary(val)) {
1161
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1162
0
  }
1163
0
1164
0
  bool isNull = val.isNullOrUndefined();
1165
0
  // We only need these if !isNull, in which case we have |cx|.
1166
0
  Maybe<JS::Rooted<JSObject *> > object;
1167
0
  Maybe<JS::Rooted<JS::Value> > temp;
1168
0
  if (!isNull) {
1169
0
    MOZ_ASSERT(cx);
1170
0
    object.emplace(cx, &val.toObject());
1171
0
    temp.emplace(cx);
1172
0
  }
1173
0
  if (!isNull) {
1174
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->avgLong_id, temp.ptr())) {
1175
0
      return false;
1176
0
    }
1177
0
  }
1178
0
  if (!isNull && !temp->isUndefined()) {
1179
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mAvgLong)) {
1180
0
      return false;
1181
0
    }
1182
0
  } else {
1183
0
    mAvgLong = 0U;
1184
0
  }
1185
0
  mIsAnyMemberPresent = true;
1186
0
1187
0
  if (!isNull) {
1188
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->avgShort_id, temp.ptr())) {
1189
0
      return false;
1190
0
    }
1191
0
  }
1192
0
  if (!isNull && !temp->isUndefined()) {
1193
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mAvgShort)) {
1194
0
      return false;
1195
0
    }
1196
0
  } else {
1197
0
    mAvgShort = 0U;
1198
0
  }
1199
0
  mIsAnyMemberPresent = true;
1200
0
1201
0
  if (!isNull) {
1202
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->stddevLong_id, temp.ptr())) {
1203
0
      return false;
1204
0
    }
1205
0
  }
1206
0
  if (!isNull && !temp->isUndefined()) {
1207
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mStddevLong)) {
1208
0
      return false;
1209
0
    }
1210
0
  } else {
1211
0
    mStddevLong = 0U;
1212
0
  }
1213
0
  mIsAnyMemberPresent = true;
1214
0
  return true;
1215
0
}
1216
1217
bool
1218
RcwnPerfStats::Init(const nsAString& aJSON)
1219
0
{
1220
0
  AutoJSAPI jsapi;
1221
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1222
0
  if (!cleanGlobal) {
1223
0
    return false;
1224
0
  }
1225
0
  if (!jsapi.Init(cleanGlobal)) {
1226
0
    return false;
1227
0
  }
1228
0
  JSContext* cx = jsapi.cx();
1229
0
  JS::Rooted<JS::Value> json(cx);
1230
0
  bool ok = ParseJSON(cx, aJSON, &json);
1231
0
  NS_ENSURE_TRUE(ok, false);
1232
0
  return Init(cx, json);
1233
0
}
1234
1235
bool
1236
RcwnPerfStats::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1237
0
{
1238
0
  RcwnPerfStatsAtoms* atomsCache = GetAtomCache<RcwnPerfStatsAtoms>(cx);
1239
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1240
0
    return false;
1241
0
  }
1242
0
1243
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1244
0
  if (!obj) {
1245
0
    return false;
1246
0
  }
1247
0
  rval.set(JS::ObjectValue(*obj));
1248
0
1249
0
  do {
1250
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1251
0
    JS::Rooted<JS::Value> temp(cx);
1252
0
    uint32_t const & currentValue = mAvgLong;
1253
0
    temp.setNumber(currentValue);
1254
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->avgLong_id, temp, JSPROP_ENUMERATE)) {
1255
0
      return false;
1256
0
    }
1257
0
    break;
1258
0
  } while(false);
1259
0
1260
0
  do {
1261
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1262
0
    JS::Rooted<JS::Value> temp(cx);
1263
0
    uint32_t const & currentValue = mAvgShort;
1264
0
    temp.setNumber(currentValue);
1265
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->avgShort_id, temp, JSPROP_ENUMERATE)) {
1266
0
      return false;
1267
0
    }
1268
0
    break;
1269
0
  } while(false);
1270
0
1271
0
  do {
1272
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1273
0
    JS::Rooted<JS::Value> temp(cx);
1274
0
    uint32_t const & currentValue = mStddevLong;
1275
0
    temp.setNumber(currentValue);
1276
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->stddevLong_id, temp, JSPROP_ENUMERATE)) {
1277
0
      return false;
1278
0
    }
1279
0
    break;
1280
0
  } while(false);
1281
0
1282
0
  return true;
1283
0
}
1284
1285
bool
1286
RcwnPerfStats::ToJSON(nsAString& aJSON) const
1287
0
{
1288
0
  AutoJSAPI jsapi;
1289
0
  jsapi.Init();
1290
0
  JSContext *cx = jsapi.cx();
1291
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1292
0
  // because we'll only be creating objects, in ways that have no
1293
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1294
0
  // which likewise guarantees no side-effects for the sorts of
1295
0
  // things we will pass it.
1296
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1297
0
  JS::Rooted<JS::Value> val(cx);
1298
0
  if (!ToObjectInternal(cx, &val)) {
1299
0
    return false;
1300
0
  }
1301
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1302
0
  return StringifyToJSON(cx, obj, aJSON);
1303
0
}
1304
1305
void
1306
RcwnPerfStats::TraceDictionary(JSTracer* trc)
1307
0
{
1308
0
}
1309
1310
RcwnPerfStats&
1311
RcwnPerfStats::operator=(const RcwnPerfStats& aOther)
1312
0
{
1313
0
  DictionaryBase::operator=(aOther);
1314
0
  mAvgLong = aOther.mAvgLong;
1315
0
  mAvgShort = aOther.mAvgShort;
1316
0
  mStddevLong = aOther.mStddevLong;
1317
0
  return *this;
1318
0
}
1319
1320
namespace binding_detail {
1321
} // namespace binding_detail
1322
1323
1324
1325
SocketElement::SocketElement()
1326
0
{
1327
0
  // Safe to pass a null context if we pass a null value
1328
0
  Init(nullptr, JS::NullHandleValue);
1329
0
}
1330
1331
1332
1333
bool
1334
SocketElement::InitIds(JSContext* cx, SocketElementAtoms* atomsCache)
1335
0
{
1336
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1337
0
1338
0
  // Initialize these in reverse order so that any failure leaves the first one
1339
0
  // uninitialized.
1340
0
  if (!atomsCache->tcp_id.init(cx, "tcp") ||
1341
0
      !atomsCache->sent_id.init(cx, "sent") ||
1342
0
      !atomsCache->received_id.init(cx, "received") ||
1343
0
      !atomsCache->port_id.init(cx, "port") ||
1344
0
      !atomsCache->host_id.init(cx, "host") ||
1345
0
      !atomsCache->active_id.init(cx, "active")) {
1346
0
    return false;
1347
0
  }
1348
0
  return true;
1349
0
}
1350
1351
bool
1352
SocketElement::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1353
0
{
1354
0
  // Passing a null JSContext is OK only if we're initing from null,
1355
0
  // Since in that case we will not have to do any property gets
1356
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1357
0
  // checkers by static analysis tools
1358
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1359
0
  SocketElementAtoms* atomsCache = nullptr;
1360
0
  if (cx) {
1361
0
    atomsCache = GetAtomCache<SocketElementAtoms>(cx);
1362
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1363
0
      return false;
1364
0
    }
1365
0
  }
1366
0
1367
0
  if (!IsConvertibleToDictionary(val)) {
1368
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1369
0
  }
1370
0
1371
0
  bool isNull = val.isNullOrUndefined();
1372
0
  // We only need these if !isNull, in which case we have |cx|.
1373
0
  Maybe<JS::Rooted<JSObject *> > object;
1374
0
  Maybe<JS::Rooted<JS::Value> > temp;
1375
0
  if (!isNull) {
1376
0
    MOZ_ASSERT(cx);
1377
0
    object.emplace(cx, &val.toObject());
1378
0
    temp.emplace(cx);
1379
0
  }
1380
0
  if (!isNull) {
1381
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->active_id, temp.ptr())) {
1382
0
      return false;
1383
0
    }
1384
0
  }
1385
0
  if (!isNull && !temp->isUndefined()) {
1386
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mActive)) {
1387
0
      return false;
1388
0
    }
1389
0
  } else {
1390
0
    mActive = false;
1391
0
  }
1392
0
  mIsAnyMemberPresent = true;
1393
0
1394
0
  if (!isNull) {
1395
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->host_id, temp.ptr())) {
1396
0
      return false;
1397
0
    }
1398
0
  }
1399
0
  if (!isNull && !temp->isUndefined()) {
1400
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHost)) {
1401
0
      return false;
1402
0
    }
1403
0
  } else {
1404
0
    static const char16_t data[] = { 0 };
1405
0
    mHost.Rebind(data, ArrayLength(data) - 1);
1406
0
  }
1407
0
  mIsAnyMemberPresent = true;
1408
0
1409
0
  if (!isNull) {
1410
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->port_id, temp.ptr())) {
1411
0
      return false;
1412
0
    }
1413
0
  }
1414
0
  if (!isNull && !temp->isUndefined()) {
1415
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mPort)) {
1416
0
      return false;
1417
0
    }
1418
0
  } else {
1419
0
    mPort = 0U;
1420
0
  }
1421
0
  mIsAnyMemberPresent = true;
1422
0
1423
0
  if (!isNull) {
1424
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->received_id, temp.ptr())) {
1425
0
      return false;
1426
0
    }
1427
0
  }
1428
0
  if (!isNull && !temp->isUndefined()) {
1429
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mReceived)) {
1430
0
      return false;
1431
0
    } else if (!mozilla::IsFinite(mReceived)) {
1432
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'received' member of SocketElement");
1433
0
      return false;
1434
0
    }
1435
0
  } else {
1436
0
    mReceived = 0.0;
1437
0
  }
1438
0
  mIsAnyMemberPresent = true;
1439
0
1440
0
  if (!isNull) {
1441
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->sent_id, temp.ptr())) {
1442
0
      return false;
1443
0
    }
1444
0
  }
1445
0
  if (!isNull && !temp->isUndefined()) {
1446
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mSent)) {
1447
0
      return false;
1448
0
    } else if (!mozilla::IsFinite(mSent)) {
1449
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'sent' member of SocketElement");
1450
0
      return false;
1451
0
    }
1452
0
  } else {
1453
0
    mSent = 0.0;
1454
0
  }
1455
0
  mIsAnyMemberPresent = true;
1456
0
1457
0
  if (!isNull) {
1458
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->tcp_id, temp.ptr())) {
1459
0
      return false;
1460
0
    }
1461
0
  }
1462
0
  if (!isNull && !temp->isUndefined()) {
1463
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mTcp)) {
1464
0
      return false;
1465
0
    }
1466
0
  } else {
1467
0
    mTcp = false;
1468
0
  }
1469
0
  mIsAnyMemberPresent = true;
1470
0
  return true;
1471
0
}
1472
1473
bool
1474
SocketElement::Init(const nsAString& aJSON)
1475
0
{
1476
0
  AutoJSAPI jsapi;
1477
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1478
0
  if (!cleanGlobal) {
1479
0
    return false;
1480
0
  }
1481
0
  if (!jsapi.Init(cleanGlobal)) {
1482
0
    return false;
1483
0
  }
1484
0
  JSContext* cx = jsapi.cx();
1485
0
  JS::Rooted<JS::Value> json(cx);
1486
0
  bool ok = ParseJSON(cx, aJSON, &json);
1487
0
  NS_ENSURE_TRUE(ok, false);
1488
0
  return Init(cx, json);
1489
0
}
1490
1491
bool
1492
SocketElement::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1493
0
{
1494
0
  SocketElementAtoms* atomsCache = GetAtomCache<SocketElementAtoms>(cx);
1495
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1496
0
    return false;
1497
0
  }
1498
0
1499
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1500
0
  if (!obj) {
1501
0
    return false;
1502
0
  }
1503
0
  rval.set(JS::ObjectValue(*obj));
1504
0
1505
0
  do {
1506
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1507
0
    JS::Rooted<JS::Value> temp(cx);
1508
0
    bool const & currentValue = mActive;
1509
0
    temp.setBoolean(currentValue);
1510
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->active_id, temp, JSPROP_ENUMERATE)) {
1511
0
      return false;
1512
0
    }
1513
0
    break;
1514
0
  } while(false);
1515
0
1516
0
  do {
1517
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1518
0
    JS::Rooted<JS::Value> temp(cx);
1519
0
    nsString const & currentValue = mHost;
1520
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1521
0
      return false;
1522
0
    }
1523
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->host_id, temp, JSPROP_ENUMERATE)) {
1524
0
      return false;
1525
0
    }
1526
0
    break;
1527
0
  } while(false);
1528
0
1529
0
  do {
1530
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1531
0
    JS::Rooted<JS::Value> temp(cx);
1532
0
    uint32_t const & currentValue = mPort;
1533
0
    temp.setNumber(currentValue);
1534
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->port_id, temp, JSPROP_ENUMERATE)) {
1535
0
      return false;
1536
0
    }
1537
0
    break;
1538
0
  } while(false);
1539
0
1540
0
  do {
1541
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1542
0
    JS::Rooted<JS::Value> temp(cx);
1543
0
    double const & currentValue = mReceived;
1544
0
    temp.set(JS_NumberValue(double(currentValue)));
1545
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->received_id, temp, JSPROP_ENUMERATE)) {
1546
0
      return false;
1547
0
    }
1548
0
    break;
1549
0
  } while(false);
1550
0
1551
0
  do {
1552
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1553
0
    JS::Rooted<JS::Value> temp(cx);
1554
0
    double const & currentValue = mSent;
1555
0
    temp.set(JS_NumberValue(double(currentValue)));
1556
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->sent_id, temp, JSPROP_ENUMERATE)) {
1557
0
      return false;
1558
0
    }
1559
0
    break;
1560
0
  } while(false);
1561
0
1562
0
  do {
1563
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1564
0
    JS::Rooted<JS::Value> temp(cx);
1565
0
    bool const & currentValue = mTcp;
1566
0
    temp.setBoolean(currentValue);
1567
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->tcp_id, temp, JSPROP_ENUMERATE)) {
1568
0
      return false;
1569
0
    }
1570
0
    break;
1571
0
  } while(false);
1572
0
1573
0
  return true;
1574
0
}
1575
1576
bool
1577
SocketElement::ToJSON(nsAString& aJSON) const
1578
0
{
1579
0
  AutoJSAPI jsapi;
1580
0
  jsapi.Init();
1581
0
  JSContext *cx = jsapi.cx();
1582
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1583
0
  // because we'll only be creating objects, in ways that have no
1584
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1585
0
  // which likewise guarantees no side-effects for the sorts of
1586
0
  // things we will pass it.
1587
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1588
0
  JS::Rooted<JS::Value> val(cx);
1589
0
  if (!ToObjectInternal(cx, &val)) {
1590
0
    return false;
1591
0
  }
1592
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1593
0
  return StringifyToJSON(cx, obj, aJSON);
1594
0
}
1595
1596
void
1597
SocketElement::TraceDictionary(JSTracer* trc)
1598
0
{
1599
0
}
1600
1601
SocketElement&
1602
SocketElement::operator=(const SocketElement& aOther)
1603
0
{
1604
0
  DictionaryBase::operator=(aOther);
1605
0
  mActive = aOther.mActive;
1606
0
  mHost = aOther.mHost;
1607
0
  mPort = aOther.mPort;
1608
0
  mReceived = aOther.mReceived;
1609
0
  mSent = aOther.mSent;
1610
0
  mTcp = aOther.mTcp;
1611
0
  return *this;
1612
0
}
1613
1614
namespace binding_detail {
1615
} // namespace binding_detail
1616
1617
1618
1619
WebSocketElement::WebSocketElement()
1620
0
{
1621
0
  // Safe to pass a null context if we pass a null value
1622
0
  Init(nullptr, JS::NullHandleValue);
1623
0
}
1624
1625
1626
1627
bool
1628
WebSocketElement::InitIds(JSContext* cx, WebSocketElementAtoms* atomsCache)
1629
0
{
1630
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1631
0
1632
0
  // Initialize these in reverse order so that any failure leaves the first one
1633
0
  // uninitialized.
1634
0
  if (!atomsCache->sentsize_id.init(cx, "sentsize") ||
1635
0
      !atomsCache->receivedsize_id.init(cx, "receivedsize") ||
1636
0
      !atomsCache->msgsent_id.init(cx, "msgsent") ||
1637
0
      !atomsCache->msgreceived_id.init(cx, "msgreceived") ||
1638
0
      !atomsCache->hostport_id.init(cx, "hostport") ||
1639
0
      !atomsCache->encrypted_id.init(cx, "encrypted")) {
1640
0
    return false;
1641
0
  }
1642
0
  return true;
1643
0
}
1644
1645
bool
1646
WebSocketElement::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1647
0
{
1648
0
  // Passing a null JSContext is OK only if we're initing from null,
1649
0
  // Since in that case we will not have to do any property gets
1650
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1651
0
  // checkers by static analysis tools
1652
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1653
0
  WebSocketElementAtoms* atomsCache = nullptr;
1654
0
  if (cx) {
1655
0
    atomsCache = GetAtomCache<WebSocketElementAtoms>(cx);
1656
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1657
0
      return false;
1658
0
    }
1659
0
  }
1660
0
1661
0
  if (!IsConvertibleToDictionary(val)) {
1662
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1663
0
  }
1664
0
1665
0
  bool isNull = val.isNullOrUndefined();
1666
0
  // We only need these if !isNull, in which case we have |cx|.
1667
0
  Maybe<JS::Rooted<JSObject *> > object;
1668
0
  Maybe<JS::Rooted<JS::Value> > temp;
1669
0
  if (!isNull) {
1670
0
    MOZ_ASSERT(cx);
1671
0
    object.emplace(cx, &val.toObject());
1672
0
    temp.emplace(cx);
1673
0
  }
1674
0
  if (!isNull) {
1675
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->encrypted_id, temp.ptr())) {
1676
0
      return false;
1677
0
    }
1678
0
  }
1679
0
  if (!isNull && !temp->isUndefined()) {
1680
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mEncrypted)) {
1681
0
      return false;
1682
0
    }
1683
0
  } else {
1684
0
    mEncrypted = false;
1685
0
  }
1686
0
  mIsAnyMemberPresent = true;
1687
0
1688
0
  if (!isNull) {
1689
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->hostport_id, temp.ptr())) {
1690
0
      return false;
1691
0
    }
1692
0
  }
1693
0
  if (!isNull && !temp->isUndefined()) {
1694
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHostport)) {
1695
0
      return false;
1696
0
    }
1697
0
  } else {
1698
0
    static const char16_t data[] = { 0 };
1699
0
    mHostport.Rebind(data, ArrayLength(data) - 1);
1700
0
  }
1701
0
  mIsAnyMemberPresent = true;
1702
0
1703
0
  if (!isNull) {
1704
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->msgreceived_id, temp.ptr())) {
1705
0
      return false;
1706
0
    }
1707
0
  }
1708
0
  if (!isNull && !temp->isUndefined()) {
1709
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mMsgreceived)) {
1710
0
      return false;
1711
0
    }
1712
0
  } else {
1713
0
    mMsgreceived = 0U;
1714
0
  }
1715
0
  mIsAnyMemberPresent = true;
1716
0
1717
0
  if (!isNull) {
1718
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->msgsent_id, temp.ptr())) {
1719
0
      return false;
1720
0
    }
1721
0
  }
1722
0
  if (!isNull && !temp->isUndefined()) {
1723
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mMsgsent)) {
1724
0
      return false;
1725
0
    }
1726
0
  } else {
1727
0
    mMsgsent = 0U;
1728
0
  }
1729
0
  mIsAnyMemberPresent = true;
1730
0
1731
0
  if (!isNull) {
1732
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->receivedsize_id, temp.ptr())) {
1733
0
      return false;
1734
0
    }
1735
0
  }
1736
0
  if (!isNull && !temp->isUndefined()) {
1737
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mReceivedsize)) {
1738
0
      return false;
1739
0
    } else if (!mozilla::IsFinite(mReceivedsize)) {
1740
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'receivedsize' member of WebSocketElement");
1741
0
      return false;
1742
0
    }
1743
0
  } else {
1744
0
    mReceivedsize = 0.0;
1745
0
  }
1746
0
  mIsAnyMemberPresent = true;
1747
0
1748
0
  if (!isNull) {
1749
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->sentsize_id, temp.ptr())) {
1750
0
      return false;
1751
0
    }
1752
0
  }
1753
0
  if (!isNull && !temp->isUndefined()) {
1754
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mSentsize)) {
1755
0
      return false;
1756
0
    } else if (!mozilla::IsFinite(mSentsize)) {
1757
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'sentsize' member of WebSocketElement");
1758
0
      return false;
1759
0
    }
1760
0
  } else {
1761
0
    mSentsize = 0.0;
1762
0
  }
1763
0
  mIsAnyMemberPresent = true;
1764
0
  return true;
1765
0
}
1766
1767
bool
1768
WebSocketElement::Init(const nsAString& aJSON)
1769
0
{
1770
0
  AutoJSAPI jsapi;
1771
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
1772
0
  if (!cleanGlobal) {
1773
0
    return false;
1774
0
  }
1775
0
  if (!jsapi.Init(cleanGlobal)) {
1776
0
    return false;
1777
0
  }
1778
0
  JSContext* cx = jsapi.cx();
1779
0
  JS::Rooted<JS::Value> json(cx);
1780
0
  bool ok = ParseJSON(cx, aJSON, &json);
1781
0
  NS_ENSURE_TRUE(ok, false);
1782
0
  return Init(cx, json);
1783
0
}
1784
1785
bool
1786
WebSocketElement::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
1787
0
{
1788
0
  WebSocketElementAtoms* atomsCache = GetAtomCache<WebSocketElementAtoms>(cx);
1789
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1790
0
    return false;
1791
0
  }
1792
0
1793
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
1794
0
  if (!obj) {
1795
0
    return false;
1796
0
  }
1797
0
  rval.set(JS::ObjectValue(*obj));
1798
0
1799
0
  do {
1800
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1801
0
    JS::Rooted<JS::Value> temp(cx);
1802
0
    bool const & currentValue = mEncrypted;
1803
0
    temp.setBoolean(currentValue);
1804
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->encrypted_id, temp, JSPROP_ENUMERATE)) {
1805
0
      return false;
1806
0
    }
1807
0
    break;
1808
0
  } while(false);
1809
0
1810
0
  do {
1811
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1812
0
    JS::Rooted<JS::Value> temp(cx);
1813
0
    nsString const & currentValue = mHostport;
1814
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
1815
0
      return false;
1816
0
    }
1817
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->hostport_id, temp, JSPROP_ENUMERATE)) {
1818
0
      return false;
1819
0
    }
1820
0
    break;
1821
0
  } while(false);
1822
0
1823
0
  do {
1824
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1825
0
    JS::Rooted<JS::Value> temp(cx);
1826
0
    uint32_t const & currentValue = mMsgreceived;
1827
0
    temp.setNumber(currentValue);
1828
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->msgreceived_id, temp, JSPROP_ENUMERATE)) {
1829
0
      return false;
1830
0
    }
1831
0
    break;
1832
0
  } while(false);
1833
0
1834
0
  do {
1835
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1836
0
    JS::Rooted<JS::Value> temp(cx);
1837
0
    uint32_t const & currentValue = mMsgsent;
1838
0
    temp.setNumber(currentValue);
1839
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->msgsent_id, temp, JSPROP_ENUMERATE)) {
1840
0
      return false;
1841
0
    }
1842
0
    break;
1843
0
  } while(false);
1844
0
1845
0
  do {
1846
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1847
0
    JS::Rooted<JS::Value> temp(cx);
1848
0
    double const & currentValue = mReceivedsize;
1849
0
    temp.set(JS_NumberValue(double(currentValue)));
1850
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->receivedsize_id, temp, JSPROP_ENUMERATE)) {
1851
0
      return false;
1852
0
    }
1853
0
    break;
1854
0
  } while(false);
1855
0
1856
0
  do {
1857
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
1858
0
    JS::Rooted<JS::Value> temp(cx);
1859
0
    double const & currentValue = mSentsize;
1860
0
    temp.set(JS_NumberValue(double(currentValue)));
1861
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->sentsize_id, temp, JSPROP_ENUMERATE)) {
1862
0
      return false;
1863
0
    }
1864
0
    break;
1865
0
  } while(false);
1866
0
1867
0
  return true;
1868
0
}
1869
1870
bool
1871
WebSocketElement::ToJSON(nsAString& aJSON) const
1872
0
{
1873
0
  AutoJSAPI jsapi;
1874
0
  jsapi.Init();
1875
0
  JSContext *cx = jsapi.cx();
1876
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
1877
0
  // because we'll only be creating objects, in ways that have no
1878
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
1879
0
  // which likewise guarantees no side-effects for the sorts of
1880
0
  // things we will pass it.
1881
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
1882
0
  JS::Rooted<JS::Value> val(cx);
1883
0
  if (!ToObjectInternal(cx, &val)) {
1884
0
    return false;
1885
0
  }
1886
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
1887
0
  return StringifyToJSON(cx, obj, aJSON);
1888
0
}
1889
1890
void
1891
WebSocketElement::TraceDictionary(JSTracer* trc)
1892
0
{
1893
0
}
1894
1895
WebSocketElement&
1896
WebSocketElement::operator=(const WebSocketElement& aOther)
1897
0
{
1898
0
  DictionaryBase::operator=(aOther);
1899
0
  mEncrypted = aOther.mEncrypted;
1900
0
  mHostport = aOther.mHostport;
1901
0
  mMsgreceived = aOther.mMsgreceived;
1902
0
  mMsgsent = aOther.mMsgsent;
1903
0
  mReceivedsize = aOther.mReceivedsize;
1904
0
  mSentsize = aOther.mSentsize;
1905
0
  return *this;
1906
0
}
1907
1908
namespace binding_detail {
1909
} // namespace binding_detail
1910
1911
1912
1913
DNSCacheDict::DNSCacheDict()
1914
0
{
1915
0
  // Safe to pass a null context if we pass a null value
1916
0
  Init(nullptr, JS::NullHandleValue);
1917
0
}
1918
1919
1920
1921
bool
1922
DNSCacheDict::InitIds(JSContext* cx, DNSCacheDictAtoms* atomsCache)
1923
0
{
1924
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
1925
0
1926
0
  // Initialize these in reverse order so that any failure leaves the first one
1927
0
  // uninitialized.
1928
0
  if (!atomsCache->entries_id.init(cx, "entries")) {
1929
0
    return false;
1930
0
  }
1931
0
  return true;
1932
0
}
1933
1934
bool
1935
DNSCacheDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
1936
0
{
1937
0
  // Passing a null JSContext is OK only if we're initing from null,
1938
0
  // Since in that case we will not have to do any property gets
1939
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
1940
0
  // checkers by static analysis tools
1941
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
1942
0
  DNSCacheDictAtoms* atomsCache = nullptr;
1943
0
  if (cx) {
1944
0
    atomsCache = GetAtomCache<DNSCacheDictAtoms>(cx);
1945
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
1946
0
      return false;
1947
0
    }
1948
0
  }
1949
0
1950
0
  if (!IsConvertibleToDictionary(val)) {
1951
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
1952
0
  }
1953
0
1954
0
  bool isNull = val.isNullOrUndefined();
1955
0
  // We only need these if !isNull, in which case we have |cx|.
1956
0
  Maybe<JS::Rooted<JSObject *> > object;
1957
0
  Maybe<JS::Rooted<JS::Value> > temp;
1958
0
  if (!isNull) {
1959
0
    MOZ_ASSERT(cx);
1960
0
    object.emplace(cx, &val.toObject());
1961
0
    temp.emplace(cx);
1962
0
  }
1963
0
  if (!isNull) {
1964
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->entries_id, temp.ptr())) {
1965
0
      return false;
1966
0
    }
1967
0
  }
1968
0
  if (!isNull && !temp->isUndefined()) {
1969
0
    mEntries.Construct();
1970
0
    if (temp.ref().isObject()) {
1971
0
      JS::ForOfIterator iter(cx);
1972
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
1973
0
        return false;
1974
0
      }
1975
0
      if (!iter.valueIsIterable()) {
1976
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'entries' member of DNSCacheDict");
1977
0
        return false;
1978
0
      }
1979
0
      Sequence<DnsCacheEntry> &arr = (mEntries.Value());
1980
0
      JS::Rooted<JS::Value> temp(cx);
1981
0
      while (true) {
1982
0
        bool done;
1983
0
        if (!iter.next(&temp, &done)) {
1984
0
          return false;
1985
0
        }
1986
0
        if (done) {
1987
0
          break;
1988
0
        }
1989
0
        DnsCacheEntry* slotPtr = arr.AppendElement(mozilla::fallible);
1990
0
        if (!slotPtr) {
1991
0
          JS_ReportOutOfMemory(cx);
1992
0
          return false;
1993
0
        }
1994
0
        DnsCacheEntry& slot = *slotPtr;
1995
0
        if (!slot.Init(cx, temp,  "Element of 'entries' member of DNSCacheDict", passedToJSImpl)) {
1996
0
          return false;
1997
0
        }
1998
0
      }
1999
0
    } else {
2000
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'entries' member of DNSCacheDict");
2001
0
      return false;
2002
0
    }
2003
0
    mIsAnyMemberPresent = true;
2004
0
  }
2005
0
  return true;
2006
0
}
2007
2008
bool
2009
DNSCacheDict::Init(const nsAString& aJSON)
2010
0
{
2011
0
  AutoJSAPI jsapi;
2012
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
2013
0
  if (!cleanGlobal) {
2014
0
    return false;
2015
0
  }
2016
0
  if (!jsapi.Init(cleanGlobal)) {
2017
0
    return false;
2018
0
  }
2019
0
  JSContext* cx = jsapi.cx();
2020
0
  JS::Rooted<JS::Value> json(cx);
2021
0
  bool ok = ParseJSON(cx, aJSON, &json);
2022
0
  NS_ENSURE_TRUE(ok, false);
2023
0
  return Init(cx, json);
2024
0
}
2025
2026
bool
2027
DNSCacheDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2028
0
{
2029
0
  DNSCacheDictAtoms* atomsCache = GetAtomCache<DNSCacheDictAtoms>(cx);
2030
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2031
0
    return false;
2032
0
  }
2033
0
2034
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
2035
0
  if (!obj) {
2036
0
    return false;
2037
0
  }
2038
0
  rval.set(JS::ObjectValue(*obj));
2039
0
2040
0
  if (mEntries.WasPassed()) {
2041
0
    do {
2042
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2043
0
      JS::Rooted<JS::Value> temp(cx);
2044
0
      Sequence<DnsCacheEntry> const & currentValue = mEntries.InternalValue();
2045
0
2046
0
      uint32_t length = currentValue.Length();
2047
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2048
0
      if (!returnArray) {
2049
0
        return false;
2050
0
      }
2051
0
      // Scope for 'tmp'
2052
0
      {
2053
0
        JS::Rooted<JS::Value> tmp(cx);
2054
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2055
0
          // Control block to let us common up the JS_DefineElement calls when there
2056
0
          // are different ways to succeed at wrapping the object.
2057
0
          do {
2058
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
2059
0
              return false;
2060
0
            }
2061
0
            break;
2062
0
          } while (false);
2063
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2064
0
                                JSPROP_ENUMERATE)) {
2065
0
            return false;
2066
0
          }
2067
0
        }
2068
0
      }
2069
0
      temp.setObject(*returnArray);
2070
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->entries_id, temp, JSPROP_ENUMERATE)) {
2071
0
        return false;
2072
0
      }
2073
0
      break;
2074
0
    } while(false);
2075
0
  }
2076
0
2077
0
  return true;
2078
0
}
2079
2080
bool
2081
DNSCacheDict::ToJSON(nsAString& aJSON) const
2082
0
{
2083
0
  AutoJSAPI jsapi;
2084
0
  jsapi.Init();
2085
0
  JSContext *cx = jsapi.cx();
2086
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
2087
0
  // because we'll only be creating objects, in ways that have no
2088
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
2089
0
  // which likewise guarantees no side-effects for the sorts of
2090
0
  // things we will pass it.
2091
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
2092
0
  JS::Rooted<JS::Value> val(cx);
2093
0
  if (!ToObjectInternal(cx, &val)) {
2094
0
    return false;
2095
0
  }
2096
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
2097
0
  return StringifyToJSON(cx, obj, aJSON);
2098
0
}
2099
2100
void
2101
DNSCacheDict::TraceDictionary(JSTracer* trc)
2102
0
{
2103
0
}
2104
2105
DNSCacheDict&
2106
DNSCacheDict::operator=(const DNSCacheDict& aOther)
2107
0
{
2108
0
  DictionaryBase::operator=(aOther);
2109
0
  mEntries.Reset();
2110
0
  if (aOther.mEntries.WasPassed()) {
2111
0
    mEntries.Construct(aOther.mEntries.Value());
2112
0
  }
2113
0
  return *this;
2114
0
}
2115
2116
namespace binding_detail {
2117
} // namespace binding_detail
2118
2119
2120
2121
HttpConnectionElement::HttpConnectionElement()
2122
0
{
2123
0
  // Safe to pass a null context if we pass a null value
2124
0
  Init(nullptr, JS::NullHandleValue);
2125
0
}
2126
2127
2128
2129
bool
2130
HttpConnectionElement::InitIds(JSContext* cx, HttpConnectionElementAtoms* atomsCache)
2131
0
{
2132
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2133
0
2134
0
  // Initialize these in reverse order so that any failure leaves the first one
2135
0
  // uninitialized.
2136
0
  if (!atomsCache->ssl_id.init(cx, "ssl") ||
2137
0
      !atomsCache->spdy_id.init(cx, "spdy") ||
2138
0
      !atomsCache->port_id.init(cx, "port") ||
2139
0
      !atomsCache->idle_id.init(cx, "idle") ||
2140
0
      !atomsCache->host_id.init(cx, "host") ||
2141
0
      !atomsCache->halfOpens_id.init(cx, "halfOpens") ||
2142
0
      !atomsCache->active_id.init(cx, "active")) {
2143
0
    return false;
2144
0
  }
2145
0
  return true;
2146
0
}
2147
2148
bool
2149
HttpConnectionElement::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2150
0
{
2151
0
  // Passing a null JSContext is OK only if we're initing from null,
2152
0
  // Since in that case we will not have to do any property gets
2153
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2154
0
  // checkers by static analysis tools
2155
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2156
0
  HttpConnectionElementAtoms* atomsCache = nullptr;
2157
0
  if (cx) {
2158
0
    atomsCache = GetAtomCache<HttpConnectionElementAtoms>(cx);
2159
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2160
0
      return false;
2161
0
    }
2162
0
  }
2163
0
2164
0
  if (!IsConvertibleToDictionary(val)) {
2165
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
2166
0
  }
2167
0
2168
0
  bool isNull = val.isNullOrUndefined();
2169
0
  // We only need these if !isNull, in which case we have |cx|.
2170
0
  Maybe<JS::Rooted<JSObject *> > object;
2171
0
  Maybe<JS::Rooted<JS::Value> > temp;
2172
0
  if (!isNull) {
2173
0
    MOZ_ASSERT(cx);
2174
0
    object.emplace(cx, &val.toObject());
2175
0
    temp.emplace(cx);
2176
0
  }
2177
0
  if (!isNull) {
2178
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->active_id, temp.ptr())) {
2179
0
      return false;
2180
0
    }
2181
0
  }
2182
0
  if (!isNull && !temp->isUndefined()) {
2183
0
    mActive.Construct();
2184
0
    if (temp.ref().isObject()) {
2185
0
      JS::ForOfIterator iter(cx);
2186
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
2187
0
        return false;
2188
0
      }
2189
0
      if (!iter.valueIsIterable()) {
2190
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'active' member of HttpConnectionElement");
2191
0
        return false;
2192
0
      }
2193
0
      Sequence<HttpConnInfo> &arr = (mActive.Value());
2194
0
      JS::Rooted<JS::Value> temp(cx);
2195
0
      while (true) {
2196
0
        bool done;
2197
0
        if (!iter.next(&temp, &done)) {
2198
0
          return false;
2199
0
        }
2200
0
        if (done) {
2201
0
          break;
2202
0
        }
2203
0
        HttpConnInfo* slotPtr = arr.AppendElement(mozilla::fallible);
2204
0
        if (!slotPtr) {
2205
0
          JS_ReportOutOfMemory(cx);
2206
0
          return false;
2207
0
        }
2208
0
        HttpConnInfo& slot = *slotPtr;
2209
0
        if (!slot.Init(cx, temp,  "Element of 'active' member of HttpConnectionElement", passedToJSImpl)) {
2210
0
          return false;
2211
0
        }
2212
0
      }
2213
0
    } else {
2214
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'active' member of HttpConnectionElement");
2215
0
      return false;
2216
0
    }
2217
0
    mIsAnyMemberPresent = true;
2218
0
  }
2219
0
2220
0
  if (!isNull) {
2221
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->halfOpens_id, temp.ptr())) {
2222
0
      return false;
2223
0
    }
2224
0
  }
2225
0
  if (!isNull && !temp->isUndefined()) {
2226
0
    mHalfOpens.Construct();
2227
0
    if (temp.ref().isObject()) {
2228
0
      JS::ForOfIterator iter(cx);
2229
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
2230
0
        return false;
2231
0
      }
2232
0
      if (!iter.valueIsIterable()) {
2233
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'halfOpens' member of HttpConnectionElement");
2234
0
        return false;
2235
0
      }
2236
0
      Sequence<HalfOpenInfoDict> &arr = (mHalfOpens.Value());
2237
0
      JS::Rooted<JS::Value> temp(cx);
2238
0
      while (true) {
2239
0
        bool done;
2240
0
        if (!iter.next(&temp, &done)) {
2241
0
          return false;
2242
0
        }
2243
0
        if (done) {
2244
0
          break;
2245
0
        }
2246
0
        HalfOpenInfoDict* slotPtr = arr.AppendElement(mozilla::fallible);
2247
0
        if (!slotPtr) {
2248
0
          JS_ReportOutOfMemory(cx);
2249
0
          return false;
2250
0
        }
2251
0
        HalfOpenInfoDict& slot = *slotPtr;
2252
0
        if (!slot.Init(cx, temp,  "Element of 'halfOpens' member of HttpConnectionElement", passedToJSImpl)) {
2253
0
          return false;
2254
0
        }
2255
0
      }
2256
0
    } else {
2257
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'halfOpens' member of HttpConnectionElement");
2258
0
      return false;
2259
0
    }
2260
0
    mIsAnyMemberPresent = true;
2261
0
  }
2262
0
2263
0
  if (!isNull) {
2264
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->host_id, temp.ptr())) {
2265
0
      return false;
2266
0
    }
2267
0
  }
2268
0
  if (!isNull && !temp->isUndefined()) {
2269
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mHost)) {
2270
0
      return false;
2271
0
    }
2272
0
  } else {
2273
0
    static const char16_t data[] = { 0 };
2274
0
    mHost.Rebind(data, ArrayLength(data) - 1);
2275
0
  }
2276
0
  mIsAnyMemberPresent = true;
2277
0
2278
0
  if (!isNull) {
2279
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->idle_id, temp.ptr())) {
2280
0
      return false;
2281
0
    }
2282
0
  }
2283
0
  if (!isNull && !temp->isUndefined()) {
2284
0
    mIdle.Construct();
2285
0
    if (temp.ref().isObject()) {
2286
0
      JS::ForOfIterator iter(cx);
2287
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
2288
0
        return false;
2289
0
      }
2290
0
      if (!iter.valueIsIterable()) {
2291
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'idle' member of HttpConnectionElement");
2292
0
        return false;
2293
0
      }
2294
0
      Sequence<HttpConnInfo> &arr = (mIdle.Value());
2295
0
      JS::Rooted<JS::Value> temp(cx);
2296
0
      while (true) {
2297
0
        bool done;
2298
0
        if (!iter.next(&temp, &done)) {
2299
0
          return false;
2300
0
        }
2301
0
        if (done) {
2302
0
          break;
2303
0
        }
2304
0
        HttpConnInfo* slotPtr = arr.AppendElement(mozilla::fallible);
2305
0
        if (!slotPtr) {
2306
0
          JS_ReportOutOfMemory(cx);
2307
0
          return false;
2308
0
        }
2309
0
        HttpConnInfo& slot = *slotPtr;
2310
0
        if (!slot.Init(cx, temp,  "Element of 'idle' member of HttpConnectionElement", passedToJSImpl)) {
2311
0
          return false;
2312
0
        }
2313
0
      }
2314
0
    } else {
2315
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'idle' member of HttpConnectionElement");
2316
0
      return false;
2317
0
    }
2318
0
    mIsAnyMemberPresent = true;
2319
0
  }
2320
0
2321
0
  if (!isNull) {
2322
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->port_id, temp.ptr())) {
2323
0
      return false;
2324
0
    }
2325
0
  }
2326
0
  if (!isNull && !temp->isUndefined()) {
2327
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mPort)) {
2328
0
      return false;
2329
0
    }
2330
0
  } else {
2331
0
    mPort = 0U;
2332
0
  }
2333
0
  mIsAnyMemberPresent = true;
2334
0
2335
0
  if (!isNull) {
2336
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->spdy_id, temp.ptr())) {
2337
0
      return false;
2338
0
    }
2339
0
  }
2340
0
  if (!isNull && !temp->isUndefined()) {
2341
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mSpdy)) {
2342
0
      return false;
2343
0
    }
2344
0
  } else {
2345
0
    mSpdy = false;
2346
0
  }
2347
0
  mIsAnyMemberPresent = true;
2348
0
2349
0
  if (!isNull) {
2350
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->ssl_id, temp.ptr())) {
2351
0
      return false;
2352
0
    }
2353
0
  }
2354
0
  if (!isNull && !temp->isUndefined()) {
2355
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mSsl)) {
2356
0
      return false;
2357
0
    }
2358
0
  } else {
2359
0
    mSsl = false;
2360
0
  }
2361
0
  mIsAnyMemberPresent = true;
2362
0
  return true;
2363
0
}
2364
2365
bool
2366
HttpConnectionElement::Init(const nsAString& aJSON)
2367
0
{
2368
0
  AutoJSAPI jsapi;
2369
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
2370
0
  if (!cleanGlobal) {
2371
0
    return false;
2372
0
  }
2373
0
  if (!jsapi.Init(cleanGlobal)) {
2374
0
    return false;
2375
0
  }
2376
0
  JSContext* cx = jsapi.cx();
2377
0
  JS::Rooted<JS::Value> json(cx);
2378
0
  bool ok = ParseJSON(cx, aJSON, &json);
2379
0
  NS_ENSURE_TRUE(ok, false);
2380
0
  return Init(cx, json);
2381
0
}
2382
2383
bool
2384
HttpConnectionElement::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2385
0
{
2386
0
  HttpConnectionElementAtoms* atomsCache = GetAtomCache<HttpConnectionElementAtoms>(cx);
2387
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2388
0
    return false;
2389
0
  }
2390
0
2391
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
2392
0
  if (!obj) {
2393
0
    return false;
2394
0
  }
2395
0
  rval.set(JS::ObjectValue(*obj));
2396
0
2397
0
  if (mActive.WasPassed()) {
2398
0
    do {
2399
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2400
0
      JS::Rooted<JS::Value> temp(cx);
2401
0
      Sequence<HttpConnInfo> const & currentValue = mActive.InternalValue();
2402
0
2403
0
      uint32_t length = currentValue.Length();
2404
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2405
0
      if (!returnArray) {
2406
0
        return false;
2407
0
      }
2408
0
      // Scope for 'tmp'
2409
0
      {
2410
0
        JS::Rooted<JS::Value> tmp(cx);
2411
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2412
0
          // Control block to let us common up the JS_DefineElement calls when there
2413
0
          // are different ways to succeed at wrapping the object.
2414
0
          do {
2415
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
2416
0
              return false;
2417
0
            }
2418
0
            break;
2419
0
          } while (false);
2420
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2421
0
                                JSPROP_ENUMERATE)) {
2422
0
            return false;
2423
0
          }
2424
0
        }
2425
0
      }
2426
0
      temp.setObject(*returnArray);
2427
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->active_id, temp, JSPROP_ENUMERATE)) {
2428
0
        return false;
2429
0
      }
2430
0
      break;
2431
0
    } while(false);
2432
0
  }
2433
0
2434
0
  if (mHalfOpens.WasPassed()) {
2435
0
    do {
2436
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2437
0
      JS::Rooted<JS::Value> temp(cx);
2438
0
      Sequence<HalfOpenInfoDict> const & currentValue = mHalfOpens.InternalValue();
2439
0
2440
0
      uint32_t length = currentValue.Length();
2441
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2442
0
      if (!returnArray) {
2443
0
        return false;
2444
0
      }
2445
0
      // Scope for 'tmp'
2446
0
      {
2447
0
        JS::Rooted<JS::Value> tmp(cx);
2448
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2449
0
          // Control block to let us common up the JS_DefineElement calls when there
2450
0
          // are different ways to succeed at wrapping the object.
2451
0
          do {
2452
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
2453
0
              return false;
2454
0
            }
2455
0
            break;
2456
0
          } while (false);
2457
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2458
0
                                JSPROP_ENUMERATE)) {
2459
0
            return false;
2460
0
          }
2461
0
        }
2462
0
      }
2463
0
      temp.setObject(*returnArray);
2464
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->halfOpens_id, temp, JSPROP_ENUMERATE)) {
2465
0
        return false;
2466
0
      }
2467
0
      break;
2468
0
    } while(false);
2469
0
  }
2470
0
2471
0
  do {
2472
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2473
0
    JS::Rooted<JS::Value> temp(cx);
2474
0
    nsString const & currentValue = mHost;
2475
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
2476
0
      return false;
2477
0
    }
2478
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->host_id, temp, JSPROP_ENUMERATE)) {
2479
0
      return false;
2480
0
    }
2481
0
    break;
2482
0
  } while(false);
2483
0
2484
0
  if (mIdle.WasPassed()) {
2485
0
    do {
2486
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2487
0
      JS::Rooted<JS::Value> temp(cx);
2488
0
      Sequence<HttpConnInfo> const & currentValue = mIdle.InternalValue();
2489
0
2490
0
      uint32_t length = currentValue.Length();
2491
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2492
0
      if (!returnArray) {
2493
0
        return false;
2494
0
      }
2495
0
      // Scope for 'tmp'
2496
0
      {
2497
0
        JS::Rooted<JS::Value> tmp(cx);
2498
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2499
0
          // Control block to let us common up the JS_DefineElement calls when there
2500
0
          // are different ways to succeed at wrapping the object.
2501
0
          do {
2502
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
2503
0
              return false;
2504
0
            }
2505
0
            break;
2506
0
          } while (false);
2507
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2508
0
                                JSPROP_ENUMERATE)) {
2509
0
            return false;
2510
0
          }
2511
0
        }
2512
0
      }
2513
0
      temp.setObject(*returnArray);
2514
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->idle_id, temp, JSPROP_ENUMERATE)) {
2515
0
        return false;
2516
0
      }
2517
0
      break;
2518
0
    } while(false);
2519
0
  }
2520
0
2521
0
  do {
2522
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2523
0
    JS::Rooted<JS::Value> temp(cx);
2524
0
    uint32_t const & currentValue = mPort;
2525
0
    temp.setNumber(currentValue);
2526
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->port_id, temp, JSPROP_ENUMERATE)) {
2527
0
      return false;
2528
0
    }
2529
0
    break;
2530
0
  } while(false);
2531
0
2532
0
  do {
2533
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2534
0
    JS::Rooted<JS::Value> temp(cx);
2535
0
    bool const & currentValue = mSpdy;
2536
0
    temp.setBoolean(currentValue);
2537
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->spdy_id, temp, JSPROP_ENUMERATE)) {
2538
0
      return false;
2539
0
    }
2540
0
    break;
2541
0
  } while(false);
2542
0
2543
0
  do {
2544
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2545
0
    JS::Rooted<JS::Value> temp(cx);
2546
0
    bool const & currentValue = mSsl;
2547
0
    temp.setBoolean(currentValue);
2548
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->ssl_id, temp, JSPROP_ENUMERATE)) {
2549
0
      return false;
2550
0
    }
2551
0
    break;
2552
0
  } while(false);
2553
0
2554
0
  return true;
2555
0
}
2556
2557
bool
2558
HttpConnectionElement::ToJSON(nsAString& aJSON) const
2559
0
{
2560
0
  AutoJSAPI jsapi;
2561
0
  jsapi.Init();
2562
0
  JSContext *cx = jsapi.cx();
2563
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
2564
0
  // because we'll only be creating objects, in ways that have no
2565
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
2566
0
  // which likewise guarantees no side-effects for the sorts of
2567
0
  // things we will pass it.
2568
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
2569
0
  JS::Rooted<JS::Value> val(cx);
2570
0
  if (!ToObjectInternal(cx, &val)) {
2571
0
    return false;
2572
0
  }
2573
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
2574
0
  return StringifyToJSON(cx, obj, aJSON);
2575
0
}
2576
2577
void
2578
HttpConnectionElement::TraceDictionary(JSTracer* trc)
2579
0
{
2580
0
}
2581
2582
HttpConnectionElement&
2583
HttpConnectionElement::operator=(const HttpConnectionElement& aOther)
2584
0
{
2585
0
  DictionaryBase::operator=(aOther);
2586
0
  mActive.Reset();
2587
0
  if (aOther.mActive.WasPassed()) {
2588
0
    mActive.Construct(aOther.mActive.Value());
2589
0
  }
2590
0
  mHalfOpens.Reset();
2591
0
  if (aOther.mHalfOpens.WasPassed()) {
2592
0
    mHalfOpens.Construct(aOther.mHalfOpens.Value());
2593
0
  }
2594
0
  mHost = aOther.mHost;
2595
0
  mIdle.Reset();
2596
0
  if (aOther.mIdle.WasPassed()) {
2597
0
    mIdle.Construct(aOther.mIdle.Value());
2598
0
  }
2599
0
  mPort = aOther.mPort;
2600
0
  mSpdy = aOther.mSpdy;
2601
0
  mSsl = aOther.mSsl;
2602
0
  return *this;
2603
0
}
2604
2605
namespace binding_detail {
2606
} // namespace binding_detail
2607
2608
2609
2610
RcwnStatus::RcwnStatus()
2611
0
{
2612
0
  // Safe to pass a null context if we pass a null value
2613
0
  Init(nullptr, JS::NullHandleValue);
2614
0
}
2615
2616
2617
2618
bool
2619
RcwnStatus::InitIds(JSContext* cx, RcwnStatusAtoms* atomsCache)
2620
0
{
2621
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2622
0
2623
0
  // Initialize these in reverse order so that any failure leaves the first one
2624
0
  // uninitialized.
2625
0
  if (!atomsCache->totalNetworkRequests_id.init(cx, "totalNetworkRequests") ||
2626
0
      !atomsCache->rcwnNetWonCount_id.init(cx, "rcwnNetWonCount") ||
2627
0
      !atomsCache->rcwnCacheWonCount_id.init(cx, "rcwnCacheWonCount") ||
2628
0
      !atomsCache->perfStats_id.init(cx, "perfStats") ||
2629
0
      !atomsCache->cacheSlowCount_id.init(cx, "cacheSlowCount") ||
2630
0
      !atomsCache->cacheNotSlowCount_id.init(cx, "cacheNotSlowCount")) {
2631
0
    return false;
2632
0
  }
2633
0
  return true;
2634
0
}
2635
2636
bool
2637
RcwnStatus::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2638
0
{
2639
0
  // Passing a null JSContext is OK only if we're initing from null,
2640
0
  // Since in that case we will not have to do any property gets
2641
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2642
0
  // checkers by static analysis tools
2643
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2644
0
  RcwnStatusAtoms* atomsCache = nullptr;
2645
0
  if (cx) {
2646
0
    atomsCache = GetAtomCache<RcwnStatusAtoms>(cx);
2647
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2648
0
      return false;
2649
0
    }
2650
0
  }
2651
0
2652
0
  if (!IsConvertibleToDictionary(val)) {
2653
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
2654
0
  }
2655
0
2656
0
  bool isNull = val.isNullOrUndefined();
2657
0
  // We only need these if !isNull, in which case we have |cx|.
2658
0
  Maybe<JS::Rooted<JSObject *> > object;
2659
0
  Maybe<JS::Rooted<JS::Value> > temp;
2660
0
  if (!isNull) {
2661
0
    MOZ_ASSERT(cx);
2662
0
    object.emplace(cx, &val.toObject());
2663
0
    temp.emplace(cx);
2664
0
  }
2665
0
  if (!isNull) {
2666
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->cacheNotSlowCount_id, temp.ptr())) {
2667
0
      return false;
2668
0
    }
2669
0
  }
2670
0
  if (!isNull && !temp->isUndefined()) {
2671
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mCacheNotSlowCount)) {
2672
0
      return false;
2673
0
    }
2674
0
  } else {
2675
0
    mCacheNotSlowCount = 0U;
2676
0
  }
2677
0
  mIsAnyMemberPresent = true;
2678
0
2679
0
  if (!isNull) {
2680
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->cacheSlowCount_id, temp.ptr())) {
2681
0
      return false;
2682
0
    }
2683
0
  }
2684
0
  if (!isNull && !temp->isUndefined()) {
2685
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mCacheSlowCount)) {
2686
0
      return false;
2687
0
    }
2688
0
  } else {
2689
0
    mCacheSlowCount = 0U;
2690
0
  }
2691
0
  mIsAnyMemberPresent = true;
2692
0
2693
0
  if (!isNull) {
2694
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->perfStats_id, temp.ptr())) {
2695
0
      return false;
2696
0
    }
2697
0
  }
2698
0
  if (!isNull && !temp->isUndefined()) {
2699
0
    mPerfStats.Construct();
2700
0
    if (temp.ref().isObject()) {
2701
0
      JS::ForOfIterator iter(cx);
2702
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
2703
0
        return false;
2704
0
      }
2705
0
      if (!iter.valueIsIterable()) {
2706
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'perfStats' member of RcwnStatus");
2707
0
        return false;
2708
0
      }
2709
0
      Sequence<RcwnPerfStats> &arr = (mPerfStats.Value());
2710
0
      JS::Rooted<JS::Value> temp(cx);
2711
0
      while (true) {
2712
0
        bool done;
2713
0
        if (!iter.next(&temp, &done)) {
2714
0
          return false;
2715
0
        }
2716
0
        if (done) {
2717
0
          break;
2718
0
        }
2719
0
        RcwnPerfStats* slotPtr = arr.AppendElement(mozilla::fallible);
2720
0
        if (!slotPtr) {
2721
0
          JS_ReportOutOfMemory(cx);
2722
0
          return false;
2723
0
        }
2724
0
        RcwnPerfStats& slot = *slotPtr;
2725
0
        if (!slot.Init(cx, temp,  "Element of 'perfStats' member of RcwnStatus", passedToJSImpl)) {
2726
0
          return false;
2727
0
        }
2728
0
      }
2729
0
    } else {
2730
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'perfStats' member of RcwnStatus");
2731
0
      return false;
2732
0
    }
2733
0
    mIsAnyMemberPresent = true;
2734
0
  }
2735
0
2736
0
  if (!isNull) {
2737
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rcwnCacheWonCount_id, temp.ptr())) {
2738
0
      return false;
2739
0
    }
2740
0
  }
2741
0
  if (!isNull && !temp->isUndefined()) {
2742
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mRcwnCacheWonCount)) {
2743
0
      return false;
2744
0
    }
2745
0
  } else {
2746
0
    mRcwnCacheWonCount = 0U;
2747
0
  }
2748
0
  mIsAnyMemberPresent = true;
2749
0
2750
0
  if (!isNull) {
2751
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->rcwnNetWonCount_id, temp.ptr())) {
2752
0
      return false;
2753
0
    }
2754
0
  }
2755
0
  if (!isNull && !temp->isUndefined()) {
2756
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mRcwnNetWonCount)) {
2757
0
      return false;
2758
0
    }
2759
0
  } else {
2760
0
    mRcwnNetWonCount = 0U;
2761
0
  }
2762
0
  mIsAnyMemberPresent = true;
2763
0
2764
0
  if (!isNull) {
2765
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->totalNetworkRequests_id, temp.ptr())) {
2766
0
      return false;
2767
0
    }
2768
0
  }
2769
0
  if (!isNull && !temp->isUndefined()) {
2770
0
    if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), &mTotalNetworkRequests)) {
2771
0
      return false;
2772
0
    }
2773
0
  } else {
2774
0
    mTotalNetworkRequests = 0U;
2775
0
  }
2776
0
  mIsAnyMemberPresent = true;
2777
0
  return true;
2778
0
}
2779
2780
bool
2781
RcwnStatus::Init(const nsAString& aJSON)
2782
0
{
2783
0
  AutoJSAPI jsapi;
2784
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
2785
0
  if (!cleanGlobal) {
2786
0
    return false;
2787
0
  }
2788
0
  if (!jsapi.Init(cleanGlobal)) {
2789
0
    return false;
2790
0
  }
2791
0
  JSContext* cx = jsapi.cx();
2792
0
  JS::Rooted<JS::Value> json(cx);
2793
0
  bool ok = ParseJSON(cx, aJSON, &json);
2794
0
  NS_ENSURE_TRUE(ok, false);
2795
0
  return Init(cx, json);
2796
0
}
2797
2798
bool
2799
RcwnStatus::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
2800
0
{
2801
0
  RcwnStatusAtoms* atomsCache = GetAtomCache<RcwnStatusAtoms>(cx);
2802
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2803
0
    return false;
2804
0
  }
2805
0
2806
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
2807
0
  if (!obj) {
2808
0
    return false;
2809
0
  }
2810
0
  rval.set(JS::ObjectValue(*obj));
2811
0
2812
0
  do {
2813
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2814
0
    JS::Rooted<JS::Value> temp(cx);
2815
0
    uint32_t const & currentValue = mCacheNotSlowCount;
2816
0
    temp.setNumber(currentValue);
2817
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->cacheNotSlowCount_id, temp, JSPROP_ENUMERATE)) {
2818
0
      return false;
2819
0
    }
2820
0
    break;
2821
0
  } while(false);
2822
0
2823
0
  do {
2824
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2825
0
    JS::Rooted<JS::Value> temp(cx);
2826
0
    uint32_t const & currentValue = mCacheSlowCount;
2827
0
    temp.setNumber(currentValue);
2828
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->cacheSlowCount_id, temp, JSPROP_ENUMERATE)) {
2829
0
      return false;
2830
0
    }
2831
0
    break;
2832
0
  } while(false);
2833
0
2834
0
  if (mPerfStats.WasPassed()) {
2835
0
    do {
2836
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2837
0
      JS::Rooted<JS::Value> temp(cx);
2838
0
      Sequence<RcwnPerfStats> const & currentValue = mPerfStats.InternalValue();
2839
0
2840
0
      uint32_t length = currentValue.Length();
2841
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
2842
0
      if (!returnArray) {
2843
0
        return false;
2844
0
      }
2845
0
      // Scope for 'tmp'
2846
0
      {
2847
0
        JS::Rooted<JS::Value> tmp(cx);
2848
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
2849
0
          // Control block to let us common up the JS_DefineElement calls when there
2850
0
          // are different ways to succeed at wrapping the object.
2851
0
          do {
2852
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
2853
0
              return false;
2854
0
            }
2855
0
            break;
2856
0
          } while (false);
2857
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
2858
0
                                JSPROP_ENUMERATE)) {
2859
0
            return false;
2860
0
          }
2861
0
        }
2862
0
      }
2863
0
      temp.setObject(*returnArray);
2864
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->perfStats_id, temp, JSPROP_ENUMERATE)) {
2865
0
        return false;
2866
0
      }
2867
0
      break;
2868
0
    } while(false);
2869
0
  }
2870
0
2871
0
  do {
2872
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2873
0
    JS::Rooted<JS::Value> temp(cx);
2874
0
    uint32_t const & currentValue = mRcwnCacheWonCount;
2875
0
    temp.setNumber(currentValue);
2876
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->rcwnCacheWonCount_id, temp, JSPROP_ENUMERATE)) {
2877
0
      return false;
2878
0
    }
2879
0
    break;
2880
0
  } while(false);
2881
0
2882
0
  do {
2883
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2884
0
    JS::Rooted<JS::Value> temp(cx);
2885
0
    uint32_t const & currentValue = mRcwnNetWonCount;
2886
0
    temp.setNumber(currentValue);
2887
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->rcwnNetWonCount_id, temp, JSPROP_ENUMERATE)) {
2888
0
      return false;
2889
0
    }
2890
0
    break;
2891
0
  } while(false);
2892
0
2893
0
  do {
2894
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
2895
0
    JS::Rooted<JS::Value> temp(cx);
2896
0
    uint32_t const & currentValue = mTotalNetworkRequests;
2897
0
    temp.setNumber(currentValue);
2898
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->totalNetworkRequests_id, temp, JSPROP_ENUMERATE)) {
2899
0
      return false;
2900
0
    }
2901
0
    break;
2902
0
  } while(false);
2903
0
2904
0
  return true;
2905
0
}
2906
2907
bool
2908
RcwnStatus::ToJSON(nsAString& aJSON) const
2909
0
{
2910
0
  AutoJSAPI jsapi;
2911
0
  jsapi.Init();
2912
0
  JSContext *cx = jsapi.cx();
2913
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
2914
0
  // because we'll only be creating objects, in ways that have no
2915
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
2916
0
  // which likewise guarantees no side-effects for the sorts of
2917
0
  // things we will pass it.
2918
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
2919
0
  JS::Rooted<JS::Value> val(cx);
2920
0
  if (!ToObjectInternal(cx, &val)) {
2921
0
    return false;
2922
0
  }
2923
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
2924
0
  return StringifyToJSON(cx, obj, aJSON);
2925
0
}
2926
2927
void
2928
RcwnStatus::TraceDictionary(JSTracer* trc)
2929
0
{
2930
0
}
2931
2932
RcwnStatus&
2933
RcwnStatus::operator=(const RcwnStatus& aOther)
2934
0
{
2935
0
  DictionaryBase::operator=(aOther);
2936
0
  mCacheNotSlowCount = aOther.mCacheNotSlowCount;
2937
0
  mCacheSlowCount = aOther.mCacheSlowCount;
2938
0
  mPerfStats.Reset();
2939
0
  if (aOther.mPerfStats.WasPassed()) {
2940
0
    mPerfStats.Construct(aOther.mPerfStats.Value());
2941
0
  }
2942
0
  mRcwnCacheWonCount = aOther.mRcwnCacheWonCount;
2943
0
  mRcwnNetWonCount = aOther.mRcwnNetWonCount;
2944
0
  mTotalNetworkRequests = aOther.mTotalNetworkRequests;
2945
0
  return *this;
2946
0
}
2947
2948
namespace binding_detail {
2949
} // namespace binding_detail
2950
2951
2952
2953
SocketsDict::SocketsDict()
2954
0
{
2955
0
  // Safe to pass a null context if we pass a null value
2956
0
  Init(nullptr, JS::NullHandleValue);
2957
0
}
2958
2959
2960
2961
bool
2962
SocketsDict::InitIds(JSContext* cx, SocketsDictAtoms* atomsCache)
2963
0
{
2964
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
2965
0
2966
0
  // Initialize these in reverse order so that any failure leaves the first one
2967
0
  // uninitialized.
2968
0
  if (!atomsCache->sockets_id.init(cx, "sockets") ||
2969
0
      !atomsCache->sent_id.init(cx, "sent") ||
2970
0
      !atomsCache->received_id.init(cx, "received")) {
2971
0
    return false;
2972
0
  }
2973
0
  return true;
2974
0
}
2975
2976
bool
2977
SocketsDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
2978
0
{
2979
0
  // Passing a null JSContext is OK only if we're initing from null,
2980
0
  // Since in that case we will not have to do any property gets
2981
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
2982
0
  // checkers by static analysis tools
2983
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
2984
0
  SocketsDictAtoms* atomsCache = nullptr;
2985
0
  if (cx) {
2986
0
    atomsCache = GetAtomCache<SocketsDictAtoms>(cx);
2987
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
2988
0
      return false;
2989
0
    }
2990
0
  }
2991
0
2992
0
  if (!IsConvertibleToDictionary(val)) {
2993
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
2994
0
  }
2995
0
2996
0
  bool isNull = val.isNullOrUndefined();
2997
0
  // We only need these if !isNull, in which case we have |cx|.
2998
0
  Maybe<JS::Rooted<JSObject *> > object;
2999
0
  Maybe<JS::Rooted<JS::Value> > temp;
3000
0
  if (!isNull) {
3001
0
    MOZ_ASSERT(cx);
3002
0
    object.emplace(cx, &val.toObject());
3003
0
    temp.emplace(cx);
3004
0
  }
3005
0
  if (!isNull) {
3006
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->received_id, temp.ptr())) {
3007
0
      return false;
3008
0
    }
3009
0
  }
3010
0
  if (!isNull && !temp->isUndefined()) {
3011
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mReceived)) {
3012
0
      return false;
3013
0
    } else if (!mozilla::IsFinite(mReceived)) {
3014
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'received' member of SocketsDict");
3015
0
      return false;
3016
0
    }
3017
0
  } else {
3018
0
    mReceived = 0.0;
3019
0
  }
3020
0
  mIsAnyMemberPresent = true;
3021
0
3022
0
  if (!isNull) {
3023
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->sent_id, temp.ptr())) {
3024
0
      return false;
3025
0
    }
3026
0
  }
3027
0
  if (!isNull && !temp->isUndefined()) {
3028
0
    if (!ValueToPrimitive<double, eDefault>(cx, temp.ref(), &mSent)) {
3029
0
      return false;
3030
0
    } else if (!mozilla::IsFinite(mSent)) {
3031
0
      ThrowErrorMessage(cx, MSG_NOT_FINITE, "'sent' member of SocketsDict");
3032
0
      return false;
3033
0
    }
3034
0
  } else {
3035
0
    mSent = 0.0;
3036
0
  }
3037
0
  mIsAnyMemberPresent = true;
3038
0
3039
0
  if (!isNull) {
3040
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->sockets_id, temp.ptr())) {
3041
0
      return false;
3042
0
    }
3043
0
  }
3044
0
  if (!isNull && !temp->isUndefined()) {
3045
0
    mSockets.Construct();
3046
0
    if (temp.ref().isObject()) {
3047
0
      JS::ForOfIterator iter(cx);
3048
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
3049
0
        return false;
3050
0
      }
3051
0
      if (!iter.valueIsIterable()) {
3052
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'sockets' member of SocketsDict");
3053
0
        return false;
3054
0
      }
3055
0
      Sequence<SocketElement> &arr = (mSockets.Value());
3056
0
      JS::Rooted<JS::Value> temp(cx);
3057
0
      while (true) {
3058
0
        bool done;
3059
0
        if (!iter.next(&temp, &done)) {
3060
0
          return false;
3061
0
        }
3062
0
        if (done) {
3063
0
          break;
3064
0
        }
3065
0
        SocketElement* slotPtr = arr.AppendElement(mozilla::fallible);
3066
0
        if (!slotPtr) {
3067
0
          JS_ReportOutOfMemory(cx);
3068
0
          return false;
3069
0
        }
3070
0
        SocketElement& slot = *slotPtr;
3071
0
        if (!slot.Init(cx, temp,  "Element of 'sockets' member of SocketsDict", passedToJSImpl)) {
3072
0
          return false;
3073
0
        }
3074
0
      }
3075
0
    } else {
3076
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'sockets' member of SocketsDict");
3077
0
      return false;
3078
0
    }
3079
0
    mIsAnyMemberPresent = true;
3080
0
  }
3081
0
  return true;
3082
0
}
3083
3084
bool
3085
SocketsDict::Init(const nsAString& aJSON)
3086
0
{
3087
0
  AutoJSAPI jsapi;
3088
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
3089
0
  if (!cleanGlobal) {
3090
0
    return false;
3091
0
  }
3092
0
  if (!jsapi.Init(cleanGlobal)) {
3093
0
    return false;
3094
0
  }
3095
0
  JSContext* cx = jsapi.cx();
3096
0
  JS::Rooted<JS::Value> json(cx);
3097
0
  bool ok = ParseJSON(cx, aJSON, &json);
3098
0
  NS_ENSURE_TRUE(ok, false);
3099
0
  return Init(cx, json);
3100
0
}
3101
3102
bool
3103
SocketsDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
3104
0
{
3105
0
  SocketsDictAtoms* atomsCache = GetAtomCache<SocketsDictAtoms>(cx);
3106
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3107
0
    return false;
3108
0
  }
3109
0
3110
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
3111
0
  if (!obj) {
3112
0
    return false;
3113
0
  }
3114
0
  rval.set(JS::ObjectValue(*obj));
3115
0
3116
0
  do {
3117
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3118
0
    JS::Rooted<JS::Value> temp(cx);
3119
0
    double const & currentValue = mReceived;
3120
0
    temp.set(JS_NumberValue(double(currentValue)));
3121
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->received_id, temp, JSPROP_ENUMERATE)) {
3122
0
      return false;
3123
0
    }
3124
0
    break;
3125
0
  } while(false);
3126
0
3127
0
  do {
3128
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3129
0
    JS::Rooted<JS::Value> temp(cx);
3130
0
    double const & currentValue = mSent;
3131
0
    temp.set(JS_NumberValue(double(currentValue)));
3132
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->sent_id, temp, JSPROP_ENUMERATE)) {
3133
0
      return false;
3134
0
    }
3135
0
    break;
3136
0
  } while(false);
3137
0
3138
0
  if (mSockets.WasPassed()) {
3139
0
    do {
3140
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3141
0
      JS::Rooted<JS::Value> temp(cx);
3142
0
      Sequence<SocketElement> const & currentValue = mSockets.InternalValue();
3143
0
3144
0
      uint32_t length = currentValue.Length();
3145
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
3146
0
      if (!returnArray) {
3147
0
        return false;
3148
0
      }
3149
0
      // Scope for 'tmp'
3150
0
      {
3151
0
        JS::Rooted<JS::Value> tmp(cx);
3152
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
3153
0
          // Control block to let us common up the JS_DefineElement calls when there
3154
0
          // are different ways to succeed at wrapping the object.
3155
0
          do {
3156
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
3157
0
              return false;
3158
0
            }
3159
0
            break;
3160
0
          } while (false);
3161
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
3162
0
                                JSPROP_ENUMERATE)) {
3163
0
            return false;
3164
0
          }
3165
0
        }
3166
0
      }
3167
0
      temp.setObject(*returnArray);
3168
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->sockets_id, temp, JSPROP_ENUMERATE)) {
3169
0
        return false;
3170
0
      }
3171
0
      break;
3172
0
    } while(false);
3173
0
  }
3174
0
3175
0
  return true;
3176
0
}
3177
3178
bool
3179
SocketsDict::ToJSON(nsAString& aJSON) const
3180
0
{
3181
0
  AutoJSAPI jsapi;
3182
0
  jsapi.Init();
3183
0
  JSContext *cx = jsapi.cx();
3184
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
3185
0
  // because we'll only be creating objects, in ways that have no
3186
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
3187
0
  // which likewise guarantees no side-effects for the sorts of
3188
0
  // things we will pass it.
3189
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
3190
0
  JS::Rooted<JS::Value> val(cx);
3191
0
  if (!ToObjectInternal(cx, &val)) {
3192
0
    return false;
3193
0
  }
3194
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
3195
0
  return StringifyToJSON(cx, obj, aJSON);
3196
0
}
3197
3198
void
3199
SocketsDict::TraceDictionary(JSTracer* trc)
3200
0
{
3201
0
}
3202
3203
SocketsDict&
3204
SocketsDict::operator=(const SocketsDict& aOther)
3205
0
{
3206
0
  DictionaryBase::operator=(aOther);
3207
0
  mReceived = aOther.mReceived;
3208
0
  mSent = aOther.mSent;
3209
0
  mSockets.Reset();
3210
0
  if (aOther.mSockets.WasPassed()) {
3211
0
    mSockets.Construct(aOther.mSockets.Value());
3212
0
  }
3213
0
  return *this;
3214
0
}
3215
3216
namespace binding_detail {
3217
} // namespace binding_detail
3218
3219
3220
3221
WebSocketDict::WebSocketDict()
3222
0
{
3223
0
  // Safe to pass a null context if we pass a null value
3224
0
  Init(nullptr, JS::NullHandleValue);
3225
0
}
3226
3227
3228
3229
bool
3230
WebSocketDict::InitIds(JSContext* cx, WebSocketDictAtoms* atomsCache)
3231
0
{
3232
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
3233
0
3234
0
  // Initialize these in reverse order so that any failure leaves the first one
3235
0
  // uninitialized.
3236
0
  if (!atomsCache->websockets_id.init(cx, "websockets")) {
3237
0
    return false;
3238
0
  }
3239
0
  return true;
3240
0
}
3241
3242
bool
3243
WebSocketDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
3244
0
{
3245
0
  // Passing a null JSContext is OK only if we're initing from null,
3246
0
  // Since in that case we will not have to do any property gets
3247
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
3248
0
  // checkers by static analysis tools
3249
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
3250
0
  WebSocketDictAtoms* atomsCache = nullptr;
3251
0
  if (cx) {
3252
0
    atomsCache = GetAtomCache<WebSocketDictAtoms>(cx);
3253
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3254
0
      return false;
3255
0
    }
3256
0
  }
3257
0
3258
0
  if (!IsConvertibleToDictionary(val)) {
3259
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
3260
0
  }
3261
0
3262
0
  bool isNull = val.isNullOrUndefined();
3263
0
  // We only need these if !isNull, in which case we have |cx|.
3264
0
  Maybe<JS::Rooted<JSObject *> > object;
3265
0
  Maybe<JS::Rooted<JS::Value> > temp;
3266
0
  if (!isNull) {
3267
0
    MOZ_ASSERT(cx);
3268
0
    object.emplace(cx, &val.toObject());
3269
0
    temp.emplace(cx);
3270
0
  }
3271
0
  if (!isNull) {
3272
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->websockets_id, temp.ptr())) {
3273
0
      return false;
3274
0
    }
3275
0
  }
3276
0
  if (!isNull && !temp->isUndefined()) {
3277
0
    mWebsockets.Construct();
3278
0
    if (temp.ref().isObject()) {
3279
0
      JS::ForOfIterator iter(cx);
3280
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
3281
0
        return false;
3282
0
      }
3283
0
      if (!iter.valueIsIterable()) {
3284
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'websockets' member of WebSocketDict");
3285
0
        return false;
3286
0
      }
3287
0
      Sequence<WebSocketElement> &arr = (mWebsockets.Value());
3288
0
      JS::Rooted<JS::Value> temp(cx);
3289
0
      while (true) {
3290
0
        bool done;
3291
0
        if (!iter.next(&temp, &done)) {
3292
0
          return false;
3293
0
        }
3294
0
        if (done) {
3295
0
          break;
3296
0
        }
3297
0
        WebSocketElement* slotPtr = arr.AppendElement(mozilla::fallible);
3298
0
        if (!slotPtr) {
3299
0
          JS_ReportOutOfMemory(cx);
3300
0
          return false;
3301
0
        }
3302
0
        WebSocketElement& slot = *slotPtr;
3303
0
        if (!slot.Init(cx, temp,  "Element of 'websockets' member of WebSocketDict", passedToJSImpl)) {
3304
0
          return false;
3305
0
        }
3306
0
      }
3307
0
    } else {
3308
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'websockets' member of WebSocketDict");
3309
0
      return false;
3310
0
    }
3311
0
    mIsAnyMemberPresent = true;
3312
0
  }
3313
0
  return true;
3314
0
}
3315
3316
bool
3317
WebSocketDict::Init(const nsAString& aJSON)
3318
0
{
3319
0
  AutoJSAPI jsapi;
3320
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
3321
0
  if (!cleanGlobal) {
3322
0
    return false;
3323
0
  }
3324
0
  if (!jsapi.Init(cleanGlobal)) {
3325
0
    return false;
3326
0
  }
3327
0
  JSContext* cx = jsapi.cx();
3328
0
  JS::Rooted<JS::Value> json(cx);
3329
0
  bool ok = ParseJSON(cx, aJSON, &json);
3330
0
  NS_ENSURE_TRUE(ok, false);
3331
0
  return Init(cx, json);
3332
0
}
3333
3334
bool
3335
WebSocketDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
3336
0
{
3337
0
  WebSocketDictAtoms* atomsCache = GetAtomCache<WebSocketDictAtoms>(cx);
3338
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3339
0
    return false;
3340
0
  }
3341
0
3342
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
3343
0
  if (!obj) {
3344
0
    return false;
3345
0
  }
3346
0
  rval.set(JS::ObjectValue(*obj));
3347
0
3348
0
  if (mWebsockets.WasPassed()) {
3349
0
    do {
3350
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3351
0
      JS::Rooted<JS::Value> temp(cx);
3352
0
      Sequence<WebSocketElement> const & currentValue = mWebsockets.InternalValue();
3353
0
3354
0
      uint32_t length = currentValue.Length();
3355
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
3356
0
      if (!returnArray) {
3357
0
        return false;
3358
0
      }
3359
0
      // Scope for 'tmp'
3360
0
      {
3361
0
        JS::Rooted<JS::Value> tmp(cx);
3362
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
3363
0
          // Control block to let us common up the JS_DefineElement calls when there
3364
0
          // are different ways to succeed at wrapping the object.
3365
0
          do {
3366
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
3367
0
              return false;
3368
0
            }
3369
0
            break;
3370
0
          } while (false);
3371
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
3372
0
                                JSPROP_ENUMERATE)) {
3373
0
            return false;
3374
0
          }
3375
0
        }
3376
0
      }
3377
0
      temp.setObject(*returnArray);
3378
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->websockets_id, temp, JSPROP_ENUMERATE)) {
3379
0
        return false;
3380
0
      }
3381
0
      break;
3382
0
    } while(false);
3383
0
  }
3384
0
3385
0
  return true;
3386
0
}
3387
3388
bool
3389
WebSocketDict::ToJSON(nsAString& aJSON) const
3390
0
{
3391
0
  AutoJSAPI jsapi;
3392
0
  jsapi.Init();
3393
0
  JSContext *cx = jsapi.cx();
3394
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
3395
0
  // because we'll only be creating objects, in ways that have no
3396
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
3397
0
  // which likewise guarantees no side-effects for the sorts of
3398
0
  // things we will pass it.
3399
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
3400
0
  JS::Rooted<JS::Value> val(cx);
3401
0
  if (!ToObjectInternal(cx, &val)) {
3402
0
    return false;
3403
0
  }
3404
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
3405
0
  return StringifyToJSON(cx, obj, aJSON);
3406
0
}
3407
3408
void
3409
WebSocketDict::TraceDictionary(JSTracer* trc)
3410
0
{
3411
0
}
3412
3413
WebSocketDict&
3414
WebSocketDict::operator=(const WebSocketDict& aOther)
3415
0
{
3416
0
  DictionaryBase::operator=(aOther);
3417
0
  mWebsockets.Reset();
3418
0
  if (aOther.mWebsockets.WasPassed()) {
3419
0
    mWebsockets.Construct(aOther.mWebsockets.Value());
3420
0
  }
3421
0
  return *this;
3422
0
}
3423
3424
namespace binding_detail {
3425
} // namespace binding_detail
3426
3427
3428
3429
HttpConnDict::HttpConnDict()
3430
0
{
3431
0
  // Safe to pass a null context if we pass a null value
3432
0
  Init(nullptr, JS::NullHandleValue);
3433
0
}
3434
3435
3436
3437
bool
3438
HttpConnDict::InitIds(JSContext* cx, HttpConnDictAtoms* atomsCache)
3439
0
{
3440
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
3441
0
3442
0
  // Initialize these in reverse order so that any failure leaves the first one
3443
0
  // uninitialized.
3444
0
  if (!atomsCache->connections_id.init(cx, "connections")) {
3445
0
    return false;
3446
0
  }
3447
0
  return true;
3448
0
}
3449
3450
bool
3451
HttpConnDict::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
3452
0
{
3453
0
  // Passing a null JSContext is OK only if we're initing from null,
3454
0
  // Since in that case we will not have to do any property gets
3455
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
3456
0
  // checkers by static analysis tools
3457
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
3458
0
  HttpConnDictAtoms* atomsCache = nullptr;
3459
0
  if (cx) {
3460
0
    atomsCache = GetAtomCache<HttpConnDictAtoms>(cx);
3461
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3462
0
      return false;
3463
0
    }
3464
0
  }
3465
0
3466
0
  if (!IsConvertibleToDictionary(val)) {
3467
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
3468
0
  }
3469
0
3470
0
  bool isNull = val.isNullOrUndefined();
3471
0
  // We only need these if !isNull, in which case we have |cx|.
3472
0
  Maybe<JS::Rooted<JSObject *> > object;
3473
0
  Maybe<JS::Rooted<JS::Value> > temp;
3474
0
  if (!isNull) {
3475
0
    MOZ_ASSERT(cx);
3476
0
    object.emplace(cx, &val.toObject());
3477
0
    temp.emplace(cx);
3478
0
  }
3479
0
  if (!isNull) {
3480
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->connections_id, temp.ptr())) {
3481
0
      return false;
3482
0
    }
3483
0
  }
3484
0
  if (!isNull && !temp->isUndefined()) {
3485
0
    mConnections.Construct();
3486
0
    if (temp.ref().isObject()) {
3487
0
      JS::ForOfIterator iter(cx);
3488
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
3489
0
        return false;
3490
0
      }
3491
0
      if (!iter.valueIsIterable()) {
3492
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'connections' member of HttpConnDict");
3493
0
        return false;
3494
0
      }
3495
0
      Sequence<HttpConnectionElement> &arr = (mConnections.Value());
3496
0
      JS::Rooted<JS::Value> temp(cx);
3497
0
      while (true) {
3498
0
        bool done;
3499
0
        if (!iter.next(&temp, &done)) {
3500
0
          return false;
3501
0
        }
3502
0
        if (done) {
3503
0
          break;
3504
0
        }
3505
0
        HttpConnectionElement* slotPtr = arr.AppendElement(mozilla::fallible);
3506
0
        if (!slotPtr) {
3507
0
          JS_ReportOutOfMemory(cx);
3508
0
          return false;
3509
0
        }
3510
0
        HttpConnectionElement& slot = *slotPtr;
3511
0
        if (!slot.Init(cx, temp,  "Element of 'connections' member of HttpConnDict", passedToJSImpl)) {
3512
0
          return false;
3513
0
        }
3514
0
      }
3515
0
    } else {
3516
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'connections' member of HttpConnDict");
3517
0
      return false;
3518
0
    }
3519
0
    mIsAnyMemberPresent = true;
3520
0
  }
3521
0
  return true;
3522
0
}
3523
3524
bool
3525
HttpConnDict::Init(const nsAString& aJSON)
3526
0
{
3527
0
  AutoJSAPI jsapi;
3528
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
3529
0
  if (!cleanGlobal) {
3530
0
    return false;
3531
0
  }
3532
0
  if (!jsapi.Init(cleanGlobal)) {
3533
0
    return false;
3534
0
  }
3535
0
  JSContext* cx = jsapi.cx();
3536
0
  JS::Rooted<JS::Value> json(cx);
3537
0
  bool ok = ParseJSON(cx, aJSON, &json);
3538
0
  NS_ENSURE_TRUE(ok, false);
3539
0
  return Init(cx, json);
3540
0
}
3541
3542
bool
3543
HttpConnDict::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
3544
0
{
3545
0
  HttpConnDictAtoms* atomsCache = GetAtomCache<HttpConnDictAtoms>(cx);
3546
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
3547
0
    return false;
3548
0
  }
3549
0
3550
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
3551
0
  if (!obj) {
3552
0
    return false;
3553
0
  }
3554
0
  rval.set(JS::ObjectValue(*obj));
3555
0
3556
0
  if (mConnections.WasPassed()) {
3557
0
    do {
3558
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
3559
0
      JS::Rooted<JS::Value> temp(cx);
3560
0
      Sequence<HttpConnectionElement> const & currentValue = mConnections.InternalValue();
3561
0
3562
0
      uint32_t length = currentValue.Length();
3563
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
3564
0
      if (!returnArray) {
3565
0
        return false;
3566
0
      }
3567
0
      // Scope for 'tmp'
3568
0
      {
3569
0
        JS::Rooted<JS::Value> tmp(cx);
3570
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
3571
0
          // Control block to let us common up the JS_DefineElement calls when there
3572
0
          // are different ways to succeed at wrapping the object.
3573
0
          do {
3574
0
            if (!currentValue[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
3575
0
              return false;
3576
0
            }
3577
0
            break;
3578
0
          } while (false);
3579
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
3580
0
                                JSPROP_ENUMERATE)) {
3581
0
            return false;
3582
0
          }
3583
0
        }
3584
0
      }
3585
0
      temp.setObject(*returnArray);
3586
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->connections_id, temp, JSPROP_ENUMERATE)) {
3587
0
        return false;
3588
0
      }
3589
0
      break;
3590
0
    } while(false);
3591
0
  }
3592
0
3593
0
  return true;
3594
0
}
3595
3596
bool
3597
HttpConnDict::ToJSON(nsAString& aJSON) const
3598
0
{
3599
0
  AutoJSAPI jsapi;
3600
0
  jsapi.Init();
3601
0
  JSContext *cx = jsapi.cx();
3602
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
3603
0
  // because we'll only be creating objects, in ways that have no
3604
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
3605
0
  // which likewise guarantees no side-effects for the sorts of
3606
0
  // things we will pass it.
3607
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
3608
0
  JS::Rooted<JS::Value> val(cx);
3609
0
  if (!ToObjectInternal(cx, &val)) {
3610
0
    return false;
3611
0
  }
3612
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
3613
0
  return StringifyToJSON(cx, obj, aJSON);
3614
0
}
3615
3616
void
3617
HttpConnDict::TraceDictionary(JSTracer* trc)
3618
0
{
3619
0
}
3620
3621
HttpConnDict&
3622
HttpConnDict::operator=(const HttpConnDict& aOther)
3623
0
{
3624
0
  DictionaryBase::operator=(aOther);
3625
0
  mConnections.Reset();
3626
0
  if (aOther.mConnections.WasPassed()) {
3627
0
    mConnections.Construct(aOther.mConnections.Value());
3628
0
  }
3629
0
  return *this;
3630
0
}
3631
3632
namespace binding_detail {
3633
} // namespace binding_detail
3634
3635
3636
} // namespace dom
3637
} // namespace mozilla