LCOV - code coverage report
Current view: top level - obj-x86_64-pc-linux-gnu/dom/bindings - PushManagerBinding.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 24 877 2.7 %
Date: 2017-07-14 16:53:18 Functions: 4 79 5.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* THIS FILE IS AUTOGENERATED FROM PushManager.webidl BY Codegen.py - DO NOT EDIT */
       2             : 
       3             : #include "AtomList.h"
       4             : #include "PushManagerBinding.h"
       5             : #include "WrapperFactory.h"
       6             : #include "jsapi.h"
       7             : #include "mozilla/OwningNonNull.h"
       8             : #include "mozilla/UseCounter.h"
       9             : #include "mozilla/dom/BindingUtils.h"
      10             : #include "mozilla/dom/DOMJSClass.h"
      11             : #include "mozilla/dom/NonRefcountedDOMObject.h"
      12             : #include "mozilla/dom/Promise.h"
      13             : #include "mozilla/dom/PushManager.h"
      14             : #include "mozilla/dom/ScriptSettings.h"
      15             : #include "mozilla/dom/ToJSValue.h"
      16             : #include "mozilla/dom/UnionConversions.h"
      17             : #include "mozilla/dom/XrayExpandoClass.h"
      18             : #include "nsContentUtils.h"
      19             : #include "nsIGlobalObject.h"
      20             : 
      21             : namespace mozilla {
      22             : namespace dom {
      23             : 
      24             : namespace PushPermissionStateValues {
      25             : extern const EnumEntry strings[4] = {
      26             :   {"granted", 7},
      27             :   {"denied", 6},
      28             :   {"prompt", 6},
      29             :   { nullptr, 0 }
      30             : };
      31             : } // namespace PushPermissionStateValues
      32             : 
      33             : bool
      34           0 : ToJSValue(JSContext* aCx, PushPermissionState aArgument, JS::MutableHandle<JS::Value> aValue)
      35             : {
      36           0 :   MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(PushPermissionStateValues::strings));
      37             :   JSString* resultStr =
      38           0 :     JS_NewStringCopyN(aCx, PushPermissionStateValues::strings[uint32_t(aArgument)].value,
      39           0 :                       PushPermissionStateValues::strings[uint32_t(aArgument)].length);
      40           0 :   if (!resultStr) {
      41           0 :     return false;
      42             :   }
      43           0 :   aValue.setString(resultStr);
      44           0 :   return true;
      45             : }
      46             : 
      47             : 
      48             : bool
      49           0 : ArrayBufferViewOrArrayBufferOrString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
      50             : {
      51           0 :   switch (mType) {
      52             :     case eUninitialized: {
      53           0 :       return false;
      54             :       break;
      55             :     }
      56             :     case eArrayBufferView: {
      57           0 :       rval.setObject(*mValue.mArrayBufferView.Value().Obj());
      58           0 :       if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
      59           0 :         return false;
      60             :       }
      61           0 :       return true;
      62             :       break;
      63             :     }
      64             :     case eArrayBuffer: {
      65           0 :       rval.setObject(*mValue.mArrayBuffer.Value().Obj());
      66           0 :       if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
      67           0 :         return false;
      68             :       }
      69           0 :       return true;
      70             :       break;
      71             :     }
      72             :     case eString: {
      73           0 :       if (!xpc::NonVoidStringToJsval(cx, mValue.mString.Value(), rval)) {
      74           0 :         return false;
      75             :       }
      76           0 :       return true;
      77             :       break;
      78             :     }
      79             :     default: {
      80           0 :       return false;
      81             :       break;
      82             :     }
      83             :   }
      84             : 
      85             :   return false;
      86             : }
      87             : 
      88             : 
      89             : ArrayBufferView&
      90           0 : OwningArrayBufferViewOrArrayBufferOrString::RawSetAsArrayBufferView()
      91             : {
      92           0 :   if (mType == eArrayBufferView) {
      93           0 :     return mValue.mArrayBufferView.Value();
      94             :   }
      95           0 :   MOZ_ASSERT(mType == eUninitialized);
      96           0 :   mType = eArrayBufferView;
      97           0 :   return mValue.mArrayBufferView.SetValue();
      98             : }
      99             : 
     100             : ArrayBufferView&
     101           0 : OwningArrayBufferViewOrArrayBufferOrString::SetAsArrayBufferView()
     102             : {
     103           0 :   if (mType == eArrayBufferView) {
     104           0 :     return mValue.mArrayBufferView.Value();
     105             :   }
     106           0 :   Uninit();
     107           0 :   mType = eArrayBufferView;
     108           0 :   return mValue.mArrayBufferView.SetValue();
     109             : }
     110             : 
     111             : bool
     112           0 : OwningArrayBufferViewOrArrayBufferOrString::TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
     113             : {
     114           0 :   tryNext = false;
     115             :   { // scope for memberSlot
     116           0 :     ArrayBufferView& memberSlot = RawSetAsArrayBufferView();
     117           0 :     if (!memberSlot.Init(&value.toObject())) {
     118           0 :       DestroyArrayBufferView();
     119           0 :       tryNext = true;
     120           0 :       return true;
     121             :     }
     122             :   }
     123           0 :   return true;
     124             : }
     125             : 
     126             : void
     127           0 : OwningArrayBufferViewOrArrayBufferOrString::DestroyArrayBufferView()
     128             : {
     129           0 :   MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
     130           0 :   mValue.mArrayBufferView.Destroy();
     131           0 :   mType = eUninitialized;
     132           0 : }
     133             : 
     134             : 
     135             : 
     136             : 
     137             : ArrayBuffer&
     138           0 : OwningArrayBufferViewOrArrayBufferOrString::RawSetAsArrayBuffer()
     139             : {
     140           0 :   if (mType == eArrayBuffer) {
     141           0 :     return mValue.mArrayBuffer.Value();
     142             :   }
     143           0 :   MOZ_ASSERT(mType == eUninitialized);
     144           0 :   mType = eArrayBuffer;
     145           0 :   return mValue.mArrayBuffer.SetValue();
     146             : }
     147             : 
     148             : ArrayBuffer&
     149           0 : OwningArrayBufferViewOrArrayBufferOrString::SetAsArrayBuffer()
     150             : {
     151           0 :   if (mType == eArrayBuffer) {
     152           0 :     return mValue.mArrayBuffer.Value();
     153             :   }
     154           0 :   Uninit();
     155           0 :   mType = eArrayBuffer;
     156           0 :   return mValue.mArrayBuffer.SetValue();
     157             : }
     158             : 
     159             : bool
     160           0 : OwningArrayBufferViewOrArrayBufferOrString::TrySetToArrayBuffer(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
     161             : {
     162           0 :   tryNext = false;
     163             :   { // scope for memberSlot
     164           0 :     ArrayBuffer& memberSlot = RawSetAsArrayBuffer();
     165           0 :     if (!memberSlot.Init(&value.toObject())) {
     166           0 :       DestroyArrayBuffer();
     167           0 :       tryNext = true;
     168           0 :       return true;
     169             :     }
     170             :   }
     171           0 :   return true;
     172             : }
     173             : 
     174             : void
     175           0 : OwningArrayBufferViewOrArrayBufferOrString::DestroyArrayBuffer()
     176             : {
     177           0 :   MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
     178           0 :   mValue.mArrayBuffer.Destroy();
     179           0 :   mType = eUninitialized;
     180           0 : }
     181             : 
     182             : 
     183             : 
     184             : 
     185             : nsString&
     186           0 : OwningArrayBufferViewOrArrayBufferOrString::RawSetAsString()
     187             : {
     188           0 :   if (mType == eString) {
     189           0 :     return mValue.mString.Value();
     190             :   }
     191           0 :   MOZ_ASSERT(mType == eUninitialized);
     192           0 :   mType = eString;
     193           0 :   return mValue.mString.SetValue();
     194             : }
     195             : 
     196             : nsString&
     197           0 : OwningArrayBufferViewOrArrayBufferOrString::SetAsString()
     198             : {
     199           0 :   if (mType == eString) {
     200           0 :     return mValue.mString.Value();
     201             :   }
     202           0 :   Uninit();
     203           0 :   mType = eString;
     204           0 :   return mValue.mString.SetValue();
     205             : }
     206             : 
     207             : bool
     208           0 : OwningArrayBufferViewOrArrayBufferOrString::TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
     209             : {
     210           0 :   tryNext = false;
     211             :   { // scope for memberSlot
     212           0 :     nsString& memberSlot = RawSetAsString();
     213           0 :     if (!ConvertJSValueToString(cx, value, eStringify, eStringify, memberSlot)) {
     214           0 :       return false;
     215             :     }
     216             :   }
     217           0 :   return true;
     218             : }
     219             : 
     220             : 
     221             : void
     222           0 : OwningArrayBufferViewOrArrayBufferOrString::DestroyString()
     223             : {
     224           0 :   MOZ_ASSERT(IsString(), "Wrong type!");
     225           0 :   mValue.mString.Destroy();
     226           0 :   mType = eUninitialized;
     227           0 : }
     228             : 
     229             : 
     230             : 
     231             : 
     232             : void
     233           0 : OwningArrayBufferViewOrArrayBufferOrString::Uninit()
     234             : {
     235           0 :   switch (mType) {
     236             :     case eUninitialized: {
     237           0 :       break;
     238             :     }
     239             :     case eArrayBufferView: {
     240           0 :       DestroyArrayBufferView();
     241           0 :       break;
     242             :     }
     243             :     case eArrayBuffer: {
     244           0 :       DestroyArrayBuffer();
     245           0 :       break;
     246             :     }
     247             :     case eString: {
     248           0 :       DestroyString();
     249           0 :       break;
     250             :     }
     251             :   }
     252           0 : }
     253             : 
     254             : bool
     255           0 : OwningArrayBufferViewOrArrayBufferOrString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
     256             : {
     257           0 :   switch (mType) {
     258             :     case eUninitialized: {
     259           0 :       return false;
     260             :       break;
     261             :     }
     262             :     case eArrayBufferView: {
     263           0 :       rval.setObject(*mValue.mArrayBufferView.Value().Obj());
     264           0 :       if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
     265           0 :         return false;
     266             :       }
     267           0 :       return true;
     268             :       break;
     269             :     }
     270             :     case eArrayBuffer: {
     271           0 :       rval.setObject(*mValue.mArrayBuffer.Value().Obj());
     272           0 :       if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
     273           0 :         return false;
     274             :       }
     275           0 :       return true;
     276             :       break;
     277             :     }
     278             :     case eString: {
     279           0 :       if (!xpc::NonVoidStringToJsval(cx, mValue.mString.Value(), rval)) {
     280           0 :         return false;
     281             :       }
     282           0 :       return true;
     283             :       break;
     284             :     }
     285             :     default: {
     286           0 :       return false;
     287             :       break;
     288             :     }
     289             :   }
     290             : 
     291             :   return false;
     292             : }
     293             : 
     294             : void
     295           0 : OwningArrayBufferViewOrArrayBufferOrString::TraceUnion(JSTracer* trc)
     296             : {
     297           0 :   switch (mType) {
     298             :     case eArrayBufferView: {
     299           0 :       mValue.mArrayBufferView.Value().TraceSelf(trc);
     300           0 :       break;
     301             :     }
     302             :     case eArrayBuffer: {
     303           0 :       mValue.mArrayBuffer.Value().TraceSelf(trc);
     304           0 :       break;
     305             :     }
     306             :     default: {
     307           0 :       break;
     308             :     }
     309             :   }
     310           0 : }
     311             : 
     312             : 
     313             : 
     314           0 : PushSubscriptionOptionsInit::PushSubscriptionOptionsInit()
     315             : {
     316             :   // Safe to pass a null context if we pass a null value
     317           0 :   Init(nullptr, JS::NullHandleValue);
     318           0 : }
     319             : 
     320             : 
     321             : bool
     322           0 : PushSubscriptionOptionsInit::InitIds(JSContext* cx, PushSubscriptionOptionsInitAtoms* atomsCache)
     323             : {
     324           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
     325             : 
     326             :   // Initialize these in reverse order so that any failure leaves the first one
     327             :   // uninitialized.
     328           0 :   if (!atomsCache->applicationServerKey_id.init(cx, "applicationServerKey")) {
     329           0 :     return false;
     330             :   }
     331           0 :   return true;
     332             : }
     333             : 
     334             : bool
     335           0 : PushSubscriptionOptionsInit::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
     336             : {
     337             :   // Passing a null JSContext is OK only if we're initing from null,
     338             :   // Since in that case we will not have to do any property gets
     339             :   // Also evaluate isNullOrUndefined in order to avoid false-positive
     340             :   // checkers by static analysis tools
     341           0 :   MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
     342           0 :   PushSubscriptionOptionsInitAtoms* atomsCache = nullptr;
     343           0 :   if (cx) {
     344           0 :     atomsCache = GetAtomCache<PushSubscriptionOptionsInitAtoms>(cx);
     345           0 :     if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     346           0 :       return false;
     347             :     }
     348             :   }
     349             : 
     350           0 :   if (!IsConvertibleToDictionary(val)) {
     351           0 :     return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
     352             :   }
     353             : 
     354           0 :   bool isNull = val.isNullOrUndefined();
     355             :   // We only need these if !isNull, in which case we have |cx|.
     356           0 :   Maybe<JS::Rooted<JSObject *> > object;
     357           0 :   Maybe<JS::Rooted<JS::Value> > temp;
     358           0 :   if (!isNull) {
     359           0 :     MOZ_ASSERT(cx);
     360           0 :     object.emplace(cx, &val.toObject());
     361           0 :     temp.emplace(cx);
     362             :   }
     363           0 :   if (!isNull) {
     364           0 :     if (!JS_GetPropertyById(cx, *object, atomsCache->applicationServerKey_id, temp.ptr())) {
     365           0 :       return false;
     366             :     }
     367             :   }
     368           0 :   if (!(!isNull && !temp->isUndefined()) || temp.ref().isNullOrUndefined()) {
     369           0 :     mApplicationServerKey.SetNull();
     370             :   } else {
     371             :     {
     372           0 :       bool done = false, failed = false, tryNext;
     373           0 :       if (temp.ref().isObject()) {
     374           0 :         done = (failed = !mApplicationServerKey.SetValue().TrySetToArrayBufferView(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext ||
     375           0 :                (failed = !mApplicationServerKey.SetValue().TrySetToArrayBuffer(cx, temp.ref(), tryNext, passedToJSImpl)) || !tryNext;
     376             : 
     377             :       }
     378           0 :       if (!done) {
     379             :         do {
     380           0 :           done = (failed = !mApplicationServerKey.SetValue().TrySetToString(cx, temp.ref(), tryNext)) || !tryNext;
     381           0 :           break;
     382             :         } while (0);
     383             :       }
     384           0 :       if (failed) {
     385           0 :         return false;
     386             :       }
     387           0 :       if (!done) {
     388           0 :         ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "'applicationServerKey' member of PushSubscriptionOptionsInit", "ArrayBufferView, ArrayBuffer");
     389           0 :         return false;
     390             :       }
     391             :     }
     392             :   }
     393           0 :   mIsAnyMemberPresent = true;
     394           0 :   return true;
     395             : }
     396             : 
     397             : bool
     398           0 : PushSubscriptionOptionsInit::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
     399             : {
     400           0 :   PushSubscriptionOptionsInitAtoms* atomsCache = GetAtomCache<PushSubscriptionOptionsInitAtoms>(cx);
     401           0 :   if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
     402           0 :     return false;
     403             :   }
     404             : 
     405           0 :   JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
     406           0 :   if (!obj) {
     407           0 :     return false;
     408             :   }
     409           0 :   rval.set(JS::ObjectValue(*obj));
     410             : 
     411             :   do {
     412             :     // block for our 'break' successCode and scope for 'temp' and 'currentValue'
     413           0 :     JS::Rooted<JS::Value> temp(cx);
     414           0 :     Nullable<OwningArrayBufferViewOrArrayBufferOrString > const & currentValue = mApplicationServerKey;
     415           0 :     if (currentValue.IsNull()) {
     416           0 :       temp.setNull();
     417           0 :       if (!JS_DefinePropertyById(cx, obj, atomsCache->applicationServerKey_id, temp, JSPROP_ENUMERATE)) {
     418           0 :         return false;
     419             :       }
     420           0 :       break;
     421             :     }
     422           0 :     if (!currentValue.Value().ToJSVal(cx, obj, &temp)) {
     423           0 :       return false;
     424             :     }
     425           0 :     if (!JS_DefinePropertyById(cx, obj, atomsCache->applicationServerKey_id, temp, JSPROP_ENUMERATE)) {
     426           0 :       return false;
     427             :     }
     428           0 :     break;
     429             :   } while(0);
     430             : 
     431           0 :   return true;
     432             : }
     433             : 
     434             : void
     435           0 : PushSubscriptionOptionsInit::TraceDictionary(JSTracer* trc)
     436             : {
     437           0 :   if (!mApplicationServerKey.IsNull()) {
     438           0 :     mApplicationServerKey.Value().TraceUnion(trc);
     439             :   }
     440           0 : }
     441             : 
     442             : namespace binding_detail {
     443             : } // namespace binding_detail
     444             : 
     445             : 
     446             : namespace PushManagerBinding {
     447             : 
     448             : static bool
     449           0 : subscribe(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManager* self, const JSJitMethodCallArgs& args)
     450             : {
     451           0 :   RootedDictionary<binding_detail::FastPushSubscriptionOptionsInit> arg0(cx);
     452           0 :   if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue,  "Argument 1 of PushManager.subscribe", false)) {
     453           0 :     return false;
     454             :   }
     455           0 :   binding_detail::FastErrorResult rv;
     456           0 :   auto result(StrongOrRawPtr<Promise>(self->Subscribe(Constify(arg0), rv)));
     457           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
     458           0 :     return false;
     459             :   }
     460           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
     461           0 :   SetDocumentAndPageUseCounter(cx, obj, eUseCounter_PushManager_subscribe);
     462           0 :   if (!ToJSValue(cx, result, args.rval())) {
     463           0 :     return false;
     464             :   }
     465           0 :   return true;
     466             : }
     467             : 
     468             : static bool
     469           0 : subscribe_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManager* self, const JSJitMethodCallArgs& args)
     470             : {
     471             :   // Make sure to save the callee before someone maybe messes
     472             :   // with rval().
     473           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
     474           0 :   bool ok = subscribe(cx, obj, self, args);
     475           0 :   if (ok) {
     476           0 :     return true;
     477             :   }
     478           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
     479           0 :                                    args.rval());
     480             : }
     481             : 
     482             : static const JSJitInfo subscribe_methodinfo = {
     483             :   { (JSJitGetterOp)subscribe_promiseWrapper },
     484             :   { prototypes::id::PushManager },
     485             :   { PrototypeTraits<prototypes::id::PushManager>::Depth },
     486             :   JSJitInfo::Method,
     487             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
     488             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
     489             :   false,  /* isInfallible. False in setters. */
     490             :   false,  /* isMovable.  Not relevant for setters. */
     491             :   false, /* isEliminatable.  Not relevant for setters. */
     492             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
     493             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
     494             :   false,  /* isTypedMethod.  Only relevant for methods. */
     495             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
     496             : };
     497             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
     498             : static_assert(0 < 1, "There is no slot for us");
     499             : 
     500             : static bool
     501           0 : getSubscription(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManager* self, const JSJitMethodCallArgs& args)
     502             : {
     503           0 :   binding_detail::FastErrorResult rv;
     504           0 :   auto result(StrongOrRawPtr<Promise>(self->GetSubscription(rv)));
     505           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
     506           0 :     return false;
     507             :   }
     508           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
     509           0 :   if (!ToJSValue(cx, result, args.rval())) {
     510           0 :     return false;
     511             :   }
     512           0 :   return true;
     513             : }
     514             : 
     515             : static bool
     516           0 : getSubscription_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManager* self, const JSJitMethodCallArgs& args)
     517             : {
     518             :   // Make sure to save the callee before someone maybe messes
     519             :   // with rval().
     520           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
     521           0 :   bool ok = getSubscription(cx, obj, self, args);
     522           0 :   if (ok) {
     523           0 :     return true;
     524             :   }
     525           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
     526           0 :                                    args.rval());
     527             : }
     528             : 
     529             : static const JSJitInfo getSubscription_methodinfo = {
     530             :   { (JSJitGetterOp)getSubscription_promiseWrapper },
     531             :   { prototypes::id::PushManager },
     532             :   { PrototypeTraits<prototypes::id::PushManager>::Depth },
     533             :   JSJitInfo::Method,
     534             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
     535             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
     536             :   false,  /* isInfallible. False in setters. */
     537             :   false,  /* isMovable.  Not relevant for setters. */
     538             :   false, /* isEliminatable.  Not relevant for setters. */
     539             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
     540             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
     541             :   false,  /* isTypedMethod.  Only relevant for methods. */
     542             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
     543             : };
     544             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
     545             : static_assert(0 < 1, "There is no slot for us");
     546             : 
     547             : static bool
     548           0 : permissionState(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManager* self, const JSJitMethodCallArgs& args)
     549             : {
     550           0 :   RootedDictionary<binding_detail::FastPushSubscriptionOptionsInit> arg0(cx);
     551           0 :   if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue,  "Argument 1 of PushManager.permissionState", false)) {
     552           0 :     return false;
     553             :   }
     554           0 :   binding_detail::FastErrorResult rv;
     555           0 :   auto result(StrongOrRawPtr<Promise>(self->PermissionState(Constify(arg0), rv)));
     556           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
     557           0 :     return false;
     558             :   }
     559           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
     560           0 :   if (!ToJSValue(cx, result, args.rval())) {
     561           0 :     return false;
     562             :   }
     563           0 :   return true;
     564             : }
     565             : 
     566             : static bool
     567           0 : permissionState_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManager* self, const JSJitMethodCallArgs& args)
     568             : {
     569             :   // Make sure to save the callee before someone maybe messes
     570             :   // with rval().
     571           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
     572           0 :   bool ok = permissionState(cx, obj, self, args);
     573           0 :   if (ok) {
     574           0 :     return true;
     575             :   }
     576           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
     577           0 :                                    args.rval());
     578             : }
     579             : 
     580             : static const JSJitInfo permissionState_methodinfo = {
     581             :   { (JSJitGetterOp)permissionState_promiseWrapper },
     582             :   { prototypes::id::PushManager },
     583             :   { PrototypeTraits<prototypes::id::PushManager>::Depth },
     584             :   JSJitInfo::Method,
     585             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
     586             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
     587             :   false,  /* isInfallible. False in setters. */
     588             :   false,  /* isMovable.  Not relevant for setters. */
     589             :   false, /* isEliminatable.  Not relevant for setters. */
     590             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
     591             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
     592             :   false,  /* isTypedMethod.  Only relevant for methods. */
     593             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
     594             : };
     595             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
     596             : static_assert(0 < 1, "There is no slot for us");
     597             : 
     598             : static bool
     599           0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
     600             : {
     601           0 :   mozilla::dom::PushManager* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushManager>(obj);
     602             :   // We don't want to preserve if we don't have a wrapper, and we
     603             :   // obviously can't preserve if we're not initialized.
     604           0 :   if (self && self->GetWrapperPreserveColor()) {
     605           0 :     PreserveWrapper(self);
     606             :   }
     607           0 :   return true;
     608             : }
     609             : 
     610             : static void
     611           0 : _finalize(js::FreeOp* fop, JSObject* obj)
     612             : {
     613           0 :   mozilla::dom::PushManager* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushManager>(obj);
     614           0 :   if (self) {
     615           0 :     ClearWrapper(self, self, obj);
     616           0 :     AddForDeferredFinalization<mozilla::dom::PushManager>(self);
     617             :   }
     618           0 : }
     619             : 
     620             : static void
     621           0 : _objectMoved(JSObject* obj, const JSObject* old)
     622             : {
     623           0 :   mozilla::dom::PushManager* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushManager>(obj);
     624           0 :   if (self) {
     625           0 :     UpdateWrapper(self, self, obj, old);
     626             :   }
     627           0 : }
     628             : 
     629             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
     630             : #if defined(__clang__)
     631             : #pragma clang diagnostic push
     632             : #pragma clang diagnostic ignored "-Wmissing-braces"
     633             : #endif
     634             : static const JSFunctionSpec sMethods_specs[] = {
     635             :   JS_FNSPEC("subscribe", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&subscribe_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
     636             :   JS_FNSPEC("getSubscription", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&getSubscription_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
     637             :   JS_FNSPEC("permissionState", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&permissionState_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
     638             :   JS_FS_END
     639             : };
     640             : #if defined(__clang__)
     641             : #pragma clang diagnostic pop
     642             : #endif
     643             : 
     644             : 
     645             : // Can't be const because the pref-enabled boolean needs to be writable
     646             : static Prefable<const JSFunctionSpec> sMethods[] = {
     647             :   { nullptr, &sMethods_specs[0] },
     648             :   { nullptr, nullptr }
     649             : };
     650             : 
     651             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
     652             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
     653             : static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
     654             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
     655             : 
     656             : 
     657             : static uint16_t sNativeProperties_sortedPropertyIndices[3];
     658             : static PropertyInfo sNativeProperties_propertyInfos[3];
     659             : 
     660             : static const NativePropertiesN<1> sNativeProperties = {
     661             :   false, 0,
     662             :   false, 0,
     663             :   true,  0 /* sMethods */,
     664             :   false, 0,
     665             :   false, 0,
     666             :   false, 0,
     667             :   false, 0,
     668             :   -1,
     669             :   3,
     670             :   sNativeProperties_sortedPropertyIndices,
     671             :   {
     672             :     { sMethods, &sNativeProperties_propertyInfos[0] }
     673             :   }
     674             : };
     675             : static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
     676             :     "We have a property info count that is oversized");
     677             : 
     678             : static bool
     679           0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
     680             : {
     681           0 :   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     682           0 :   JS::Rooted<JSObject*> obj(cx, &args.callee());
     683           0 :   if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
     684           0 :     return ThrowingConstructor(cx, argc, vp);
     685             :   }
     686             : 
     687           0 :   if (!args.isConstructing()) {
     688             :     // XXXbz wish I could get the name from the callee instead of
     689             :     // Adding more relocations
     690           0 :     return ThrowConstructorWithoutNew(cx, "PushManager");
     691             :   }
     692             : 
     693           0 :   GlobalObject global(cx, obj);
     694           0 :   if (global.Failed()) {
     695           0 :     return false;
     696             :   }
     697             : 
     698           0 :   JS::Rooted<JSObject*> desiredProto(cx);
     699           0 :   if (!GetDesiredProto(cx, args, &desiredProto)) {
     700           0 :     return false;
     701             :   }
     702             : 
     703           0 :   if (MOZ_UNLIKELY(args.length() < 1)) {
     704           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "PushManager");
     705             :   }
     706           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
     707           0 :   binding_detail::FakeString arg0;
     708           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
     709           0 :     return false;
     710             :   }
     711           0 :   Maybe<JSAutoCompartment> ac;
     712           0 :   if (objIsXray) {
     713           0 :     obj = js::CheckedUnwrap(obj);
     714           0 :     if (!obj) {
     715           0 :       return false;
     716             :     }
     717           0 :     ac.emplace(cx, obj);
     718           0 :     if (!JS_WrapObject(cx, &desiredProto)) {
     719           0 :       return false;
     720             :     }
     721             :   }
     722           0 :   binding_detail::FastErrorResult rv;
     723           0 :   auto result(StrongOrRawPtr<mozilla::dom::PushManager>(mozilla::dom::PushManager::Constructor(global, NonNullHelper(Constify(arg0)), rv)));
     724           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
     725           0 :     return false;
     726             :   }
     727           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
     728             :   static_assert(!IsPointer<decltype(result)>::value,
     729             :                 "NewObject implies that we need to keep the object alive with a strong reference.");
     730           0 :   if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
     731           0 :     MOZ_ASSERT(true || JS_IsExceptionPending(cx));
     732           0 :     return false;
     733             :   }
     734           0 :   return true;
     735             : }
     736             : 
     737             : static const js::ClassOps sInterfaceObjectClassOps = {
     738             :     nullptr,               /* addProperty */
     739             :     nullptr,               /* delProperty */
     740             :     nullptr,               /* getProperty */
     741             :     nullptr,               /* setProperty */
     742             :     nullptr,               /* enumerate */
     743             :     nullptr,               /* newEnumerate */
     744             :     nullptr,               /* resolve */
     745             :     nullptr,               /* mayResolve */
     746             :     nullptr,               /* finalize */
     747             :     _constructor, /* call */
     748             :     nullptr,               /* hasInstance */
     749             :     _constructor, /* construct */
     750             :     nullptr,               /* trace */
     751             : };
     752             : 
     753             : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
     754             :   {
     755             :     "Function",
     756             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
     757             :     &sInterfaceObjectClassOps,
     758             :     JS_NULL_CLASS_SPEC,
     759             :     JS_NULL_CLASS_EXT,
     760             :     &sInterfaceObjectClassObjectOps
     761             :   },
     762             :   eInterface,
     763             :   true,
     764             :   prototypes::id::PushManager,
     765             :   PrototypeTraits<prototypes::id::PushManager>::Depth,
     766             :   sNativePropertyHooks,
     767             :   "function PushManager() {\n    [native code]\n}",
     768             :   JS::GetRealmFunctionPrototype
     769             : };
     770             : 
     771             : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
     772             :   {
     773             :     "PushManagerPrototype",
     774             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
     775             :     JS_NULL_CLASS_OPS,
     776             :     JS_NULL_CLASS_SPEC,
     777             :     JS_NULL_CLASS_EXT,
     778             :     JS_NULL_OBJECT_OPS
     779             :   },
     780             :   eInterfacePrototype,
     781             :   false,
     782             :   prototypes::id::PushManager,
     783             :   PrototypeTraits<prototypes::id::PushManager>::Depth,
     784             :   sNativePropertyHooks,
     785             :   "[object PushManagerPrototype]",
     786             :   JS::GetRealmObjectPrototype
     787             : };
     788             : 
     789             : bool
     790           1 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
     791             : {
     792           1 :   return nsContentUtils::PushEnabled(aCx, aObj);
     793             : }
     794             : 
     795             : JSObject*
     796           0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
     797             : {
     798           0 :   return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
     799             : }
     800             : 
     801             : static const js::ClassOps sClassOps = {
     802             :   _addProperty, /* addProperty */
     803             :   nullptr,               /* delProperty */
     804             :   nullptr,               /* getProperty */
     805             :   nullptr,               /* setProperty */
     806             :   nullptr,               /* enumerate */
     807             :   nullptr, /* newEnumerate */
     808             :   nullptr, /* resolve */
     809             :   nullptr, /* mayResolve */
     810             :   _finalize, /* finalize */
     811             :   nullptr, /* call */
     812             :   nullptr,               /* hasInstance */
     813             :   nullptr,               /* construct */
     814             :   nullptr, /* trace */
     815             : };
     816             : 
     817             : static const js::ClassExtension sClassExtension = {
     818             :   nullptr, /* weakmapKeyDelegateOp */
     819             :   _objectMoved /* objectMovedOp */
     820             : };
     821             : 
     822             : static const DOMJSClass sClass = {
     823             :   { "PushManager",
     824             :     JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
     825             :     &sClassOps,
     826             :     JS_NULL_CLASS_SPEC,
     827             :     &sClassExtension,
     828             :     JS_NULL_OBJECT_OPS
     829             :   },
     830             :   { prototypes::id::PushManager, 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 },
     831             :   IsBaseOf<nsISupports, mozilla::dom::PushManager >::value,
     832             :   sNativePropertyHooks,
     833             :   FindAssociatedGlobalForNative<mozilla::dom::PushManager>::Get,
     834             :   GetProtoObjectHandle,
     835             :   GetCCParticipant<mozilla::dom::PushManager>::Get()
     836             : };
     837             : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
     838             :               "Must have the right minimal number of reserved slots.");
     839             : static_assert(1 >= 1,
     840             :               "Must have enough reserved slots.");
     841             : 
     842             : const JSClass*
     843           0 : GetJSClass()
     844             : {
     845           0 :   return sClass.ToJSClass();
     846             : }
     847             : 
     848             : bool
     849           0 : Wrap(JSContext* aCx, mozilla::dom::PushManager* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
     850             : {
     851             :   MOZ_ASSERT(static_cast<mozilla::dom::PushManager*>(aObject) ==
     852             :              reinterpret_cast<mozilla::dom::PushManager*>(aObject),
     853             :              "Multiple inheritance for mozilla::dom::PushManager is broken.");
     854           0 :   MOZ_ASSERT(ToSupportsIsCorrect(aObject));
     855           0 :   MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
     856           0 :   MOZ_ASSERT(!aCache->GetWrapper(),
     857             :              "You should probably not be using Wrap() directly; use "
     858             :              "GetOrCreateDOMReflector instead");
     859             : 
     860           0 :   MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
     861             :              "nsISupports must be on our primary inheritance chain");
     862             : 
     863           0 :   JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
     864           0 :   if (!global) {
     865           0 :     return false;
     866             :   }
     867           0 :   MOZ_ASSERT(JS_IsGlobalObject(global));
     868           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(global));
     869             : 
     870             :   // That might have ended up wrapping us already, due to the wonders
     871             :   // of XBL.  Check for that, and bail out as needed.
     872           0 :   aReflector.set(aCache->GetWrapper());
     873           0 :   if (aReflector) {
     874             : #ifdef DEBUG
     875           0 :     binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
     876             : #endif // DEBUG
     877           0 :     return true;
     878             :   }
     879             : 
     880           0 :   JSAutoCompartment ac(aCx, global);
     881           0 :   JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
     882           0 :   if (!canonicalProto) {
     883           0 :     return false;
     884             :   }
     885           0 :   JS::Rooted<JSObject*> proto(aCx);
     886           0 :   if (aGivenProto) {
     887           0 :     proto = aGivenProto;
     888             :     // Unfortunately, while aGivenProto was in the compartment of aCx
     889             :     // coming in, we changed compartments to that of "parent" so may need
     890             :     // to wrap the proto here.
     891           0 :     if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
     892           0 :       if (!JS_WrapObject(aCx, &proto)) {
     893           0 :         return false;
     894             :       }
     895             :     }
     896             :   } else {
     897           0 :     proto = canonicalProto;
     898             :   }
     899             : 
     900           0 :   BindingJSObjectCreator<mozilla::dom::PushManager> creator(aCx);
     901           0 :   creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
     902           0 :   if (!aReflector) {
     903           0 :     return false;
     904             :   }
     905             : 
     906           0 :   aCache->SetWrapper(aReflector);
     907           0 :   creator.InitializationSucceeded();
     908             : 
     909           0 :   MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
     910             :              aCache->GetWrapperPreserveColor() == aReflector);
     911             :   // If proto != canonicalProto, we have to preserve our wrapper;
     912             :   // otherwise we won't be able to properly recreate it later, since
     913             :   // we won't know what proto to use.  Note that we don't check
     914             :   // aGivenProto here, since it's entirely possible (and even
     915             :   // somewhat common) to have a non-null aGivenProto which is the
     916             :   // same as canonicalProto.
     917           0 :   if (proto != canonicalProto) {
     918           0 :     PreserveWrapper(aObject);
     919             :   }
     920             : 
     921           0 :   return true;
     922             : }
     923             : 
     924             : const NativePropertyHooks sNativePropertyHooks[] = { {
     925             :   nullptr,
     926             :   nullptr,
     927             :   nullptr,
     928             :   { sNativeProperties.Upcast(), nullptr },
     929             :   prototypes::id::PushManager,
     930             :   constructors::id::PushManager,
     931             :   nullptr,
     932             :   &DefaultXrayExpandoObjectClass
     933             : } };
     934             : 
     935             : void
     936           1 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
     937             : {
     938           2 :   JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
     939           1 :   if (!parentProto) {
     940           0 :     return;
     941             :   }
     942             : 
     943           2 :   JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
     944           1 :   if (!constructorProto) {
     945           0 :     return;
     946             :   }
     947             : 
     948             :   static bool sIdsInited = false;
     949           1 :   if (!sIdsInited && NS_IsMainThread()) {
     950           0 :     if (!InitIds(aCx, sNativeProperties.Upcast())) {
     951           0 :       return;
     952             :     }
     953           0 :     sIdsInited = true;
     954             :   }
     955             : 
     956           1 :   JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::PushManager);
     957           1 :   JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::PushManager);
     958           2 :   dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
     959             :                               &sPrototypeClass.mBase, protoCache,
     960             :                               constructorProto, &sInterfaceObjectClass.mBase, 1, nullptr,
     961             :                               interfaceCache,
     962             :                               sNativeProperties.Upcast(),
     963             :                               nullptr,
     964             :                               "PushManager", aDefineOnGlobal,
     965             :                               nullptr,
     966           1 :                               false);
     967             : }
     968             : 
     969             : JS::Handle<JSObject*>
     970           0 : GetProtoObjectHandle(JSContext* aCx)
     971             : {
     972             :   /* Get the interface prototype object for this class.  This will create the
     973             :      object as needed. */
     974           0 :   bool aDefineOnGlobal = true;
     975             : 
     976             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
     977           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
     978           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
     979           0 :     return nullptr;
     980             :   }
     981             : 
     982             :   /* Check to see whether the interface objects are already installed */
     983           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
     984           0 :   if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::PushManager)) {
     985           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
     986           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
     987             :   }
     988             : 
     989             :   /*
     990             :    * The object might _still_ be null, but that's OK.
     991             :    *
     992             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
     993             :    * traced by TraceProtoAndIfaceCache() and its contents are never
     994             :    * changed after they have been set.
     995             :    *
     996             :    * Calling address() avoids the read read barrier that does gray
     997             :    * unmarking, but it's not possible for the object to be gray here.
     998             :    */
     999             : 
    1000           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::PushManager);
    1001           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    1002           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    1003             : }
    1004             : 
    1005             : JS::Handle<JSObject*>
    1006           1 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
    1007             : {
    1008             :   /* Get the interface object for this class.  This will create the object as
    1009             :      needed. */
    1010             : 
    1011             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    1012           1 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    1013           1 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    1014           0 :     return nullptr;
    1015             :   }
    1016             : 
    1017             :   /* Check to see whether the interface objects are already installed */
    1018           1 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    1019           1 :   if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::PushManager)) {
    1020           2 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    1021           1 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    1022             :   }
    1023             : 
    1024             :   /*
    1025             :    * The object might _still_ be null, but that's OK.
    1026             :    *
    1027             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    1028             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    1029             :    * changed after they have been set.
    1030             :    *
    1031             :    * Calling address() avoids the read read barrier that does gray
    1032             :    * unmarking, but it's not possible for the object to be gray here.
    1033             :    */
    1034             : 
    1035           1 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::PushManager);
    1036           1 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    1037           1 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    1038             : }
    1039             : 
    1040             : JSObject*
    1041           1 : GetConstructorObject(JSContext* aCx)
    1042             : {
    1043           1 :   return GetConstructorObjectHandle(aCx);
    1044             : }
    1045             : 
    1046             : } // namespace PushManagerBinding
    1047             : 
    1048             : 
    1049             : 
    1050             : namespace PushManagerImplBinding {
    1051             : 
    1052             : static bool
    1053           0 : subscribe(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManagerImpl* self, const JSJitMethodCallArgs& args)
    1054             : {
    1055           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    1056           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    1057           0 :   if (objIsXray) {
    1058           0 :     unwrappedObj.emplace(cx, obj);
    1059             :   }
    1060           0 :   RootedDictionary<binding_detail::FastPushSubscriptionOptionsInit> arg0(cx);
    1061           0 :   if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue,  "Argument 1 of PushManagerImpl.subscribe", true)) {
    1062           0 :     return false;
    1063             :   }
    1064           0 :   if (objIsXray) {
    1065           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    1066           0 :     if (!unwrappedObj.ref()) {
    1067           0 :       return false;
    1068             :     }
    1069             :   }
    1070           0 :   binding_detail::FastErrorResult rv;
    1071           0 :   auto result(StrongOrRawPtr<Promise>(self->Subscribe(Constify(arg0), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    1072           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1073           0 :     return false;
    1074             :   }
    1075           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1076           0 :   if (!ToJSValue(cx, result, args.rval())) {
    1077           0 :     return false;
    1078             :   }
    1079           0 :   return true;
    1080             : }
    1081             : 
    1082             : static bool
    1083           0 : subscribe_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManagerImpl* self, const JSJitMethodCallArgs& args)
    1084             : {
    1085             :   // Make sure to save the callee before someone maybe messes
    1086             :   // with rval().
    1087           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    1088           0 :   bool ok = subscribe(cx, obj, self, args);
    1089           0 :   if (ok) {
    1090           0 :     return true;
    1091             :   }
    1092           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    1093           0 :                                    args.rval());
    1094             : }
    1095             : 
    1096             : static const JSJitInfo subscribe_methodinfo = {
    1097             :   { (JSJitGetterOp)subscribe_promiseWrapper },
    1098             :   { prototypes::id::PushManagerImpl },
    1099             :   { PrototypeTraits<prototypes::id::PushManagerImpl>::Depth },
    1100             :   JSJitInfo::Method,
    1101             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    1102             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    1103             :   false,  /* isInfallible. False in setters. */
    1104             :   false,  /* isMovable.  Not relevant for setters. */
    1105             :   false, /* isEliminatable.  Not relevant for setters. */
    1106             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    1107             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    1108             :   false,  /* isTypedMethod.  Only relevant for methods. */
    1109             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    1110             : };
    1111             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    1112             : static_assert(0 < 1, "There is no slot for us");
    1113             : 
    1114             : static bool
    1115           0 : getSubscription(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManagerImpl* self, const JSJitMethodCallArgs& args)
    1116             : {
    1117           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    1118           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    1119           0 :   if (objIsXray) {
    1120           0 :     unwrappedObj.emplace(cx, obj);
    1121             :   }
    1122           0 :   if (objIsXray) {
    1123           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    1124           0 :     if (!unwrappedObj.ref()) {
    1125           0 :       return false;
    1126             :     }
    1127             :   }
    1128           0 :   binding_detail::FastErrorResult rv;
    1129           0 :   auto result(StrongOrRawPtr<Promise>(self->GetSubscription(rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    1130           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1131           0 :     return false;
    1132             :   }
    1133           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1134           0 :   if (!ToJSValue(cx, result, args.rval())) {
    1135           0 :     return false;
    1136             :   }
    1137           0 :   return true;
    1138             : }
    1139             : 
    1140             : static bool
    1141           0 : getSubscription_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManagerImpl* self, const JSJitMethodCallArgs& args)
    1142             : {
    1143             :   // Make sure to save the callee before someone maybe messes
    1144             :   // with rval().
    1145           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    1146           0 :   bool ok = getSubscription(cx, obj, self, args);
    1147           0 :   if (ok) {
    1148           0 :     return true;
    1149             :   }
    1150           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    1151           0 :                                    args.rval());
    1152             : }
    1153             : 
    1154             : static const JSJitInfo getSubscription_methodinfo = {
    1155             :   { (JSJitGetterOp)getSubscription_promiseWrapper },
    1156             :   { prototypes::id::PushManagerImpl },
    1157             :   { PrototypeTraits<prototypes::id::PushManagerImpl>::Depth },
    1158             :   JSJitInfo::Method,
    1159             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    1160             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    1161             :   false,  /* isInfallible. False in setters. */
    1162             :   false,  /* isMovable.  Not relevant for setters. */
    1163             :   false, /* isEliminatable.  Not relevant for setters. */
    1164             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    1165             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    1166             :   false,  /* isTypedMethod.  Only relevant for methods. */
    1167             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    1168             : };
    1169             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    1170             : static_assert(0 < 1, "There is no slot for us");
    1171             : 
    1172             : static bool
    1173           0 : permissionState(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManagerImpl* self, const JSJitMethodCallArgs& args)
    1174             : {
    1175           0 :   Maybe<JS::Rooted<JSObject*> > unwrappedObj;
    1176           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    1177           0 :   if (objIsXray) {
    1178           0 :     unwrappedObj.emplace(cx, obj);
    1179             :   }
    1180           0 :   RootedDictionary<binding_detail::FastPushSubscriptionOptionsInit> arg0(cx);
    1181           0 :   if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue,  "Argument 1 of PushManagerImpl.permissionState", true)) {
    1182           0 :     return false;
    1183             :   }
    1184           0 :   if (objIsXray) {
    1185           0 :     unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
    1186           0 :     if (!unwrappedObj.ref()) {
    1187           0 :       return false;
    1188             :     }
    1189             :   }
    1190           0 :   binding_detail::FastErrorResult rv;
    1191           0 :   auto result(StrongOrRawPtr<Promise>(self->PermissionState(Constify(arg0), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj))));
    1192           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1193           0 :     return false;
    1194             :   }
    1195           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1196           0 :   if (!ToJSValue(cx, result, args.rval())) {
    1197           0 :     return false;
    1198             :   }
    1199           0 :   return true;
    1200             : }
    1201             : 
    1202             : static bool
    1203           0 : permissionState_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::PushManagerImpl* self, const JSJitMethodCallArgs& args)
    1204             : {
    1205             :   // Make sure to save the callee before someone maybe messes
    1206             :   // with rval().
    1207           0 :   JS::Rooted<JSObject*> callee(cx, &args.callee());
    1208           0 :   bool ok = permissionState(cx, obj, self, args);
    1209           0 :   if (ok) {
    1210           0 :     return true;
    1211             :   }
    1212           0 :   return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
    1213           0 :                                    args.rval());
    1214             : }
    1215             : 
    1216             : static const JSJitInfo permissionState_methodinfo = {
    1217             :   { (JSJitGetterOp)permissionState_promiseWrapper },
    1218             :   { prototypes::id::PushManagerImpl },
    1219             :   { PrototypeTraits<prototypes::id::PushManagerImpl>::Depth },
    1220             :   JSJitInfo::Method,
    1221             :   JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
    1222             :   JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
    1223             :   false,  /* isInfallible. False in setters. */
    1224             :   false,  /* isMovable.  Not relevant for setters. */
    1225             :   false, /* isEliminatable.  Not relevant for setters. */
    1226             :   false, /* isAlwaysInSlot.  Only relevant for getters. */
    1227             :   false, /* isLazilyCachedInSlot.  Only relevant for getters. */
    1228             :   false,  /* isTypedMethod.  Only relevant for methods. */
    1229             :   0   /* Reserved slot index, if we're stored in a slot, else 0. */
    1230             : };
    1231             : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
    1232             : static_assert(0 < 1, "There is no slot for us");
    1233             : 
    1234             : static bool
    1235           0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
    1236             : {
    1237           0 :   mozilla::dom::PushManagerImpl* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushManagerImpl>(obj);
    1238             :   // We don't want to preserve if we don't have a wrapper, and we
    1239             :   // obviously can't preserve if we're not initialized.
    1240           0 :   if (self && self->GetWrapperPreserveColor()) {
    1241           0 :     PreserveWrapper(self);
    1242             :   }
    1243           0 :   return true;
    1244             : }
    1245             : 
    1246             : static void
    1247           0 : _finalize(js::FreeOp* fop, JSObject* obj)
    1248             : {
    1249           0 :   mozilla::dom::PushManagerImpl* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushManagerImpl>(obj);
    1250           0 :   if (self) {
    1251           0 :     ClearWrapper(self, self, obj);
    1252           0 :     AddForDeferredFinalization<mozilla::dom::PushManagerImpl>(self);
    1253             :   }
    1254           0 : }
    1255             : 
    1256             : static void
    1257           0 : _objectMoved(JSObject* obj, const JSObject* old)
    1258             : {
    1259           0 :   mozilla::dom::PushManagerImpl* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::PushManagerImpl>(obj);
    1260           0 :   if (self) {
    1261           0 :     UpdateWrapper(self, self, obj, old);
    1262             :   }
    1263           0 : }
    1264             : 
    1265             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    1266             : #if defined(__clang__)
    1267             : #pragma clang diagnostic push
    1268             : #pragma clang diagnostic ignored "-Wmissing-braces"
    1269             : #endif
    1270             : static const JSFunctionSpec sChromeStaticMethods_specs[] = {
    1271             :   JS_FNSPEC("_create", PushManagerImpl::_Create, nullptr, 2, 0, nullptr),
    1272             :   JS_FS_END
    1273             : };
    1274             : #if defined(__clang__)
    1275             : #pragma clang diagnostic pop
    1276             : #endif
    1277             : 
    1278             : 
    1279             : // Can't be const because the pref-enabled boolean needs to be writable
    1280             : static Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
    1281             :   { nullptr, &sChromeStaticMethods_specs[0] },
    1282             :   { nullptr, nullptr }
    1283             : };
    1284             : 
    1285             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    1286             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    1287             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    1288             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    1289             : 
    1290             : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
    1291             : #if defined(__clang__)
    1292             : #pragma clang diagnostic push
    1293             : #pragma clang diagnostic ignored "-Wmissing-braces"
    1294             : #endif
    1295             : static const JSFunctionSpec sMethods_specs[] = {
    1296             :   JS_FNSPEC("subscribe", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&subscribe_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
    1297             :   JS_FNSPEC("getSubscription", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&getSubscription_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
    1298             :   JS_FNSPEC("permissionState", GenericPromiseReturningBindingMethod, reinterpret_cast<const JSJitInfo*>(&permissionState_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
    1299             :   JS_FS_END
    1300             : };
    1301             : #if defined(__clang__)
    1302             : #pragma clang diagnostic pop
    1303             : #endif
    1304             : 
    1305             : 
    1306             : // Can't be const because the pref-enabled boolean needs to be writable
    1307             : static Prefable<const JSFunctionSpec> sMethods[] = {
    1308             :   { nullptr, &sMethods_specs[0] },
    1309             :   { nullptr, nullptr }
    1310             : };
    1311             : 
    1312             : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
    1313             :     "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
    1314             : static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
    1315             :     "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
    1316             : 
    1317             : 
    1318             : static uint16_t sNativeProperties_sortedPropertyIndices[3];
    1319             : static PropertyInfo sNativeProperties_propertyInfos[3];
    1320             : 
    1321             : static const NativePropertiesN<1> sNativeProperties = {
    1322             :   false, 0,
    1323             :   false, 0,
    1324             :   true,  0 /* sMethods */,
    1325             :   false, 0,
    1326             :   false, 0,
    1327             :   false, 0,
    1328             :   false, 0,
    1329             :   -1,
    1330             :   3,
    1331             :   sNativeProperties_sortedPropertyIndices,
    1332             :   {
    1333             :     { sMethods, &sNativeProperties_propertyInfos[0] }
    1334             :   }
    1335             : };
    1336             : static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
    1337             :     "We have a property info count that is oversized");
    1338             : 
    1339             : static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[1];
    1340             : static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[1];
    1341             : 
    1342             : static const NativePropertiesN<1> sChromeOnlyNativeProperties = {
    1343             :   true,  0 /* sChromeStaticMethods */,
    1344             :   false, 0,
    1345             :   false, 0,
    1346             :   false, 0,
    1347             :   false, 0,
    1348             :   false, 0,
    1349             :   false, 0,
    1350             :   -1,
    1351             :   1,
    1352             :   sChromeOnlyNativeProperties_sortedPropertyIndices,
    1353             :   {
    1354             :     { sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] }
    1355             :   }
    1356             : };
    1357             : static_assert(1 < 1ull << CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount),
    1358             :     "We have a property info count that is oversized");
    1359             : 
    1360             : static bool
    1361           0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
    1362             : {
    1363           0 :   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
    1364           0 :   JS::Rooted<JSObject*> obj(cx, &args.callee());
    1365           0 :   if (!args.isConstructing()) {
    1366             :     // XXXbz wish I could get the name from the callee instead of
    1367             :     // Adding more relocations
    1368           0 :     return ThrowConstructorWithoutNew(cx, "PushManagerImpl");
    1369             :   }
    1370             : 
    1371           0 :   GlobalObject global(cx, obj);
    1372           0 :   if (global.Failed()) {
    1373           0 :     return false;
    1374             :   }
    1375             : 
    1376           0 :   JS::Rooted<JSObject*> desiredProto(cx);
    1377           0 :   if (!GetDesiredProto(cx, args, &desiredProto)) {
    1378           0 :     return false;
    1379             :   }
    1380             : 
    1381           0 :   if (MOZ_UNLIKELY(args.length() < 1)) {
    1382           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "PushManagerImpl");
    1383             :   }
    1384           0 :   bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
    1385           0 :   binding_detail::FakeString arg0;
    1386           0 :   if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
    1387           0 :     return false;
    1388             :   }
    1389           0 :   Maybe<JSAutoCompartment> ac;
    1390           0 :   if (objIsXray) {
    1391           0 :     obj = js::CheckedUnwrap(obj);
    1392           0 :     if (!obj) {
    1393           0 :       return false;
    1394             :     }
    1395           0 :     ac.emplace(cx, obj);
    1396           0 :     if (!JS_WrapObject(cx, &desiredProto)) {
    1397           0 :       return false;
    1398             :     }
    1399             :   }
    1400           0 :   binding_detail::FastErrorResult rv;
    1401           0 :   auto result(StrongOrRawPtr<mozilla::dom::PushManagerImpl>(mozilla::dom::PushManagerImpl::Constructor(global, cx, NonNullHelper(Constify(arg0)), rv)));
    1402           0 :   if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
    1403           0 :     return false;
    1404             :   }
    1405           0 :   MOZ_ASSERT(!JS_IsExceptionPending(cx));
    1406             :   static_assert(!IsPointer<decltype(result)>::value,
    1407             :                 "NewObject implies that we need to keep the object alive with a strong reference.");
    1408           0 :   if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
    1409           0 :     MOZ_ASSERT(true || JS_IsExceptionPending(cx));
    1410           0 :     return false;
    1411             :   }
    1412           0 :   return true;
    1413             : }
    1414             : 
    1415             : static const js::ClassOps sInterfaceObjectClassOps = {
    1416             :     nullptr,               /* addProperty */
    1417             :     nullptr,               /* delProperty */
    1418             :     nullptr,               /* getProperty */
    1419             :     nullptr,               /* setProperty */
    1420             :     nullptr,               /* enumerate */
    1421             :     nullptr,               /* newEnumerate */
    1422             :     nullptr,               /* resolve */
    1423             :     nullptr,               /* mayResolve */
    1424             :     nullptr,               /* finalize */
    1425             :     _constructor, /* call */
    1426             :     nullptr,               /* hasInstance */
    1427             :     _constructor, /* construct */
    1428             :     nullptr,               /* trace */
    1429             : };
    1430             : 
    1431             : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
    1432             :   {
    1433             :     "Function",
    1434             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
    1435             :     &sInterfaceObjectClassOps,
    1436             :     JS_NULL_CLASS_SPEC,
    1437             :     JS_NULL_CLASS_EXT,
    1438             :     &sInterfaceObjectClassObjectOps
    1439             :   },
    1440             :   eInterface,
    1441             :   true,
    1442             :   prototypes::id::PushManagerImpl,
    1443             :   PrototypeTraits<prototypes::id::PushManagerImpl>::Depth,
    1444             :   sNativePropertyHooks,
    1445             :   "function PushManagerImpl() {\n    [native code]\n}",
    1446             :   JS::GetRealmFunctionPrototype
    1447             : };
    1448             : 
    1449             : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
    1450             :   {
    1451             :     "PushManagerImplPrototype",
    1452             :     JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
    1453             :     JS_NULL_CLASS_OPS,
    1454             :     JS_NULL_CLASS_SPEC,
    1455             :     JS_NULL_CLASS_EXT,
    1456             :     JS_NULL_OBJECT_OPS
    1457             :   },
    1458             :   eInterfacePrototype,
    1459             :   false,
    1460             :   prototypes::id::PushManagerImpl,
    1461             :   PrototypeTraits<prototypes::id::PushManagerImpl>::Depth,
    1462             :   sNativePropertyHooks,
    1463             :   "[object PushManagerImplPrototype]",
    1464             :   JS::GetRealmObjectPrototype
    1465             : };
    1466             : 
    1467             : bool
    1468           0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
    1469             : {
    1470           0 :   return nsContentUtils::ThreadsafeIsSystemCaller(aCx);
    1471             : }
    1472             : 
    1473             : JSObject*
    1474           0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
    1475             : {
    1476           0 :   return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
    1477             : }
    1478             : 
    1479             : static const js::ClassOps sClassOps = {
    1480             :   _addProperty, /* addProperty */
    1481             :   nullptr,               /* delProperty */
    1482             :   nullptr,               /* getProperty */
    1483             :   nullptr,               /* setProperty */
    1484             :   nullptr,               /* enumerate */
    1485             :   nullptr, /* newEnumerate */
    1486             :   nullptr, /* resolve */
    1487             :   nullptr, /* mayResolve */
    1488             :   _finalize, /* finalize */
    1489             :   nullptr, /* call */
    1490             :   nullptr,               /* hasInstance */
    1491             :   nullptr,               /* construct */
    1492             :   nullptr, /* trace */
    1493             : };
    1494             : 
    1495             : static const js::ClassExtension sClassExtension = {
    1496             :   nullptr, /* weakmapKeyDelegateOp */
    1497             :   _objectMoved /* objectMovedOp */
    1498             : };
    1499             : 
    1500             : static const DOMJSClass sClass = {
    1501             :   { "PushManagerImpl",
    1502             :     JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
    1503             :     &sClassOps,
    1504             :     JS_NULL_CLASS_SPEC,
    1505             :     &sClassExtension,
    1506             :     JS_NULL_OBJECT_OPS
    1507             :   },
    1508             :   { prototypes::id::PushManagerImpl, 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 },
    1509             :   IsBaseOf<nsISupports, mozilla::dom::PushManagerImpl >::value,
    1510             :   sNativePropertyHooks,
    1511             :   FindAssociatedGlobalForNative<mozilla::dom::PushManagerImpl>::Get,
    1512             :   GetProtoObjectHandle,
    1513             :   GetCCParticipant<mozilla::dom::PushManagerImpl>::Get()
    1514             : };
    1515             : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
    1516             :               "Must have the right minimal number of reserved slots.");
    1517             : static_assert(1 >= 1,
    1518             :               "Must have enough reserved slots.");
    1519             : 
    1520             : const JSClass*
    1521           0 : GetJSClass()
    1522             : {
    1523           0 :   return sClass.ToJSClass();
    1524             : }
    1525             : 
    1526             : bool
    1527           0 : Wrap(JSContext* aCx, mozilla::dom::PushManagerImpl* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
    1528             : {
    1529             :   MOZ_ASSERT(static_cast<mozilla::dom::PushManagerImpl*>(aObject) ==
    1530             :              reinterpret_cast<mozilla::dom::PushManagerImpl*>(aObject),
    1531             :              "Multiple inheritance for mozilla::dom::PushManagerImpl is broken.");
    1532           0 :   MOZ_ASSERT(ToSupportsIsCorrect(aObject));
    1533           0 :   MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
    1534           0 :   MOZ_ASSERT(!aCache->GetWrapper(),
    1535             :              "You should probably not be using Wrap() directly; use "
    1536             :              "GetOrCreateDOMReflector instead");
    1537             : 
    1538           0 :   MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
    1539             :              "nsISupports must be on our primary inheritance chain");
    1540             : 
    1541           0 :   JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
    1542           0 :   if (!global) {
    1543           0 :     return false;
    1544             :   }
    1545           0 :   MOZ_ASSERT(JS_IsGlobalObject(global));
    1546           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(global));
    1547             : 
    1548             :   // That might have ended up wrapping us already, due to the wonders
    1549             :   // of XBL.  Check for that, and bail out as needed.
    1550           0 :   aReflector.set(aCache->GetWrapper());
    1551           0 :   if (aReflector) {
    1552             : #ifdef DEBUG
    1553           0 :     binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
    1554             : #endif // DEBUG
    1555           0 :     return true;
    1556             :   }
    1557             : 
    1558           0 :   JSAutoCompartment ac(aCx, global);
    1559           0 :   JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
    1560           0 :   if (!canonicalProto) {
    1561           0 :     return false;
    1562             :   }
    1563           0 :   JS::Rooted<JSObject*> proto(aCx);
    1564           0 :   if (aGivenProto) {
    1565           0 :     proto = aGivenProto;
    1566             :     // Unfortunately, while aGivenProto was in the compartment of aCx
    1567             :     // coming in, we changed compartments to that of "parent" so may need
    1568             :     // to wrap the proto here.
    1569           0 :     if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
    1570           0 :       if (!JS_WrapObject(aCx, &proto)) {
    1571           0 :         return false;
    1572             :       }
    1573             :     }
    1574             :   } else {
    1575           0 :     proto = canonicalProto;
    1576             :   }
    1577             : 
    1578           0 :   BindingJSObjectCreator<mozilla::dom::PushManagerImpl> creator(aCx);
    1579           0 :   creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
    1580           0 :   if (!aReflector) {
    1581           0 :     return false;
    1582             :   }
    1583             : 
    1584           0 :   aCache->SetWrapper(aReflector);
    1585           0 :   creator.InitializationSucceeded();
    1586             : 
    1587           0 :   MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
    1588             :              aCache->GetWrapperPreserveColor() == aReflector);
    1589             :   // If proto != canonicalProto, we have to preserve our wrapper;
    1590             :   // otherwise we won't be able to properly recreate it later, since
    1591             :   // we won't know what proto to use.  Note that we don't check
    1592             :   // aGivenProto here, since it's entirely possible (and even
    1593             :   // somewhat common) to have a non-null aGivenProto which is the
    1594             :   // same as canonicalProto.
    1595           0 :   if (proto != canonicalProto) {
    1596           0 :     PreserveWrapper(aObject);
    1597             :   }
    1598             : 
    1599           0 :   return true;
    1600             : }
    1601             : 
    1602             : const NativePropertyHooks sNativePropertyHooks[] = { {
    1603             :   nullptr,
    1604             :   nullptr,
    1605             :   nullptr,
    1606             :   { sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast() },
    1607             :   prototypes::id::PushManagerImpl,
    1608             :   constructors::id::PushManagerImpl,
    1609             :   nullptr,
    1610             :   &DefaultXrayExpandoObjectClass
    1611             : } };
    1612             : 
    1613             : void
    1614           0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
    1615             : {
    1616           0 :   JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
    1617           0 :   if (!parentProto) {
    1618           0 :     return;
    1619             :   }
    1620             : 
    1621           0 :   JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
    1622           0 :   if (!constructorProto) {
    1623           0 :     return;
    1624             :   }
    1625             : 
    1626             :   static bool sIdsInited = false;
    1627           0 :   if (!sIdsInited && NS_IsMainThread()) {
    1628           0 :     if (!InitIds(aCx, sNativeProperties.Upcast())) {
    1629           0 :       return;
    1630             :     }
    1631           0 :     if (!InitIds(aCx, sChromeOnlyNativeProperties.Upcast())) {
    1632           0 :       return;
    1633             :     }
    1634           0 :     sIdsInited = true;
    1635             :   }
    1636             : 
    1637           0 :   JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::PushManagerImpl);
    1638           0 :   JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::PushManagerImpl);
    1639           0 :   dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
    1640             :                               &sPrototypeClass.mBase, protoCache,
    1641             :                               constructorProto, &sInterfaceObjectClass.mBase, 1, nullptr,
    1642             :                               interfaceCache,
    1643             :                               sNativeProperties.Upcast(),
    1644           0 :                               nsContentUtils::ThreadsafeIsSystemCaller(aCx) ? sChromeOnlyNativeProperties.Upcast() : nullptr,
    1645             :                               "PushManagerImpl", aDefineOnGlobal,
    1646             :                               nullptr,
    1647           0 :                               false);
    1648             : }
    1649             : 
    1650             : JS::Handle<JSObject*>
    1651           0 : GetProtoObjectHandle(JSContext* aCx)
    1652             : {
    1653             :   /* Get the interface prototype object for this class.  This will create the
    1654             :      object as needed. */
    1655           0 :   bool aDefineOnGlobal = true;
    1656             : 
    1657             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    1658           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    1659           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    1660           0 :     return nullptr;
    1661             :   }
    1662             : 
    1663             :   /* Check to see whether the interface objects are already installed */
    1664           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    1665           0 :   if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::PushManagerImpl)) {
    1666           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    1667           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    1668             :   }
    1669             : 
    1670             :   /*
    1671             :    * The object might _still_ be null, but that's OK.
    1672             :    *
    1673             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    1674             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    1675             :    * changed after they have been set.
    1676             :    *
    1677             :    * Calling address() avoids the read read barrier that does gray
    1678             :    * unmarking, but it's not possible for the object to be gray here.
    1679             :    */
    1680             : 
    1681           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::PushManagerImpl);
    1682           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    1683           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    1684             : }
    1685             : 
    1686             : JS::Handle<JSObject*>
    1687           0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
    1688             : {
    1689             :   /* Get the interface object for this class.  This will create the object as
    1690             :      needed. */
    1691             : 
    1692             :   /* Make sure our global is sane.  Hopefully we can remove this sometime */
    1693           0 :   JSObject* global = JS::CurrentGlobalOrNull(aCx);
    1694           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
    1695           0 :     return nullptr;
    1696             :   }
    1697             : 
    1698             :   /* Check to see whether the interface objects are already installed */
    1699           0 :   ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
    1700           0 :   if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::PushManagerImpl)) {
    1701           0 :     JS::Rooted<JSObject*> rootedGlobal(aCx, global);
    1702           0 :     CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
    1703             :   }
    1704             : 
    1705             :   /*
    1706             :    * The object might _still_ be null, but that's OK.
    1707             :    *
    1708             :    * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
    1709             :    * traced by TraceProtoAndIfaceCache() and its contents are never
    1710             :    * changed after they have been set.
    1711             :    *
    1712             :    * Calling address() avoids the read read barrier that does gray
    1713             :    * unmarking, but it's not possible for the object to be gray here.
    1714             :    */
    1715             : 
    1716           0 :   const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::PushManagerImpl);
    1717           0 :   MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
    1718           0 :   return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
    1719             : }
    1720             : 
    1721             : JSObject*
    1722           0 : GetConstructorObject(JSContext* aCx)
    1723             : {
    1724           0 :   return GetConstructorObjectHandle(aCx);
    1725             : }
    1726             : 
    1727             : } // namespace PushManagerImplBinding
    1728             : 
    1729             : 
    1730             : 
    1731             : already_AddRefed<Promise>
    1732           0 : PushManagerImplJSImpl::Subscribe(const PushSubscriptionOptionsInit& options, ErrorResult& aRv, JSCompartment* aCompartment)
    1733             : {
    1734           0 :   CallSetup s(this, aRv, "PushManagerImpl.subscribe", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    1735           0 :   JSContext* cx = s.GetContext();
    1736           0 :   if (!cx) {
    1737           0 :     MOZ_ASSERT(aRv.Failed());
    1738           0 :     return nullptr;
    1739             :   }
    1740           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    1741           0 :   JS::AutoValueVector argv(cx);
    1742           0 :   if (!argv.resize(1)) {
    1743           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    1744           0 :     return nullptr;
    1745             :   }
    1746           0 :   unsigned argc = 1;
    1747             : 
    1748             :   do {
    1749           0 :     if (!options.ToObjectInternal(cx, argv[0])) {
    1750           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1751           0 :       return nullptr;
    1752             :     }
    1753           0 :     break;
    1754             :   } while (0);
    1755             : 
    1756           0 :   JS::Rooted<JS::Value> callable(cx);
    1757           0 :   PushManagerImplAtoms* atomsCache = GetAtomCache<PushManagerImplAtoms>(cx);
    1758           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    1759           0 :       !GetCallableProperty(cx, atomsCache->subscribe_id, &callable)) {
    1760           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    1761           0 :     return nullptr;
    1762             :   }
    1763           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    1764           0 :   if (!JS::Call(cx, thisValue, callable,
    1765           0 :                 JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    1766           0 :     aRv.NoteJSContextException(cx);
    1767           0 :     return nullptr;
    1768             :   }
    1769           0 :   RefPtr<Promise> rvalDecl;
    1770             :   { // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
    1771             :     // etc.
    1772             : 
    1773           0 :     JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
    1774           0 :     if (!rval.isObject()) {
    1775           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of PushManagerImpl.subscribe"));
    1776           0 :       return nullptr;
    1777             :     }
    1778           0 :     JSObject* unwrappedVal = js::CheckedUnwrap(&rval.toObject());
    1779           0 :     if (!unwrappedVal) {
    1780             :       // A slight lie, but not much of one, for a dead object wrapper.
    1781           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of PushManagerImpl.subscribe"));
    1782           0 :       return nullptr;
    1783             :     }
    1784           0 :     globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
    1785           0 :     JSAutoCompartment ac(cx, globalObj);
    1786           0 :     GlobalObject promiseGlobal(cx, globalObj);
    1787           0 :     if (promiseGlobal.Failed()) {
    1788           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1789           0 :       return nullptr;
    1790             :     }
    1791             : 
    1792           0 :     JS::Rooted<JS::Value> valueToResolve(cx, rval);
    1793           0 :     if (!JS_WrapValue(cx, &valueToResolve)) {
    1794           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1795           0 :       return nullptr;
    1796             :     }
    1797           0 :     binding_detail::FastErrorResult promiseRv;
    1798             :     nsCOMPtr<nsIGlobalObject> global =
    1799           0 :       do_QueryInterface(promiseGlobal.GetAsSupports());
    1800           0 :     if (!global) {
    1801           0 :       promiseRv.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
    1802           0 :       MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
    1803           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1804           0 :       return nullptr;
    1805             :     }
    1806           0 :     rvalDecl = Promise::Resolve(global, cx, valueToResolve,
    1807           0 :                                     promiseRv);
    1808           0 :     if (promiseRv.MaybeSetPendingException(cx)) {
    1809           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1810           0 :       return nullptr;
    1811             :     }
    1812             :   }
    1813           0 :   return rvalDecl.forget();
    1814             : }
    1815             : 
    1816             : already_AddRefed<Promise>
    1817           0 : PushManagerImplJSImpl::GetSubscription(ErrorResult& aRv, JSCompartment* aCompartment)
    1818             : {
    1819           0 :   CallSetup s(this, aRv, "PushManagerImpl.getSubscription", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    1820           0 :   JSContext* cx = s.GetContext();
    1821           0 :   if (!cx) {
    1822           0 :     MOZ_ASSERT(aRv.Failed());
    1823           0 :     return nullptr;
    1824             :   }
    1825           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    1826             : 
    1827           0 :   JS::Rooted<JS::Value> callable(cx);
    1828           0 :   PushManagerImplAtoms* atomsCache = GetAtomCache<PushManagerImplAtoms>(cx);
    1829           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    1830           0 :       !GetCallableProperty(cx, atomsCache->getSubscription_id, &callable)) {
    1831           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    1832           0 :     return nullptr;
    1833             :   }
    1834           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    1835           0 :   if (!JS::Call(cx, thisValue, callable,
    1836           0 :                 JS::HandleValueArray::empty(), &rval)) {
    1837           0 :     aRv.NoteJSContextException(cx);
    1838           0 :     return nullptr;
    1839             :   }
    1840           0 :   RefPtr<Promise> rvalDecl;
    1841             :   { // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
    1842             :     // etc.
    1843             : 
    1844           0 :     JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
    1845           0 :     if (!rval.isObject()) {
    1846           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of PushManagerImpl.getSubscription"));
    1847           0 :       return nullptr;
    1848             :     }
    1849           0 :     JSObject* unwrappedVal = js::CheckedUnwrap(&rval.toObject());
    1850           0 :     if (!unwrappedVal) {
    1851             :       // A slight lie, but not much of one, for a dead object wrapper.
    1852           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of PushManagerImpl.getSubscription"));
    1853           0 :       return nullptr;
    1854             :     }
    1855           0 :     globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
    1856           0 :     JSAutoCompartment ac(cx, globalObj);
    1857           0 :     GlobalObject promiseGlobal(cx, globalObj);
    1858           0 :     if (promiseGlobal.Failed()) {
    1859           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1860           0 :       return nullptr;
    1861             :     }
    1862             : 
    1863           0 :     JS::Rooted<JS::Value> valueToResolve(cx, rval);
    1864           0 :     if (!JS_WrapValue(cx, &valueToResolve)) {
    1865           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1866           0 :       return nullptr;
    1867             :     }
    1868           0 :     binding_detail::FastErrorResult promiseRv;
    1869             :     nsCOMPtr<nsIGlobalObject> global =
    1870           0 :       do_QueryInterface(promiseGlobal.GetAsSupports());
    1871           0 :     if (!global) {
    1872           0 :       promiseRv.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
    1873           0 :       MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
    1874           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1875           0 :       return nullptr;
    1876             :     }
    1877           0 :     rvalDecl = Promise::Resolve(global, cx, valueToResolve,
    1878           0 :                                     promiseRv);
    1879           0 :     if (promiseRv.MaybeSetPendingException(cx)) {
    1880           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1881           0 :       return nullptr;
    1882             :     }
    1883             :   }
    1884           0 :   return rvalDecl.forget();
    1885             : }
    1886             : 
    1887             : already_AddRefed<Promise>
    1888           0 : PushManagerImplJSImpl::PermissionState(const PushSubscriptionOptionsInit& options, ErrorResult& aRv, JSCompartment* aCompartment)
    1889             : {
    1890           0 :   CallSetup s(this, aRv, "PushManagerImpl.permissionState", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    1891           0 :   JSContext* cx = s.GetContext();
    1892           0 :   if (!cx) {
    1893           0 :     MOZ_ASSERT(aRv.Failed());
    1894           0 :     return nullptr;
    1895             :   }
    1896           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    1897           0 :   JS::AutoValueVector argv(cx);
    1898           0 :   if (!argv.resize(1)) {
    1899           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    1900           0 :     return nullptr;
    1901             :   }
    1902           0 :   unsigned argc = 1;
    1903             : 
    1904             :   do {
    1905           0 :     if (!options.ToObjectInternal(cx, argv[0])) {
    1906           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1907           0 :       return nullptr;
    1908             :     }
    1909           0 :     break;
    1910             :   } while (0);
    1911             : 
    1912           0 :   JS::Rooted<JS::Value> callable(cx);
    1913           0 :   PushManagerImplAtoms* atomsCache = GetAtomCache<PushManagerImplAtoms>(cx);
    1914           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    1915           0 :       !GetCallableProperty(cx, atomsCache->permissionState_id, &callable)) {
    1916           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    1917           0 :     return nullptr;
    1918             :   }
    1919           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    1920           0 :   if (!JS::Call(cx, thisValue, callable,
    1921           0 :                 JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    1922           0 :     aRv.NoteJSContextException(cx);
    1923           0 :     return nullptr;
    1924             :   }
    1925           0 :   RefPtr<Promise> rvalDecl;
    1926             :   { // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
    1927             :     // etc.
    1928             : 
    1929           0 :     JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
    1930           0 :     if (!rval.isObject()) {
    1931           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of PushManagerImpl.permissionState"));
    1932           0 :       return nullptr;
    1933             :     }
    1934           0 :     JSObject* unwrappedVal = js::CheckedUnwrap(&rval.toObject());
    1935           0 :     if (!unwrappedVal) {
    1936             :       // A slight lie, but not much of one, for a dead object wrapper.
    1937           0 :       aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("return value of PushManagerImpl.permissionState"));
    1938           0 :       return nullptr;
    1939             :     }
    1940           0 :     globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
    1941           0 :     JSAutoCompartment ac(cx, globalObj);
    1942           0 :     GlobalObject promiseGlobal(cx, globalObj);
    1943           0 :     if (promiseGlobal.Failed()) {
    1944           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1945           0 :       return nullptr;
    1946             :     }
    1947             : 
    1948           0 :     JS::Rooted<JS::Value> valueToResolve(cx, rval);
    1949           0 :     if (!JS_WrapValue(cx, &valueToResolve)) {
    1950           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1951           0 :       return nullptr;
    1952             :     }
    1953           0 :     binding_detail::FastErrorResult promiseRv;
    1954             :     nsCOMPtr<nsIGlobalObject> global =
    1955           0 :       do_QueryInterface(promiseGlobal.GetAsSupports());
    1956           0 :     if (!global) {
    1957           0 :       promiseRv.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
    1958           0 :       MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
    1959           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1960           0 :       return nullptr;
    1961             :     }
    1962           0 :     rvalDecl = Promise::Resolve(global, cx, valueToResolve,
    1963           0 :                                     promiseRv);
    1964           0 :     if (promiseRv.MaybeSetPendingException(cx)) {
    1965           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1966           0 :       return nullptr;
    1967             :     }
    1968             :   }
    1969           0 :   return rvalDecl.forget();
    1970             : }
    1971             : 
    1972             : void
    1973           0 : PushManagerImplJSImpl::__Init(const nsAString& scope, ErrorResult& aRv, JSCompartment* aCompartment)
    1974             : {
    1975           0 :   CallSetup s(this, aRv, "__init", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
    1976           0 :   JSContext* cx = s.GetContext();
    1977           0 :   if (!cx) {
    1978           0 :     MOZ_ASSERT(aRv.Failed());
    1979           0 :     return;
    1980             :   }
    1981           0 :   JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    1982           0 :   JS::AutoValueVector argv(cx);
    1983           0 :   if (!argv.resize(1)) {
    1984           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    1985           0 :     return;
    1986             :   }
    1987           0 :   unsigned argc = 1;
    1988             : 
    1989             :   do {
    1990           0 :     nsString mutableStr(scope);
    1991           0 :     if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
    1992           0 :       aRv.Throw(NS_ERROR_UNEXPECTED);
    1993           0 :       return;
    1994             :     }
    1995           0 :     break;
    1996             :   } while (0);
    1997             : 
    1998           0 :   JS::Rooted<JS::Value> callable(cx);
    1999           0 :   PushManagerImplAtoms* atomsCache = GetAtomCache<PushManagerImplAtoms>(cx);
    2000           0 :   if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
    2001           0 :       !GetCallableProperty(cx, atomsCache->__init_id, &callable)) {
    2002           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2003           0 :     return;
    2004             :   }
    2005           0 :   JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
    2006           0 :   if (!JS::Call(cx, thisValue, callable,
    2007           0 :                 JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    2008           0 :     aRv.NoteJSContextException(cx);
    2009           0 :     return;
    2010             :   }
    2011             : }
    2012             : 
    2013             : bool
    2014           0 : PushManagerImplJSImpl::InitIds(JSContext* cx, PushManagerImplAtoms* atomsCache)
    2015             : {
    2016           0 :   MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
    2017             : 
    2018             :   // Initialize these in reverse order so that any failure leaves the first one
    2019             :   // uninitialized.
    2020           0 :   if (!atomsCache->__init_id.init(cx, "__init") ||
    2021           0 :       !atomsCache->permissionState_id.init(cx, "permissionState") ||
    2022           0 :       !atomsCache->getSubscription_id.init(cx, "getSubscription") ||
    2023           0 :       !atomsCache->subscribe_id.init(cx, "subscribe")) {
    2024           0 :     return false;
    2025             :   }
    2026           0 :   return true;
    2027             : }
    2028             : 
    2029             : 
    2030             : 
    2031             : NS_IMPL_CYCLE_COLLECTION_CLASS(PushManagerImpl)
    2032           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PushManagerImpl)
    2033           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImpl)
    2034           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
    2035           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
    2036           0 :   tmp->ClearWeakReferences();
    2037           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    2038           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PushManagerImpl)
    2039           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)
    2040           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
    2041           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    2042           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(PushManagerImpl)
    2043           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(PushManagerImpl)
    2044           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(PushManagerImpl)
    2045           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushManagerImpl)
    2046           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    2047           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    2048           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    2049           0 : NS_INTERFACE_MAP_END
    2050             : 
    2051           0 : PushManagerImpl::PushManagerImpl(JS::Handle<JSObject*> aJSImplObject, nsIGlobalObject* aParent)
    2052           0 :   : mImpl(new PushManagerImplJSImpl(nullptr, aJSImplObject, /* aIncumbentGlobal = */ nullptr)),
    2053           0 :     mParent(aParent)
    2054             : {
    2055           0 : }
    2056             : 
    2057             : 
    2058           0 : PushManagerImpl::~PushManagerImpl()
    2059             : {
    2060           0 : }
    2061             : 
    2062             : nsISupports*
    2063           0 : PushManagerImpl::GetParentObject() const
    2064             : {
    2065           0 :   return mParent;
    2066             : }
    2067             : 
    2068             : JSObject*
    2069           0 : PushManagerImpl::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
    2070             : {
    2071           0 :   JS::Rooted<JSObject*> obj(aCx, PushManagerImplBinding::Wrap(aCx, this, aGivenProto));
    2072           0 :   if (!obj) {
    2073           0 :     return nullptr;
    2074             :   }
    2075             : 
    2076             :   // Now define it on our chrome object
    2077           0 :   JSAutoCompartment ac(aCx, mImpl->CallbackOrNull());
    2078           0 :   if (!JS_WrapObject(aCx, &obj)) {
    2079           0 :     return nullptr;
    2080             :   }
    2081           0 :   if (!JS_DefineProperty(aCx, mImpl->CallbackOrNull(), "__DOM_IMPL__", obj, 0)) {
    2082           0 :     return nullptr;
    2083             :   }
    2084           0 :   return obj;
    2085             : }
    2086             : 
    2087             : already_AddRefed<PushManagerImpl>
    2088           0 : PushManagerImpl::Constructor(const GlobalObject& global, JSContext* cx, const nsAString& scope, ErrorResult& aRv)
    2089             : {
    2090           0 :   JS::Rooted<JSObject*> jsImplObj(cx);
    2091             :   nsCOMPtr<nsIGlobalObject> globalHolder =
    2092           0 :     ConstructJSImplementation("@mozilla.org/push/PushManager;1", global, &jsImplObj, aRv);
    2093           0 :   if (aRv.Failed()) {
    2094           0 :     return nullptr;
    2095             :   }
    2096             :   // Build the C++ implementation.
    2097           0 :   RefPtr<PushManagerImpl> impl = new PushManagerImpl(jsImplObj, globalHolder);
    2098             :   // Wrap the object before calling __Init so that __DOM_IMPL__ is available.
    2099           0 :   JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
    2100           0 :   MOZ_ASSERT(js::IsObjectInContextCompartment(scopeObj, cx));
    2101           0 :   JS::Rooted<JS::Value> wrappedVal(cx);
    2102           0 :   if (!GetOrCreateDOMReflector(cx, impl, &wrappedVal)) {
    2103             :     //XXX Assertion disabled for now, see bug 991271.
    2104           0 :     MOZ_ASSERT(true || JS_IsExceptionPending(cx));
    2105           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
    2106           0 :     return nullptr;
    2107             :   }
    2108             :   // Initialize the object with the constructor arguments.
    2109           0 :   impl->mImpl->__Init(scope, aRv, js::GetObjectCompartment(scopeObj));
    2110           0 :   if (aRv.Failed()) {
    2111           0 :     return nullptr;
    2112             :   }
    2113           0 :   return impl.forget();
    2114             : }
    2115             : 
    2116             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    2117             : already_AddRefed<Promise>
    2118           0 : PushManagerImpl::Subscribe(const PushSubscriptionOptionsInit& options, ErrorResult& aRv, JSCompartment* aCompartment)
    2119             : {
    2120           0 :   return mImpl->Subscribe(options, aRv, aCompartment);
    2121             : }
    2122             : 
    2123             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    2124             : already_AddRefed<Promise>
    2125           0 : PushManagerImpl::GetSubscription(ErrorResult& aRv, JSCompartment* aCompartment)
    2126             : {
    2127           0 :   return mImpl->GetSubscription(aRv, aCompartment);
    2128             : }
    2129             : 
    2130             : // Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
    2131             : already_AddRefed<Promise>
    2132           0 : PushManagerImpl::PermissionState(const PushSubscriptionOptionsInit& options, ErrorResult& aRv, JSCompartment* aCompartment)
    2133             : {
    2134           0 :   return mImpl->PermissionState(options, aRv, aCompartment);
    2135             : }
    2136             : 
    2137             : bool
    2138           0 : PushManagerImpl::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
    2139             : {
    2140           0 :   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
    2141           0 :   if (args.length() < 2) {
    2142           0 :     return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "PushManagerImpl._create");
    2143             :   }
    2144           0 :   if (!args[0].isObject()) {
    2145           0 :     return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of PushManagerImpl._create");
    2146             :   }
    2147           0 :   if (!args[1].isObject()) {
    2148           0 :     return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of PushManagerImpl._create");
    2149             :   }
    2150             : 
    2151             :   // GlobalObject will go through wrappers as needed for us, and
    2152             :   // is simpler than the right UnwrapArg incantation.
    2153           0 :   GlobalObject global(cx, &args[0].toObject());
    2154           0 :   if (global.Failed()) {
    2155           0 :     return false;
    2156             :   }
    2157           0 :   nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
    2158           0 :   MOZ_ASSERT(globalHolder);
    2159           0 :   JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
    2160           0 :   RefPtr<PushManagerImpl> impl = new PushManagerImpl(arg, globalHolder);
    2161           0 :   MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
    2162           0 :   return GetOrCreateDOMReflector(cx, impl, args.rval());
    2163             : }
    2164             : 
    2165             : 
    2166             : } // namespace dom
    2167             : } // namespace mozilla

Generated by: LCOV version 1.13