LCOV - code coverage report
Current view: top level - obj-x86_64-pc-linux-gnu/dom/bindings - AddonManagerBinding.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 28 1682 1.7 %
Date: 2017-07-14 16:53:18 Functions: 4 153 2.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13