Coverage Report

Created: 2018-09-25 14:53

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