LCOV - code coverage report
Current view: top level - obj-x86_64-pc-linux-gnu/dom/bindings - WebExtensionPolicyBinding.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 881 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13