Coverage Report

Created: 2018-09-25 14:53

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