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