Line data Source code
1 : /* THIS FILE IS AUTOGENERATED FROM ThreadSafeChromeUtils.webidl BY Codegen.py - DO NOT EDIT */
2 :
3 : #include "AtomList.h"
4 : #include "ThreadSafeChromeUtilsBinding.h"
5 : #include "WrapperFactory.h"
6 : #include "jsapi.h"
7 : #include "jsfriendapi.h"
8 : #include "mozilla/OwningNonNull.h"
9 : #include "mozilla/devtools/HeapSnapshot.h"
10 : #include "mozilla/dom/BindingUtils.h"
11 : #include "mozilla/dom/ChromeUtils.h"
12 : #include "mozilla/dom/DOMJSClass.h"
13 : #include "mozilla/dom/NonRefcountedDOMObject.h"
14 : #include "mozilla/dom/PrimitiveConversions.h"
15 : #include "mozilla/dom/ScriptSettings.h"
16 : #include "mozilla/dom/SimpleGlobalObject.h"
17 : #include "mozilla/dom/TypedArray.h"
18 : #include "mozilla/dom/UnionConversions.h"
19 : #include "mozilla/dom/UnionTypes.h"
20 : #include "mozilla/dom/XrayExpandoClass.h"
21 : #include "nsContentUtils.h"
22 :
23 : namespace mozilla {
24 : namespace dom {
25 :
26 : namespace Base64URLDecodePaddingValues {
27 : extern const EnumEntry strings[4] = {
28 : {"require", 7},
29 : {"ignore", 6},
30 : {"reject", 6},
31 : { nullptr, 0 }
32 : };
33 : } // namespace Base64URLDecodePaddingValues
34 :
35 : bool
36 0 : ToJSValue(JSContext* aCx, Base64URLDecodePadding aArgument, JS::MutableHandle<JS::Value> aValue)
37 : {
38 0 : MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(Base64URLDecodePaddingValues::strings));
39 : JSString* resultStr =
40 0 : JS_NewStringCopyN(aCx, Base64URLDecodePaddingValues::strings[uint32_t(aArgument)].value,
41 0 : Base64URLDecodePaddingValues::strings[uint32_t(aArgument)].length);
42 0 : if (!resultStr) {
43 0 : return false;
44 : }
45 0 : aValue.setString(resultStr);
46 0 : return true;
47 : }
48 :
49 :
50 :
51 0 : Base64URLDecodeOptions::Base64URLDecodeOptions()
52 : {
53 : // Safe to pass a null context if we pass a null value
54 0 : Init(nullptr, JS::NullHandleValue);
55 0 : }
56 :
57 :
58 :
59 : bool
60 0 : Base64URLDecodeOptions::InitIds(JSContext* cx, Base64URLDecodeOptionsAtoms* atomsCache)
61 : {
62 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
63 :
64 : // Initialize these in reverse order so that any failure leaves the first one
65 : // uninitialized.
66 0 : if (!atomsCache->padding_id.init(cx, "padding")) {
67 0 : return false;
68 : }
69 0 : return true;
70 : }
71 :
72 : bool
73 0 : Base64URLDecodeOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
74 : {
75 : // Passing a null JSContext is OK only if we're initing from null,
76 : // Since in that case we will not have to do any property gets
77 : // Also evaluate isNullOrUndefined in order to avoid false-positive
78 : // checkers by static analysis tools
79 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
80 0 : Base64URLDecodeOptionsAtoms* atomsCache = nullptr;
81 0 : if (cx) {
82 0 : atomsCache = GetAtomCache<Base64URLDecodeOptionsAtoms>(cx);
83 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
84 0 : return false;
85 : }
86 : }
87 :
88 0 : if (!IsConvertibleToDictionary(val)) {
89 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
90 : }
91 :
92 0 : bool isNull = val.isNullOrUndefined();
93 : // We only need these if !isNull, in which case we have |cx|.
94 0 : Maybe<JS::Rooted<JSObject *> > object;
95 0 : Maybe<JS::Rooted<JS::Value> > temp;
96 0 : if (!isNull) {
97 0 : MOZ_ASSERT(cx);
98 0 : object.emplace(cx, &val.toObject());
99 0 : temp.emplace(cx);
100 : }
101 0 : if (!isNull) {
102 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->padding_id, temp.ptr())) {
103 0 : return false;
104 : }
105 : }
106 0 : if (!isNull && !temp->isUndefined()) {
107 : {
108 : int index;
109 0 : if (!FindEnumStringIndex<true>(cx, temp.ref(), Base64URLDecodePaddingValues::strings, "Base64URLDecodePadding", "'padding' member of Base64URLDecodeOptions", &index)) {
110 0 : return false;
111 : }
112 0 : MOZ_ASSERT(index >= 0);
113 0 : mPadding = static_cast<Base64URLDecodePadding>(index);
114 : }
115 0 : mIsAnyMemberPresent = true;
116 0 : } else if (cx) {
117 : // Don't error out if we have no cx. In that
118 : // situation the caller is default-constructing us and we'll
119 : // just assume they know what they're doing.
120 0 : return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
121 0 : "'padding' member of Base64URLDecodeOptions");
122 : }
123 0 : return true;
124 : }
125 :
126 : bool
127 0 : Base64URLDecodeOptions::Init(const nsAString& aJSON)
128 : {
129 0 : AutoJSAPI jsapi;
130 0 : JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
131 0 : if (!cleanGlobal) {
132 0 : return false;
133 : }
134 0 : if (!jsapi.Init(cleanGlobal)) {
135 0 : return false;
136 : }
137 0 : JSContext* cx = jsapi.cx();
138 0 : JS::Rooted<JS::Value> json(cx);
139 0 : bool ok = ParseJSON(cx, aJSON, &json);
140 0 : NS_ENSURE_TRUE(ok, false);
141 0 : return Init(cx, json);
142 : }
143 :
144 : bool
145 0 : Base64URLDecodeOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
146 : {
147 0 : Base64URLDecodeOptionsAtoms* atomsCache = GetAtomCache<Base64URLDecodeOptionsAtoms>(cx);
148 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
149 0 : return false;
150 : }
151 :
152 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
153 0 : if (!obj) {
154 0 : return false;
155 : }
156 0 : rval.set(JS::ObjectValue(*obj));
157 :
158 : do {
159 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
160 0 : JS::Rooted<JS::Value> temp(cx);
161 0 : Base64URLDecodePadding const & currentValue = mPadding;
162 0 : if (!ToJSValue(cx, currentValue, &temp)) {
163 0 : return false;
164 : }
165 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->padding_id, temp, JSPROP_ENUMERATE)) {
166 0 : return false;
167 : }
168 0 : break;
169 : } while(0);
170 :
171 0 : return true;
172 : }
173 :
174 : bool
175 0 : Base64URLDecodeOptions::ToJSON(nsAString& aJSON) const
176 : {
177 0 : AutoJSAPI jsapi;
178 0 : jsapi.Init();
179 0 : JSContext *cx = jsapi.cx();
180 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
181 : // because we'll only be creating objects, in ways that have no
182 : // side-effects, followed by a call to JS::ToJSONMaybeSafely,
183 : // which likewise guarantees no side-effects for the sorts of
184 : // things we will pass it.
185 0 : JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
186 0 : JS::Rooted<JS::Value> val(cx);
187 0 : if (!ToObjectInternal(cx, &val)) {
188 0 : return false;
189 : }
190 0 : JS::Rooted<JSObject*> obj(cx, &val.toObject());
191 0 : return StringifyToJSON(cx, obj, aJSON);
192 : }
193 :
194 : void
195 0 : Base64URLDecodeOptions::TraceDictionary(JSTracer* trc)
196 : {
197 0 : }
198 :
199 : Base64URLDecodeOptions&
200 0 : Base64URLDecodeOptions::operator=(const Base64URLDecodeOptions& aOther)
201 : {
202 0 : mPadding = aOther.mPadding;
203 0 : return *this;
204 : }
205 :
206 : namespace binding_detail {
207 : } // namespace binding_detail
208 :
209 :
210 :
211 0 : Base64URLEncodeOptions::Base64URLEncodeOptions()
212 : {
213 : // Safe to pass a null context if we pass a null value
214 0 : Init(nullptr, JS::NullHandleValue);
215 0 : }
216 :
217 :
218 :
219 : bool
220 0 : Base64URLEncodeOptions::InitIds(JSContext* cx, Base64URLEncodeOptionsAtoms* atomsCache)
221 : {
222 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
223 :
224 : // Initialize these in reverse order so that any failure leaves the first one
225 : // uninitialized.
226 0 : if (!atomsCache->pad_id.init(cx, "pad")) {
227 0 : return false;
228 : }
229 0 : return true;
230 : }
231 :
232 : bool
233 0 : Base64URLEncodeOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
234 : {
235 : // Passing a null JSContext is OK only if we're initing from null,
236 : // Since in that case we will not have to do any property gets
237 : // Also evaluate isNullOrUndefined in order to avoid false-positive
238 : // checkers by static analysis tools
239 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
240 0 : Base64URLEncodeOptionsAtoms* atomsCache = nullptr;
241 0 : if (cx) {
242 0 : atomsCache = GetAtomCache<Base64URLEncodeOptionsAtoms>(cx);
243 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
244 0 : return false;
245 : }
246 : }
247 :
248 0 : if (!IsConvertibleToDictionary(val)) {
249 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
250 : }
251 :
252 0 : bool isNull = val.isNullOrUndefined();
253 : // We only need these if !isNull, in which case we have |cx|.
254 0 : Maybe<JS::Rooted<JSObject *> > object;
255 0 : Maybe<JS::Rooted<JS::Value> > temp;
256 0 : if (!isNull) {
257 0 : MOZ_ASSERT(cx);
258 0 : object.emplace(cx, &val.toObject());
259 0 : temp.emplace(cx);
260 : }
261 0 : if (!isNull) {
262 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->pad_id, temp.ptr())) {
263 0 : return false;
264 : }
265 : }
266 0 : if (!isNull && !temp->isUndefined()) {
267 0 : if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mPad)) {
268 0 : return false;
269 : }
270 0 : mIsAnyMemberPresent = true;
271 0 : } else if (cx) {
272 : // Don't error out if we have no cx. In that
273 : // situation the caller is default-constructing us and we'll
274 : // just assume they know what they're doing.
275 0 : return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
276 0 : "'pad' member of Base64URLEncodeOptions");
277 : }
278 0 : return true;
279 : }
280 :
281 : bool
282 0 : Base64URLEncodeOptions::Init(const nsAString& aJSON)
283 : {
284 0 : AutoJSAPI jsapi;
285 0 : JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
286 0 : if (!cleanGlobal) {
287 0 : return false;
288 : }
289 0 : if (!jsapi.Init(cleanGlobal)) {
290 0 : return false;
291 : }
292 0 : JSContext* cx = jsapi.cx();
293 0 : JS::Rooted<JS::Value> json(cx);
294 0 : bool ok = ParseJSON(cx, aJSON, &json);
295 0 : NS_ENSURE_TRUE(ok, false);
296 0 : return Init(cx, json);
297 : }
298 :
299 : bool
300 0 : Base64URLEncodeOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
301 : {
302 0 : Base64URLEncodeOptionsAtoms* atomsCache = GetAtomCache<Base64URLEncodeOptionsAtoms>(cx);
303 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
304 0 : return false;
305 : }
306 :
307 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
308 0 : if (!obj) {
309 0 : return false;
310 : }
311 0 : rval.set(JS::ObjectValue(*obj));
312 :
313 : do {
314 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
315 0 : JS::Rooted<JS::Value> temp(cx);
316 0 : bool const & currentValue = mPad;
317 0 : temp.setBoolean(currentValue);
318 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->pad_id, temp, JSPROP_ENUMERATE)) {
319 0 : return false;
320 : }
321 0 : break;
322 : } while(0);
323 :
324 0 : return true;
325 : }
326 :
327 : bool
328 0 : Base64URLEncodeOptions::ToJSON(nsAString& aJSON) const
329 : {
330 0 : AutoJSAPI jsapi;
331 0 : jsapi.Init();
332 0 : JSContext *cx = jsapi.cx();
333 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
334 : // because we'll only be creating objects, in ways that have no
335 : // side-effects, followed by a call to JS::ToJSONMaybeSafely,
336 : // which likewise guarantees no side-effects for the sorts of
337 : // things we will pass it.
338 0 : JSAutoCompartment ac(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
339 0 : JS::Rooted<JS::Value> val(cx);
340 0 : if (!ToObjectInternal(cx, &val)) {
341 0 : return false;
342 : }
343 0 : JS::Rooted<JSObject*> obj(cx, &val.toObject());
344 0 : return StringifyToJSON(cx, obj, aJSON);
345 : }
346 :
347 : void
348 0 : Base64URLEncodeOptions::TraceDictionary(JSTracer* trc)
349 : {
350 0 : }
351 :
352 : Base64URLEncodeOptions&
353 0 : Base64URLEncodeOptions::operator=(const Base64URLEncodeOptions& aOther)
354 : {
355 0 : mPad = aOther.mPad;
356 0 : return *this;
357 : }
358 :
359 : namespace binding_detail {
360 : } // namespace binding_detail
361 :
362 :
363 :
364 0 : HeapSnapshotBoundaries::HeapSnapshotBoundaries()
365 : {
366 : // Safe to pass a null context if we pass a null value
367 0 : Init(nullptr, JS::NullHandleValue);
368 0 : }
369 :
370 :
371 : bool
372 0 : HeapSnapshotBoundaries::InitIds(JSContext* cx, HeapSnapshotBoundariesAtoms* atomsCache)
373 : {
374 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
375 :
376 : // Initialize these in reverse order so that any failure leaves the first one
377 : // uninitialized.
378 0 : if (!atomsCache->runtime_id.init(cx, "runtime") ||
379 0 : !atomsCache->globals_id.init(cx, "globals") ||
380 0 : !atomsCache->debugger_id.init(cx, "debugger")) {
381 0 : return false;
382 : }
383 0 : return true;
384 : }
385 :
386 : bool
387 0 : HeapSnapshotBoundaries::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
388 : {
389 : // Passing a null JSContext is OK only if we're initing from null,
390 : // Since in that case we will not have to do any property gets
391 : // Also evaluate isNullOrUndefined in order to avoid false-positive
392 : // checkers by static analysis tools
393 0 : MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
394 0 : HeapSnapshotBoundariesAtoms* atomsCache = nullptr;
395 0 : if (cx) {
396 0 : atomsCache = GetAtomCache<HeapSnapshotBoundariesAtoms>(cx);
397 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
398 0 : return false;
399 : }
400 : }
401 :
402 0 : if (!IsConvertibleToDictionary(val)) {
403 0 : return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
404 : }
405 :
406 0 : bool isNull = val.isNullOrUndefined();
407 : // We only need these if !isNull, in which case we have |cx|.
408 0 : Maybe<JS::Rooted<JSObject *> > object;
409 0 : Maybe<JS::Rooted<JS::Value> > temp;
410 0 : if (!isNull) {
411 0 : MOZ_ASSERT(cx);
412 0 : object.emplace(cx, &val.toObject());
413 0 : temp.emplace(cx);
414 : }
415 0 : if (!isNull) {
416 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->debugger_id, temp.ptr())) {
417 0 : return false;
418 : }
419 : }
420 0 : if (!isNull && !temp->isUndefined()) {
421 0 : mDebugger.Construct();
422 0 : if (temp.ref().isObject()) {
423 : #ifdef __clang__
424 : #pragma clang diagnostic push
425 : #pragma clang diagnostic ignored "-Wunreachable-code"
426 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
427 : #endif // __clang__
428 0 : if ((passedToJSImpl) && !CallerSubsumes(temp.ref())) {
429 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "'debugger' member of HeapSnapshotBoundaries");
430 0 : return false;
431 : }
432 : #ifdef __clang__
433 : #pragma clang diagnostic pop
434 : #endif // __clang__
435 0 : (mDebugger.Value()) = &temp.ref().toObject();
436 : } else {
437 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'debugger' member of HeapSnapshotBoundaries");
438 0 : return false;
439 : }
440 0 : mIsAnyMemberPresent = true;
441 : }
442 :
443 0 : if (!isNull) {
444 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->globals_id, temp.ptr())) {
445 0 : return false;
446 : }
447 : }
448 0 : if (!isNull && !temp->isUndefined()) {
449 0 : mGlobals.Construct();
450 0 : if (temp.ref().isObject()) {
451 0 : JS::ForOfIterator iter(cx);
452 0 : if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
453 0 : return false;
454 : }
455 0 : if (!iter.valueIsIterable()) {
456 0 : ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'globals' member of HeapSnapshotBoundaries");
457 0 : return false;
458 : }
459 0 : Sequence<JSObject*> &arr = (mGlobals.Value());
460 0 : JS::Rooted<JS::Value> temp(cx);
461 : while (true) {
462 : bool done;
463 0 : if (!iter.next(&temp, &done)) {
464 0 : return false;
465 : }
466 0 : if (done) {
467 0 : break;
468 : }
469 0 : JSObject** slotPtr = arr.AppendElement(mozilla::fallible);
470 0 : if (!slotPtr) {
471 0 : JS_ReportOutOfMemory(cx);
472 0 : return false;
473 : }
474 0 : JSObject*& slot = *slotPtr;
475 0 : if (temp.isObject()) {
476 : #ifdef __clang__
477 : #pragma clang diagnostic push
478 : #pragma clang diagnostic ignored "-Wunreachable-code"
479 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
480 : #endif // __clang__
481 0 : if ((passedToJSImpl) && !CallerSubsumes(temp)) {
482 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "element of 'globals' member of HeapSnapshotBoundaries");
483 0 : return false;
484 : }
485 : #ifdef __clang__
486 : #pragma clang diagnostic pop
487 : #endif // __clang__
488 0 : slot = &temp.toObject();
489 : } else {
490 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Element of 'globals' member of HeapSnapshotBoundaries");
491 0 : return false;
492 : }
493 0 : }
494 : } else {
495 0 : ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'globals' member of HeapSnapshotBoundaries");
496 0 : return false;
497 : }
498 0 : mIsAnyMemberPresent = true;
499 : }
500 :
501 0 : if (!isNull) {
502 0 : if (!JS_GetPropertyById(cx, *object, atomsCache->runtime_id, temp.ptr())) {
503 0 : return false;
504 : }
505 : }
506 0 : if (!isNull && !temp->isUndefined()) {
507 0 : mRuntime.Construct();
508 0 : if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &(mRuntime.Value()))) {
509 0 : return false;
510 : }
511 0 : mIsAnyMemberPresent = true;
512 : }
513 0 : return true;
514 : }
515 :
516 : bool
517 0 : HeapSnapshotBoundaries::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
518 : {
519 0 : HeapSnapshotBoundariesAtoms* atomsCache = GetAtomCache<HeapSnapshotBoundariesAtoms>(cx);
520 0 : if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
521 0 : return false;
522 : }
523 :
524 0 : JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
525 0 : if (!obj) {
526 0 : return false;
527 : }
528 0 : rval.set(JS::ObjectValue(*obj));
529 :
530 0 : if (mDebugger.WasPassed()) {
531 : do {
532 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
533 0 : JS::Rooted<JS::Value> temp(cx);
534 0 : JSObject* const & currentValue = mDebugger.InternalValue();
535 0 : JS::ExposeObjectToActiveJS(currentValue);
536 0 : temp.setObject(*currentValue);
537 0 : if (!MaybeWrapObjectValue(cx, &temp)) {
538 0 : return false;
539 : }
540 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->debugger_id, temp, JSPROP_ENUMERATE)) {
541 0 : return false;
542 : }
543 0 : break;
544 : } while(0);
545 : }
546 :
547 0 : if (mGlobals.WasPassed()) {
548 : do {
549 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
550 0 : JS::Rooted<JS::Value> temp(cx);
551 0 : Sequence<JSObject*> const & currentValue = mGlobals.InternalValue();
552 :
553 0 : uint32_t length = currentValue.Length();
554 0 : JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
555 0 : if (!returnArray) {
556 0 : return false;
557 : }
558 : // Scope for 'tmp'
559 : {
560 0 : JS::Rooted<JS::Value> tmp(cx);
561 0 : for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
562 : // Control block to let us common up the JS_DefineElement calls when there
563 : // are different ways to succeed at wrapping the object.
564 : do {
565 0 : JS::ExposeObjectToActiveJS(currentValue[sequenceIdx0]);
566 0 : tmp.setObject(*currentValue[sequenceIdx0]);
567 0 : if (!MaybeWrapObjectValue(cx, &tmp)) {
568 0 : return false;
569 : }
570 0 : break;
571 : } while (0);
572 0 : if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
573 : JSPROP_ENUMERATE)) {
574 0 : return false;
575 : }
576 : }
577 : }
578 0 : temp.setObject(*returnArray);
579 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->globals_id, temp, JSPROP_ENUMERATE)) {
580 0 : return false;
581 : }
582 0 : break;
583 : } while(0);
584 : }
585 :
586 0 : if (mRuntime.WasPassed()) {
587 : do {
588 : // block for our 'break' successCode and scope for 'temp' and 'currentValue'
589 0 : JS::Rooted<JS::Value> temp(cx);
590 0 : bool const & currentValue = mRuntime.InternalValue();
591 0 : temp.setBoolean(currentValue);
592 0 : if (!JS_DefinePropertyById(cx, obj, atomsCache->runtime_id, temp, JSPROP_ENUMERATE)) {
593 0 : return false;
594 : }
595 0 : break;
596 : } while(0);
597 : }
598 :
599 0 : return true;
600 : }
601 :
602 : void
603 0 : HeapSnapshotBoundaries::TraceDictionary(JSTracer* trc)
604 : {
605 0 : if (mDebugger.WasPassed()) {
606 0 : JS::UnsafeTraceRoot(trc, &mDebugger.Value(), "HeapSnapshotBoundaries.mDebugger");
607 : }
608 :
609 0 : if (mGlobals.WasPassed()) {
610 0 : DoTraceSequence(trc, mGlobals.Value());
611 : }
612 0 : }
613 :
614 : namespace binding_detail {
615 : } // namespace binding_detail
616 :
617 :
618 : namespace ThreadSafeChromeUtilsBinding {
619 :
620 : static bool
621 0 : saveHeapSnapshot(JSContext* cx, unsigned argc, JS::Value* vp)
622 : {
623 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
624 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
625 :
626 0 : GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
627 0 : if (global.Failed()) {
628 0 : return false;
629 : }
630 :
631 0 : RootedDictionary<binding_detail::FastHeapSnapshotBoundaries> arg0(cx);
632 0 : if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue, "Argument 1 of ThreadSafeChromeUtils.saveHeapSnapshot", false)) {
633 0 : return false;
634 : }
635 0 : binding_detail::FastErrorResult rv;
636 0 : DOMString result;
637 0 : mozilla::dom::ThreadSafeChromeUtils::SaveHeapSnapshot(global, Constify(arg0), result, rv);
638 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
639 0 : return false;
640 : }
641 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
642 0 : if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
643 0 : return false;
644 : }
645 0 : return true;
646 : }
647 :
648 : static bool
649 0 : saveHeapSnapshotGetId(JSContext* cx, unsigned argc, JS::Value* vp)
650 : {
651 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
652 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
653 :
654 0 : GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
655 0 : if (global.Failed()) {
656 0 : return false;
657 : }
658 :
659 0 : RootedDictionary<binding_detail::FastHeapSnapshotBoundaries> arg0(cx);
660 0 : if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue, "Argument 1 of ThreadSafeChromeUtils.saveHeapSnapshotGetId", false)) {
661 0 : return false;
662 : }
663 0 : binding_detail::FastErrorResult rv;
664 0 : DOMString result;
665 0 : mozilla::dom::ThreadSafeChromeUtils::SaveHeapSnapshotGetId(global, Constify(arg0), result, rv);
666 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
667 0 : return false;
668 : }
669 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
670 0 : if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
671 0 : return false;
672 : }
673 0 : return true;
674 : }
675 :
676 : static bool
677 0 : readHeapSnapshot(JSContext* cx, unsigned argc, JS::Value* vp)
678 : {
679 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
680 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
681 :
682 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
683 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "ThreadSafeChromeUtils.readHeapSnapshot");
684 : }
685 0 : GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
686 0 : if (global.Failed()) {
687 0 : return false;
688 : }
689 :
690 0 : binding_detail::FakeString arg0;
691 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
692 0 : return false;
693 : }
694 0 : binding_detail::FastErrorResult rv;
695 0 : auto result(StrongOrRawPtr<mozilla::devtools::HeapSnapshot>(mozilla::dom::ThreadSafeChromeUtils::ReadHeapSnapshot(global, NonNullHelper(Constify(arg0)), rv)));
696 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
697 0 : return false;
698 : }
699 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
700 : static_assert(!IsPointer<decltype(result)>::value,
701 : "NewObject implies that we need to keep the object alive with a strong reference.");
702 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
703 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
704 0 : return false;
705 : }
706 0 : return true;
707 : }
708 :
709 : static bool
710 0 : nondeterministicGetWeakMapKeys(JSContext* cx, unsigned argc, JS::Value* vp)
711 : {
712 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
713 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
714 :
715 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
716 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "ThreadSafeChromeUtils.nondeterministicGetWeakMapKeys");
717 : }
718 0 : GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
719 0 : if (global.Failed()) {
720 0 : return false;
721 : }
722 :
723 0 : JS::Rooted<JS::Value> arg0(cx);
724 0 : arg0 = args[0];
725 0 : binding_detail::FastErrorResult rv;
726 0 : JS::Rooted<JS::Value> result(cx);
727 0 : mozilla::dom::ThreadSafeChromeUtils::NondeterministicGetWeakMapKeys(global, arg0, &result, rv);
728 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
729 0 : return false;
730 : }
731 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
732 0 : JS::ExposeValueToActiveJS(result);
733 0 : args.rval().set(result);
734 0 : if (!MaybeWrapValue(cx, args.rval())) {
735 0 : return false;
736 : }
737 0 : return true;
738 : }
739 :
740 : static bool
741 0 : nondeterministicGetWeakSetKeys(JSContext* cx, unsigned argc, JS::Value* vp)
742 : {
743 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
744 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
745 :
746 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
747 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "ThreadSafeChromeUtils.nondeterministicGetWeakSetKeys");
748 : }
749 0 : GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
750 0 : if (global.Failed()) {
751 0 : return false;
752 : }
753 :
754 0 : JS::Rooted<JS::Value> arg0(cx);
755 0 : arg0 = args[0];
756 0 : binding_detail::FastErrorResult rv;
757 0 : JS::Rooted<JS::Value> result(cx);
758 0 : mozilla::dom::ThreadSafeChromeUtils::NondeterministicGetWeakSetKeys(global, arg0, &result, rv);
759 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
760 0 : return false;
761 : }
762 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
763 0 : JS::ExposeValueToActiveJS(result);
764 0 : args.rval().set(result);
765 0 : if (!MaybeWrapValue(cx, args.rval())) {
766 0 : return false;
767 : }
768 0 : return true;
769 : }
770 :
771 : static bool
772 0 : base64URLEncode(JSContext* cx, unsigned argc, JS::Value* vp)
773 : {
774 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
775 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
776 :
777 0 : if (MOZ_UNLIKELY(args.length() < 2)) {
778 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "ThreadSafeChromeUtils.base64URLEncode");
779 : }
780 0 : GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
781 0 : if (global.Failed()) {
782 0 : return false;
783 : }
784 :
785 0 : ArrayBufferViewOrArrayBuffer arg0;
786 0 : ArrayBufferViewOrArrayBufferArgument arg0_holder(arg0);
787 : {
788 0 : bool done = false, failed = false, tryNext;
789 0 : if (args[0].isObject()) {
790 0 : done = (failed = !arg0_holder.TrySetToArrayBufferView(cx, args[0], tryNext, false)) || !tryNext ||
791 0 : (failed = !arg0_holder.TrySetToArrayBuffer(cx, args[0], tryNext, false)) || !tryNext;
792 :
793 : }
794 0 : if (failed) {
795 0 : return false;
796 : }
797 0 : if (!done) {
798 0 : ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of ThreadSafeChromeUtils.base64URLEncode", "ArrayBufferView, ArrayBuffer");
799 0 : return false;
800 : }
801 : }
802 0 : binding_detail::FastBase64URLEncodeOptions arg1;
803 0 : if (!arg1.Init(cx, args[1], "Argument 2 of ThreadSafeChromeUtils.base64URLEncode", false)) {
804 0 : return false;
805 : }
806 0 : binding_detail::FastErrorResult rv;
807 0 : nsCString result;
808 0 : mozilla::dom::ThreadSafeChromeUtils::Base64URLEncode(global, Constify(arg0), Constify(arg1), result, rv);
809 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
810 0 : return false;
811 : }
812 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
813 0 : if (!NonVoidByteStringToJsval(cx, result, args.rval())) {
814 0 : return false;
815 : }
816 0 : return true;
817 : }
818 :
819 : static bool
820 0 : base64URLDecode(JSContext* cx, unsigned argc, JS::Value* vp)
821 : {
822 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
823 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
824 :
825 0 : if (MOZ_UNLIKELY(args.length() < 2)) {
826 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "ThreadSafeChromeUtils.base64URLDecode");
827 : }
828 0 : GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
829 0 : if (global.Failed()) {
830 0 : return false;
831 : }
832 :
833 0 : nsCString arg0;
834 0 : if (!ConvertJSValueToByteString(cx, args[0], false, arg0)) {
835 0 : return false;
836 : }
837 0 : binding_detail::FastBase64URLDecodeOptions arg1;
838 0 : if (!arg1.Init(cx, args[1], "Argument 2 of ThreadSafeChromeUtils.base64URLDecode", false)) {
839 0 : return false;
840 : }
841 0 : binding_detail::FastErrorResult rv;
842 0 : JS::Rooted<JSObject*> result(cx);
843 0 : mozilla::dom::ThreadSafeChromeUtils::Base64URLDecode(global, Constify(arg0), Constify(arg1), &result, rv);
844 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
845 0 : return false;
846 : }
847 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
848 0 : JS::ExposeObjectToActiveJS(result);
849 0 : args.rval().setObject(*result);
850 0 : if (!MaybeWrapNonDOMObjectValue(cx, args.rval())) {
851 0 : return false;
852 : }
853 0 : return true;
854 : }
855 :
856 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
857 : #if defined(__clang__)
858 : #pragma clang diagnostic push
859 : #pragma clang diagnostic ignored "-Wmissing-braces"
860 : #endif
861 : static const JSFunctionSpec sStaticMethods_specs[] = {
862 : JS_FNSPEC("saveHeapSnapshot", saveHeapSnapshot, nullptr, 0, JSPROP_ENUMERATE, nullptr),
863 : JS_FNSPEC("saveHeapSnapshotGetId", saveHeapSnapshotGetId, nullptr, 0, JSPROP_ENUMERATE, nullptr),
864 : JS_FNSPEC("readHeapSnapshot", readHeapSnapshot, nullptr, 1, JSPROP_ENUMERATE, nullptr),
865 : JS_FNSPEC("nondeterministicGetWeakMapKeys", nondeterministicGetWeakMapKeys, nullptr, 1, JSPROP_ENUMERATE, nullptr),
866 : JS_FNSPEC("nondeterministicGetWeakSetKeys", nondeterministicGetWeakSetKeys, nullptr, 1, JSPROP_ENUMERATE, nullptr),
867 : JS_FNSPEC("base64URLEncode", base64URLEncode, nullptr, 2, JSPROP_ENUMERATE, nullptr),
868 : JS_FNSPEC("base64URLDecode", base64URLDecode, nullptr, 2, JSPROP_ENUMERATE, nullptr),
869 : JS_FS_END
870 : };
871 : #if defined(__clang__)
872 : #pragma clang diagnostic pop
873 : #endif
874 :
875 :
876 : // Can't be const because the pref-enabled boolean needs to be writable
877 : static Prefable<const JSFunctionSpec> sStaticMethods[] = {
878 : { nullptr, &sStaticMethods_specs[0] },
879 : { nullptr, nullptr }
880 : };
881 :
882 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
883 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
884 : static_assert(7 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
885 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
886 :
887 :
888 : static uint16_t sNativeProperties_sortedPropertyIndices[7];
889 : static PropertyInfo sNativeProperties_propertyInfos[7];
890 :
891 : static const NativePropertiesN<1> sNativeProperties = {
892 : true, 0 /* sStaticMethods */,
893 : false, 0,
894 : false, 0,
895 : false, 0,
896 : false, 0,
897 : false, 0,
898 : false, 0,
899 : -1,
900 : 7,
901 : sNativeProperties_sortedPropertyIndices,
902 : {
903 : { sStaticMethods, &sNativeProperties_propertyInfos[0] }
904 : }
905 : };
906 : static_assert(7 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
907 : "We have a property info count that is oversized");
908 :
909 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
910 : {
911 : "Function",
912 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
913 : &sBoringInterfaceObjectClassClassOps,
914 : JS_NULL_CLASS_SPEC,
915 : JS_NULL_CLASS_EXT,
916 : &sInterfaceObjectClassObjectOps
917 : },
918 : eInterface,
919 : false,
920 : prototypes::id::_ID_Count,
921 : 0,
922 : sNativePropertyHooks,
923 : "function ThreadSafeChromeUtils() {\n [native code]\n}",
924 : JS::GetRealmFunctionPrototype
925 : };
926 :
927 : bool
928 1 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
929 : {
930 1 : return nsContentUtils::ThreadsafeIsSystemCaller(aCx);
931 : }
932 :
933 : JSObject*
934 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
935 : {
936 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
937 : }
938 :
939 : const NativePropertyHooks sNativePropertyHooks[] = { {
940 : nullptr,
941 : nullptr,
942 : nullptr,
943 : { sNativeProperties.Upcast(), nullptr },
944 : prototypes::id::_ID_Count,
945 : constructors::id::ThreadSafeChromeUtils,
946 : nullptr,
947 : &DefaultXrayExpandoObjectClass
948 : } };
949 :
950 : void
951 2 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
952 : {
953 4 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
954 2 : if (!constructorProto) {
955 0 : return;
956 : }
957 :
958 : static bool sIdsInited = false;
959 2 : if (!sIdsInited && NS_IsMainThread()) {
960 1 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
961 0 : return;
962 : }
963 1 : sIdsInited = true;
964 : }
965 :
966 2 : JS::Heap<JSObject*>* protoCache = nullptr;
967 2 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::ThreadSafeChromeUtils);
968 4 : dom::CreateInterfaceObjects(aCx, aGlobal, nullptr,
969 : nullptr, protoCache,
970 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
971 : interfaceCache,
972 : sNativeProperties.Upcast(),
973 : nullptr,
974 : "ThreadSafeChromeUtils", aDefineOnGlobal,
975 : nullptr,
976 2 : false);
977 : }
978 :
979 : JS::Handle<JSObject*>
980 2 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
981 : {
982 : /* Get the interface object for this class. This will create the object as
983 : needed. */
984 :
985 : /* Make sure our global is sane. Hopefully we can remove this sometime */
986 2 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
987 2 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
988 0 : return nullptr;
989 : }
990 :
991 : /* Check to see whether the interface objects are already installed */
992 2 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
993 2 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::ThreadSafeChromeUtils)) {
994 4 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
995 2 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
996 : }
997 :
998 : /*
999 : * The object might _still_ be null, but that's OK.
1000 : *
1001 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1002 : * traced by TraceProtoAndIfaceCache() and its contents are never
1003 : * changed after they have been set.
1004 : *
1005 : * Calling address() avoids the read read barrier that does gray
1006 : * unmarking, but it's not possible for the object to be gray here.
1007 : */
1008 :
1009 2 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::ThreadSafeChromeUtils);
1010 2 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1011 2 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1012 : }
1013 :
1014 : JSObject*
1015 1 : GetConstructorObject(JSContext* aCx)
1016 : {
1017 1 : return GetConstructorObjectHandle(aCx);
1018 : }
1019 :
1020 : } // namespace ThreadSafeChromeUtilsBinding
1021 :
1022 :
1023 :
1024 : } // namespace dom
1025 : } // namespace mozilla
|