/* THIS FILE IS AUTOGENERATED FROM WebExtensionPolicy.webidl BY Codegen.py - DO NOT EDIT */ #include #include "AtomList.h" #include "MainThreadUtils.h" #include "WebExtensionPolicyBinding.h" #include "WrapperFactory.h" #include "XrayWrapper.h" #include "js/Array.h" #include "js/CallAndConstruct.h" #include "js/Exception.h" #include "js/ForOfIterator.h" #include "js/MapAndSet.h" #include "js/Object.h" #include "js/PropertyAndElement.h" #include "js/PropertyDescriptor.h" #include "js/experimental/JitInfo.h" #include "js/shadow/Object.h" #include "mozilla/Atomics.h" #include "mozilla/OwningNonNull.h" #include "mozilla/ProfilerLabels.h" #include "mozilla/dom/BindingCallContext.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/DOMJSClass.h" #include "mozilla/dom/NonRefcountedDOMObject.h" #include "mozilla/dom/Nullable.h" #include "mozilla/dom/PrimitiveConversions.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ToJSValue.h" #include "mozilla/dom/WindowProxyHolder.h" #include "mozilla/dom/XrayExpandoClass.h" #include "mozilla/extensions/MatchGlob.h" #include "mozilla/extensions/MatchPattern.h" #include "mozilla/extensions/WebExtensionContentScript.h" #include "mozilla/extensions/WebExtensionPolicy.h" #include "nsContentUtils.h" #include "nsIURI.h" #include "nsJSUtils.h" namespace mozilla::dom { namespace binding_detail {}; // Just to make sure it's known as a namespace using namespace mozilla::dom::binding_detail; WebAccessibleResourceInit::WebAccessibleResourceInit() { // Safe to pass a null context if we pass a null value Init(nullptr, JS::NullHandleValue); } bool WebAccessibleResourceInit::InitIds(JSContext* cx, WebAccessibleResourceInitAtoms* atomsCache) { MOZ_ASSERT(reinterpret_cast(atomsCache)->isVoid()); // Initialize these in reverse order so that any failure leaves the first one // uninitialized. if (!atomsCache->resources_id.init(cx, "resources") || !atomsCache->matches_id.init(cx, "matches") || !atomsCache->extension_ids_id.init(cx, "extension_ids")) { return false; } return true; } bool WebAccessibleResourceInit::Init(BindingCallContext& cx, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // Passing a null JSContext is OK only if we're initing from null, // Since in that case we will not have to do any property gets // Also evaluate isNullOrUndefined in order to avoid false-positive // checkers by static analysis tools MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined()); WebAccessibleResourceInitAtoms* atomsCache = nullptr; if (cx) { atomsCache = GetAtomCache(cx); if (reinterpret_cast(atomsCache)->isVoid() && !InitIds(cx, atomsCache)) { return false; } } if (!IsConvertibleToDictionary(val)) { return cx.ThrowErrorMessage(sourceDescription, "dictionary"); } bool isNull = val.isNullOrUndefined(); // We only need these if !isNull, in which case we have |cx|. Maybe > object; Maybe > temp; if (!isNull) { MOZ_ASSERT(cx); object.emplace(cx, &val.toObject()); temp.emplace(cx); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->extension_ids_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'extension_ids' member of WebAccessibleResourceInit", "sequence"); return false; } Sequence &arr = mExtension_ids.SetValue(); if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } nsString* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } nsString& slot = *slotPtr; if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) { return false; } } } else if (temp.ref().isNullOrUndefined()) { mExtension_ids.SetNull(); } else { cx.ThrowErrorMessage("'extension_ids' member of WebAccessibleResourceInit", "sequence"); return false; } } else { mExtension_ids.SetNull(); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->matches_id, temp.ptr())) { return false; } } if (!(!isNull && !temp->isUndefined()) || temp.ref().isNullOrUndefined()) { mMatches.SetNull(); } else { if (!mMatches.SetValue().Init(cx, temp.ref(), "'matches' member of WebAccessibleResourceInit", passedToJSImpl)) { return false; } } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->resources_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'resources' member of WebAccessibleResourceInit", "sequence"); return false; } Sequence &arr = mResources; if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } OwningMatchGlobOrUTF8String* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } OwningMatchGlobOrUTF8String& slot = *slotPtr; if (!slot.Init(cx, temp, "Element of 'resources' member of WebAccessibleResourceInit", passedToJSImpl)) { return false; } } } else { cx.ThrowErrorMessage("'resources' member of WebAccessibleResourceInit", "sequence"); return false; } mIsAnyMemberPresent = true; } else if (cx) { // Don't error out if we have no cx. In that // situation the caller is default-constructing us and we'll // just assume they know what they're doing. return cx.ThrowErrorMessage("'resources' member of WebAccessibleResourceInit"); } return true; } bool WebAccessibleResourceInit::Init(JSContext* cx_, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // We don't want to use sourceDescription for our context here; // that's not really what it's formatted for. BindingCallContext cx(cx_, nullptr); return Init(cx, val, sourceDescription, passedToJSImpl); } void WebAccessibleResourceInit::TraceDictionary(JSTracer* trc) { } WebAccessibleResourceInit& WebAccessibleResourceInit::operator=(const WebAccessibleResourceInit& aOther) { MaybeEmptyDictionaryBase::operator=(aOther); mExtension_ids = aOther.mExtension_ids; mMatches = aOther.mMatches; mResources = aOther.mResources; return *this; } MOZ_CAN_RUN_SCRIPT void WebExtensionLocalizeCallback::Call(BindingCallContext& cx, JS::Handle aThisVal, const nsAString& unlocalizedText, nsString& aRetVal, ErrorResult& aRv) { JS::Rooted rval(cx); JS::RootedVector argv(cx); if (!argv.resize(1)) { // That threw an exception on the JSContext, and our CallSetup will do // the right thing with that. return; } unsigned argc = 1; do { if (!xpc::NonVoidStringToJsval(cx, unlocalizedText, argv[0])) { aRv.Throw(NS_ERROR_UNEXPECTED); return; } break; } while (false); JS::Rooted callable(cx, JS::ObjectValue(*mCallback)); if (!JS::Call(cx, aThisVal, callable, JS::HandleValueArray::subarray(argv, 0, argc), &rval)) { aRv.NoteJSContextException(cx); return; } nsAutoString rvalDecl; if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) { aRv.Throw(NS_ERROR_UNEXPECTED); return; } aRetVal = std::move(rvalDecl); } WebExtensionInit::WebExtensionInit() { // Safe to pass a null context if we pass a null value Init(nullptr, JS::NullHandleValue); } bool WebExtensionInit::InitIds(JSContext* cx, WebExtensionInitAtoms* atomsCache) { MOZ_ASSERT(reinterpret_cast(atomsCache)->isVoid()); // Initialize these in reverse order so that any failure leaves the first one // uninitialized. if (!atomsCache->webAccessibleResources_id.init(cx, "webAccessibleResources") || !atomsCache->version_id.init(cx, "version") || !atomsCache->type_id.init(cx, "type") || !atomsCache->temporarilyInstalled_id.init(cx, "temporarilyInstalled") || !atomsCache->sandboxPages_id.init(cx, "sandboxPages") || !atomsCache->sandboxPageCSP_id.init(cx, "sandboxPageCSP") || !atomsCache->readyPromise_id.init(cx, "readyPromise") || !atomsCache->permissions_id.init(cx, "permissions") || !atomsCache->name_id.init(cx, "name") || !atomsCache->mozExtensionHostname_id.init(cx, "mozExtensionHostname") || !atomsCache->manifestVersion_id.init(cx, "manifestVersion") || !atomsCache->localizeCallback_id.init(cx, "localizeCallback") || !atomsCache->isPrivileged_id.init(cx, "isPrivileged") || !atomsCache->ignoreQuarantine_id.init(cx, "ignoreQuarantine") || !atomsCache->id_id.init(cx, "id") || !atomsCache->hasRecommendedState_id.init(cx, "hasRecommendedState") || !atomsCache->extensionPageCSP_id.init(cx, "extensionPageCSP") || !atomsCache->contentScripts_id.init(cx, "contentScripts") || !atomsCache->baseURL_id.init(cx, "baseURL") || !atomsCache->backgroundWorkerScript_id.init(cx, "backgroundWorkerScript") || !atomsCache->backgroundTypeModule_id.init(cx, "backgroundTypeModule") || !atomsCache->backgroundScripts_id.init(cx, "backgroundScripts") || !atomsCache->allowedOrigins_id.init(cx, "allowedOrigins")) { return false; } return true; } bool WebExtensionInit::Init(BindingCallContext& cx, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // Passing a null JSContext is OK only if we're initing from null, // Since in that case we will not have to do any property gets // Also evaluate isNullOrUndefined in order to avoid false-positive // checkers by static analysis tools MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined()); WebExtensionInitAtoms* atomsCache = nullptr; if (cx) { atomsCache = GetAtomCache(cx); if (reinterpret_cast(atomsCache)->isVoid() && !InitIds(cx, atomsCache)) { return false; } } if (!IsConvertibleToDictionary(val)) { return cx.ThrowErrorMessage(sourceDescription, "dictionary"); } bool isNull = val.isNullOrUndefined(); // We only need these if !isNull, in which case we have |cx|. Maybe > object; Maybe > temp; if (!isNull) { MOZ_ASSERT(cx); object.emplace(cx, &val.toObject()); temp.emplace(cx); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->allowedOrigins_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!mAllowedOrigins.Init(cx, temp.ref(), "'allowedOrigins' member of WebExtensionInit", passedToJSImpl)) { return false; } mIsAnyMemberPresent = true; } else if (cx) { // Don't error out if we have no cx. In that // situation the caller is default-constructing us and we'll // just assume they know what they're doing. return cx.ThrowErrorMessage("'allowedOrigins' member of WebExtensionInit"); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->backgroundScripts_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'backgroundScripts' member of WebExtensionInit", "sequence"); return false; } Sequence &arr = mBackgroundScripts.SetValue(); if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } nsString* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } nsString& slot = *slotPtr; if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) { return false; } } } else if (temp.ref().isNullOrUndefined()) { mBackgroundScripts.SetNull(); } else { cx.ThrowErrorMessage("'backgroundScripts' member of WebExtensionInit", "sequence"); return false; } } else { mBackgroundScripts.SetNull(); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->backgroundTypeModule_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'backgroundTypeModule' member of WebExtensionInit", &mBackgroundTypeModule)) { return false; } } else { mBackgroundTypeModule = false; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->backgroundWorkerScript_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, mBackgroundWorkerScript)) { return false; } } else { mBackgroundWorkerScript.SetIsVoid(true); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->baseURL_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mBaseURL)) { return false; } mIsAnyMemberPresent = true; } else if (cx) { // Don't error out if we have no cx. In that // situation the caller is default-constructing us and we'll // just assume they know what they're doing. return cx.ThrowErrorMessage("'baseURL' member of WebExtensionInit"); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->contentScripts_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'contentScripts' member of WebExtensionInit", "sequence"); return false; } Sequence &arr = mContentScripts; if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } WebExtensionContentScriptInit* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } WebExtensionContentScriptInit& slot = *slotPtr; if (!slot.Init(cx, temp, "Element of 'contentScripts' member of WebExtensionInit", passedToJSImpl)) { return false; } } } else { cx.ThrowErrorMessage("'contentScripts' member of WebExtensionInit", "sequence"); return false; } } else { /* mContentScripts array is already empty; nothing to do */ } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->extensionPageCSP_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, mExtensionPageCSP)) { return false; } } else { mExtensionPageCSP.SetIsVoid(true); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->hasRecommendedState_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'hasRecommendedState' member of WebExtensionInit", &mHasRecommendedState)) { return false; } } else { mHasRecommendedState = false; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->id_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mId)) { return false; } mIsAnyMemberPresent = true; } else if (cx) { // Don't error out if we have no cx. In that // situation the caller is default-constructing us and we'll // just assume they know what they're doing. return cx.ThrowErrorMessage("'id' member of WebExtensionInit"); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->ignoreQuarantine_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'ignoreQuarantine' member of WebExtensionInit", &mIgnoreQuarantine)) { return false; } } else { mIgnoreQuarantine = false; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->isPrivileged_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'isPrivileged' member of WebExtensionInit", &mIsPrivileged)) { return false; } } else { mIsPrivileged = false; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->localizeCallback_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { if (JS::IsCallable(&temp.ref().toObject())) { { // scope for tempRoot and tempGlobalRoot if needed JS::Rooted tempRoot(cx, &temp.ref().toObject()); JS::Rooted tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx)); mLocalizeCallback = new WebExtensionLocalizeCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal()); } } else { cx.ThrowErrorMessage("'localizeCallback' member of WebExtensionInit"); return false; } } else { cx.ThrowErrorMessage("'localizeCallback' member of WebExtensionInit"); return false; } mIsAnyMemberPresent = true; } else if (cx) { // Don't error out if we have no cx. In that // situation the caller is default-constructing us and we'll // just assume they know what they're doing. return cx.ThrowErrorMessage("'localizeCallback' member of WebExtensionInit"); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->manifestVersion_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'manifestVersion' member of WebExtensionInit", &mManifestVersion)) { return false; } } else { mManifestVersion = 2U; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->mozExtensionHostname_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToByteString(cx, temp.ref(), false, "'mozExtensionHostname' member of WebExtensionInit", mMozExtensionHostname)) { return false; } mIsAnyMemberPresent = true; } else if (cx) { // Don't error out if we have no cx. In that // situation the caller is default-constructing us and we'll // just assume they know what they're doing. return cx.ThrowErrorMessage("'mozExtensionHostname' member of WebExtensionInit"); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->name_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mName)) { return false; } } else { mName.AssignLiteral(u""); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->permissions_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'permissions' member of WebExtensionInit", "sequence"); return false; } Sequence &arr = mPermissions; if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } nsString* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } nsString& slot = *slotPtr; if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) { return false; } } } else { cx.ThrowErrorMessage("'permissions' member of WebExtensionInit", "sequence"); return false; } } else { /* mPermissions array is already empty; nothing to do */ } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->readyPromise_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { mReadyPromise.Construct(); { // Scope for our GlobalObject, FastErrorResult, JSAutoRealm, // etc. JS::Rooted globalObj(cx); globalObj = JS::CurrentGlobalOrNull(cx); JSAutoRealm ar(cx, globalObj); GlobalObject promiseGlobal(cx, globalObj); if (promiseGlobal.Failed()) { return false; } JS::Rooted valueToResolve(cx, temp.ref()); if (!JS_WrapValue(cx, &valueToResolve)) { return false; } binding_detail::FastErrorResult promiseRv; nsCOMPtr global = do_QueryInterface(promiseGlobal.GetAsSupports()); if (!global) { promiseRv.Throw(NS_ERROR_UNEXPECTED); MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx)); return false; } (mReadyPromise.Value()) = Promise::Resolve(global, cx, valueToResolve, promiseRv); if (promiseRv.MaybeSetPendingException(cx)) { return false; } } mIsAnyMemberPresent = true; } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->sandboxPageCSP_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, mSandboxPageCSP)) { return false; } } else { mSandboxPageCSP.SetIsVoid(true); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->sandboxPages_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'sandboxPages' member of WebExtensionInit", "sequence"); return false; } Sequence &arr = mSandboxPages.SetValue(); if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } OwningMatchGlobOrUTF8String* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } OwningMatchGlobOrUTF8String& slot = *slotPtr; if (!slot.Init(cx, temp, "Element of 'sandboxPages' member of WebExtensionInit", passedToJSImpl)) { return false; } } } else if (temp.ref().isNullOrUndefined()) { mSandboxPages.SetNull(); } else { cx.ThrowErrorMessage("'sandboxPages' member of WebExtensionInit", "sequence"); return false; } } else { mSandboxPages.SetNull(); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->temporarilyInstalled_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'temporarilyInstalled' member of WebExtensionInit", &mTemporarilyInstalled)) { return false; } } else { mTemporarilyInstalled = false; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mType)) { return false; } } else { mType.AssignLiteral(u""); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->version_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mVersion)) { return false; } } else { mVersion.AssignLiteral(u""); } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->webAccessibleResources_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'webAccessibleResources' member of WebExtensionInit", "sequence"); return false; } Sequence &arr = mWebAccessibleResources; if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } WebAccessibleResourceInit* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } WebAccessibleResourceInit& slot = *slotPtr; if (!slot.Init(cx, temp, "Element of 'webAccessibleResources' member of WebExtensionInit", passedToJSImpl)) { return false; } } } else { cx.ThrowErrorMessage("'webAccessibleResources' member of WebExtensionInit", "sequence"); return false; } } else { /* mWebAccessibleResources array is already empty; nothing to do */ } mIsAnyMemberPresent = true; return true; } bool WebExtensionInit::Init(JSContext* cx_, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // We don't want to use sourceDescription for our context here; // that's not really what it's formatted for. BindingCallContext cx(cx_, nullptr); return Init(cx, val, sourceDescription, passedToJSImpl); } void WebExtensionInit::TraceDictionary(JSTracer* trc) { } namespace WebExtensionPolicy_Binding { static bool get_id(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "id", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); // Have to either root across the getter call or reget after. bool isXray; JS::Rooted slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray)); if (!slotStorage) { return false; } const size_t slotIndex = isXray ? (DOM_EXPANDO_RESERVED_SLOTS + 0) : (DOM_INSTANCE_RESERVED_SLOTS + 0); MOZ_ASSERT(slotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(slotStorage))); { // Scope for cachedVal JS::Value cachedVal = JS::GetNativeObjectReservedSlot(slotStorage, slotIndex); if (!cachedVal.isUndefined()) { args.rval().set(cachedVal); // The cached value is in the compartment of slotStorage, // so wrap into the caller compartment as needed. return MaybeWrapValue(cx, args.rval()); } } DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetId(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetId(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); { JS::Rooted conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage); JSAutoRealm ar(cx, conversionScope); do { // block we break out of when done wrapping if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } break; } while (false); } { // And now store things in the realm of our slotStorage. JSAutoRealm ar(cx, slotStorage); // Make a copy so that we don't do unnecessary wrapping on args.rval(). JS::Rooted storedVal(cx, args.rval()); if (!MaybeWrapValue(cx, &storedVal)) { return false; } JS::SetNativeObjectReservedSlot(slotStorage, slotIndex, storedVal); } // And now make sure args.rval() is in the caller realm. return MaybeWrapValue(cx, args.rval()); } static const JSJitInfo id_getterinfo = { { get_id }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ true, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ (DOM_INSTANCE_RESERVED_SLOTS + 0) /* Reserved slot index, if we're stored in a slot, else 0. */ }; static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) <= JSJitInfo::maxSlotIndex, "We won't fit"); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) < 8, "There is no slot for us"); static bool get_mozExtensionHostname(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "mozExtensionHostname", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); // Have to either root across the getter call or reget after. bool isXray; JS::Rooted slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray)); if (!slotStorage) { return false; } const size_t slotIndex = isXray ? (DOM_EXPANDO_RESERVED_SLOTS + 1) : (DOM_INSTANCE_RESERVED_SLOTS + 1); MOZ_ASSERT(slotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(slotStorage))); { // Scope for cachedVal JS::Value cachedVal = JS::GetNativeObjectReservedSlot(slotStorage, slotIndex); if (!cachedVal.isUndefined()) { args.rval().set(cachedVal); // The cached value is in the compartment of slotStorage, // so wrap into the caller compartment as needed. return MaybeWrapValue(cx, args.rval()); } } nsAutoCString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetMozExtensionHostname(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetMozExtensionHostname(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); { JS::Rooted conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage); JSAutoRealm ar(cx, conversionScope); do { // block we break out of when done wrapping if (!NonVoidByteStringToJsval(cx, result, args.rval())) { return false; } break; } while (false); } { // And now store things in the realm of our slotStorage. JSAutoRealm ar(cx, slotStorage); // Make a copy so that we don't do unnecessary wrapping on args.rval(). JS::Rooted storedVal(cx, args.rval()); if (!MaybeWrapValue(cx, &storedVal)) { return false; } JS::SetNativeObjectReservedSlot(slotStorage, slotIndex, storedVal); } // And now make sure args.rval() is in the caller realm. return MaybeWrapValue(cx, args.rval()); } static const JSJitInfo mozExtensionHostname_getterinfo = { { get_mozExtensionHostname }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ true, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ (DOM_INSTANCE_RESERVED_SLOTS + 1) /* Reserved slot index, if we're stored in a slot, else 0. */ }; static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) <= JSJitInfo::maxSlotIndex, "We won't fit"); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) < 8, "There is no slot for us"); MOZ_CAN_RUN_SCRIPT static bool get_baseURL(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "baseURL", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); nsAutoCString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetBaseURL(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetBaseURL(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!NonVoidByteStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo baseURL_getterinfo = { { get_baseURL }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_name(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "name", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetName(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetName(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo name_getterinfo = { { get_name }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_version(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "version", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetVersion(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetVersion(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo version_getterinfo = { { get_version }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_type(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "type", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetType(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetType(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo type_getterinfo = { { get_type }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_isPrivileged(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "isPrivileged", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); bool result(MOZ_KnownLive(self)->IsPrivileged()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo isPrivileged_getterinfo = { { get_isPrivileged }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_temporarilyInstalled(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "temporarilyInstalled", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); bool result(MOZ_KnownLive(self)->TemporarilyInstalled()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo temporarilyInstalled_getterinfo = { { get_temporarilyInstalled }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_manifestVersion(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "manifestVersion", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); uint32_t result(MOZ_KnownLive(self)->ManifestVersion()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setNumber(result); return true; } static const JSJitInfo manifestVersion_getterinfo = { { get_manifestVersion }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_baseCSP(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "baseCSP", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetBaseCSP(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetBaseCSP(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo baseCSP_getterinfo = { { get_baseCSP }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_extensionPageCSP(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "extensionPageCSP", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetExtensionPageCSP(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetExtensionPageCSP(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo extensionPageCSP_getterinfo = { { get_extensionPageCSP }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_sandboxPageCSP(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "sandboxPageCSP", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetSandboxPageCSP(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetSandboxPageCSP(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo sandboxPageCSP_getterinfo = { { get_sandboxPageCSP }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasNone, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_permissions(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "permissions", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); // Have to either root across the getter call or reget after. bool isXray; JS::Rooted slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray)); if (!slotStorage) { return false; } const size_t slotIndex = isXray ? (DOM_EXPANDO_RESERVED_SLOTS + 2) : (DOM_INSTANCE_RESERVED_SLOTS + 2); MOZ_ASSERT(slotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(slotStorage))); { // Scope for cachedVal JS::Value cachedVal = JS::GetNativeObjectReservedSlot(slotStorage, slotIndex); if (!cachedVal.isUndefined()) { args.rval().set(cachedVal); // The cached value is in the compartment of slotStorage, // so wrap into the caller compartment as needed. return MaybeWrapNonDOMObjectValue(cx, args.rval()); } } nsTArray result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetPermissions(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetPermissions(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); { JS::Rooted conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage); JSAutoRealm ar(cx, conversionScope); do { // block we break out of when done wrapping uint32_t length = result.Length(); JS::Rooted returnArray(cx, JS::NewArrayObject(cx, length)); if (!returnArray) { return false; } // Scope for 'tmp' { JS::Rooted tmp(cx); for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) { // Control block to let us common up the JS_DefineElement calls when there // are different ways to succeed at wrapping the object. do { if (!xpc::NonVoidStringToJsval(cx, result[sequenceIdx0], &tmp)) { return false; } break; } while (false); if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp, JSPROP_ENUMERATE)) { return false; } } } args.rval().setObject(*returnArray); break; } while (false); JS::Rooted rvalObj(cx, &args.rval().toObject()); if (!JS_FreezeObject(cx, rvalObj)) { return false; } } { // And now store things in the realm of our slotStorage. JSAutoRealm ar(cx, slotStorage); // Make a copy so that we don't do unnecessary wrapping on args.rval(). JS::Rooted storedVal(cx, args.rval()); if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) { return false; } JS::SetNativeObjectReservedSlot(slotStorage, slotIndex, storedVal); if (!isXray) { // In the Xray case we don't need to do this, because getting the // expando object already preserved our wrapper. PreserveWrapper(self); } } // And now make sure args.rval() is in the caller realm. return MaybeWrapNonDOMObjectValue(cx, args.rval()); } MOZ_CAN_RUN_SCRIPT static bool set_permissions(JSContext* cx_, JS::Handle obj, void* void_self, JSJitSetterCallArgs args) { BindingCallContext cx(cx_, "WebExtensionPolicy.permissions setter"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "permissions", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_SETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); binding_detail::AutoSequence arg0; if (args[0].isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(args[0], JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("Value being assigned", "sequence"); return false; } binding_detail::AutoSequence &arr = arg0; if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } nsString* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } nsString& slot = *slotPtr; if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) { return false; } } } else { cx.ThrowErrorMessage("Value being assigned", "sequence"); return false; } // NOTE: This assert does NOT call the function. static_assert(std::is_void_vSetPermissions(Constify(arg0)))>, "Should be returning void here"); MOZ_KnownLive(self)->SetPermissions(Constify(arg0)); MOZ_ASSERT(!JS_IsExceptionPending(cx)); ClearCachedPermissionsValue(self); return true; } static const JSJitInfo permissions_getterinfo = { { get_permissions }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ true, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ (DOM_INSTANCE_RESERVED_SLOTS + 2) /* Reserved slot index, if we're stored in a slot, else 0. */ }; static_assert((DOM_INSTANCE_RESERVED_SLOTS + 2) <= JSJitInfo::maxSlotIndex, "We won't fit"); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 2) < 8, "There is no slot for us"); static const JSJitInfo permissions_setterinfo = { { (JSJitGetterOp)set_permissions }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Setter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_allowedOrigins(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "allowedOrigins", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); auto result(StrongOrRawPtr(MOZ_KnownLive(self)->AllowedOrigins())); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } MOZ_CAN_RUN_SCRIPT static bool set_allowedOrigins(JSContext* cx_, JS::Handle obj, void* void_self, JSJitSetterCallArgs args) { BindingCallContext cx(cx_, "WebExtensionPolicy.allowedOrigins setter"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "allowedOrigins", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_SETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); NonNull arg0; if (args[0].isObject()) { { // Our JSContext should be in the right global to do unwrapping in. nsresult rv = UnwrapObject(args[0], arg0, cx); if (NS_FAILED(rv)) { cx.ThrowErrorMessage("Value being assigned", "MatchPatternSet"); return false; } } } else { cx.ThrowErrorMessage("Value being assigned"); return false; } // NOTE: This assert does NOT call the function. static_assert(std::is_void_vSetAllowedOrigins(MOZ_KnownLive(NonNullHelper(arg0))))>, "Should be returning void here"); MOZ_KnownLive(self)->SetAllowedOrigins(MOZ_KnownLive(NonNullHelper(arg0))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); return true; } static const JSJitInfo allowedOrigins_getterinfo = { { get_allowedOrigins }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; static const JSJitInfo allowedOrigins_setterinfo = { { (JSJitGetterOp)set_allowedOrigins }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Setter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_fileSchemeAllowed(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "fileSchemeAllowed", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); bool result(MOZ_KnownLive(self)->FileSchemeAllowed()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo fileSchemeAllowed_getterinfo = { { get_fileSchemeAllowed }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_guardSets(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "guardSets", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); // Have to either root across the getter call or reget after. bool isXray; JS::Rooted slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray)); if (!slotStorage) { return false; } const size_t slotIndex = isXray ? (DOM_EXPANDO_RESERVED_SLOTS + 3) : (DOM_INSTANCE_RESERVED_SLOTS + 3); MOZ_ASSERT(slotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(slotStorage))); { // Scope for cachedVal JS::Value cachedVal = JS::GetNativeObjectReservedSlot(slotStorage, slotIndex); if (!cachedVal.isUndefined()) { args.rval().set(cachedVal); // The cached value is in the compartment of slotStorage, // so wrap into the caller compartment as needed. return MaybeWrapNonDOMObjectValue(cx, args.rval()); } } nsTArray> result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetGuardSets(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetGuardSets(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); { JS::Rooted conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage); JSAutoRealm ar(cx, conversionScope); do { // block we break out of when done wrapping uint32_t length = result.Length(); JS::Rooted returnArray(cx, JS::NewArrayObject(cx, length)); if (!returnArray) { return false; } // Scope for 'tmp' { JS::Rooted tmp(cx); for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) { // Control block to let us common up the JS_DefineElement calls when there // are different ways to succeed at wrapping the object. do { if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } break; } while (false); if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp, JSPROP_ENUMERATE)) { return false; } } } args.rval().setObject(*returnArray); break; } while (false); JS::Rooted rvalObj(cx, &args.rval().toObject()); if (!JS_FreezeObject(cx, rvalObj)) { return false; } } { // And now store things in the realm of our slotStorage. JSAutoRealm ar(cx, slotStorage); // Make a copy so that we don't do unnecessary wrapping on args.rval(). JS::Rooted storedVal(cx, args.rval()); if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) { return false; } JS::SetNativeObjectReservedSlot(slotStorage, slotIndex, storedVal); if (!isXray) { // In the Xray case we don't need to do this, because getting the // expando object already preserved our wrapper. PreserveWrapper(self); } } // And now make sure args.rval() is in the caller realm. return MaybeWrapNonDOMObjectValue(cx, args.rval()); } MOZ_CAN_RUN_SCRIPT static bool set_guardSets(JSContext* cx_, JS::Handle obj, void* void_self, JSJitSetterCallArgs args) { BindingCallContext cx(cx_, "WebExtensionPolicy.guardSets setter"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "guardSets", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_SETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); binding_detail::AutoSequence> arg0; if (args[0].isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(args[0], JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("Value being assigned", "sequence"); return false; } binding_detail::AutoSequence> &arr = arg0; if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } OwningNonNull* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } OwningNonNull& slot = *slotPtr; if (temp.isObject()) { static_assert(IsRefcounted::value, "We can only store refcounted classes."); { // Our JSContext should be in the right global to do unwrapping in. nsresult rv = UnwrapObject(&temp, slot, cx); if (NS_FAILED(rv)) { cx.ThrowErrorMessage("Element of value being assigned", "ExtensionGuardSet"); return false; } } } else { cx.ThrowErrorMessage("Element of value being assigned"); return false; } } } else { cx.ThrowErrorMessage("Value being assigned", "sequence"); return false; } // NOTE: This assert does NOT call the function. static_assert(std::is_void_vSetGuardSets(Constify(arg0)))>, "Should be returning void here"); MOZ_KnownLive(self)->SetGuardSets(Constify(arg0)); MOZ_ASSERT(!JS_IsExceptionPending(cx)); ClearCachedGuardSetsValue(self); return true; } static const JSJitInfo guardSets_getterinfo = { { get_guardSets }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ true, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ (DOM_INSTANCE_RESERVED_SLOTS + 3) /* Reserved slot index, if we're stored in a slot, else 0. */ }; static_assert((DOM_INSTANCE_RESERVED_SLOTS + 3) <= JSJitInfo::maxSlotIndex, "We won't fit"); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 3) < 8, "There is no slot for us"); static const JSJitInfo guardSets_setterinfo = { { (JSJitGetterOp)set_guardSets }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Setter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool checkGuarded(JSContext* cx_, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { BindingCallContext cx(cx_, "WebExtensionPolicy.checkGuarded"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "checkGuarded", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.checkGuarded", 1)) { return false; } nsIURI* arg0; RefPtr arg0_holder; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapArg(cx, source, getter_AddRefs(arg0_holder)))) { cx.ThrowErrorMessage("Argument 1", "URI"); return false; } MOZ_ASSERT(arg0_holder); arg0 = arg0_holder; } else { cx.ThrowErrorMessage("Argument 1"); return false; } Nullable result(MOZ_KnownLive(self)->CheckGuarded(MOZ_KnownLive(NonNullHelper(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (result.IsNull()) { args.rval().setNull(); return true; } else { if (!ToJSValue(cx, result.Value(), args.rval())) { return false; } return true; } } static const JSJitInfo checkGuarded_methodinfo = { { (JSJitGetterOp)checkGuarded }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_contentScripts(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "contentScripts", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); // Have to either root across the getter call or reget after. bool isXray; JS::Rooted slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray)); if (!slotStorage) { return false; } const size_t slotIndex = isXray ? (DOM_EXPANDO_RESERVED_SLOTS + 4) : (DOM_INSTANCE_RESERVED_SLOTS + 4); MOZ_ASSERT(slotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(slotStorage))); { // Scope for cachedVal JS::Value cachedVal = JS::GetNativeObjectReservedSlot(slotStorage, slotIndex); if (!cachedVal.isUndefined()) { args.rval().set(cachedVal); // The cached value is in the compartment of slotStorage, // so wrap into the caller compartment as needed. return MaybeWrapNonDOMObjectValue(cx, args.rval()); } } nsTArray> result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetContentScripts(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetContentScripts(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); { JS::Rooted conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage); JSAutoRealm ar(cx, conversionScope); do { // block we break out of when done wrapping uint32_t length = result.Length(); JS::Rooted returnArray(cx, JS::NewArrayObject(cx, length)); if (!returnArray) { return false; } // Scope for 'tmp' { JS::Rooted tmp(cx); for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) { // Control block to let us common up the JS_DefineElement calls when there // are different ways to succeed at wrapping the object. do { if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } break; } while (false); if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp, JSPROP_ENUMERATE)) { return false; } } } args.rval().setObject(*returnArray); break; } while (false); JS::Rooted rvalObj(cx, &args.rval().toObject()); if (!JS_FreezeObject(cx, rvalObj)) { return false; } } { // And now store things in the realm of our slotStorage. JSAutoRealm ar(cx, slotStorage); // Make a copy so that we don't do unnecessary wrapping on args.rval(). JS::Rooted storedVal(cx, args.rval()); if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) { return false; } JS::SetNativeObjectReservedSlot(slotStorage, slotIndex, storedVal); if (!isXray) { // In the Xray case we don't need to do this, because getting the // expando object already preserved our wrapper. PreserveWrapper(self); } } // And now make sure args.rval() is in the caller realm. return MaybeWrapNonDOMObjectValue(cx, args.rval()); } static const JSJitInfo contentScripts_getterinfo = { { get_contentScripts }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ true, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ (DOM_INSTANCE_RESERVED_SLOTS + 4) /* Reserved slot index, if we're stored in a slot, else 0. */ }; static_assert((DOM_INSTANCE_RESERVED_SLOTS + 4) <= JSJitInfo::maxSlotIndex, "We won't fit"); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 4) < 8, "There is no slot for us"); MOZ_CAN_RUN_SCRIPT static bool get_active(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "active", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); bool result(MOZ_KnownLive(self)->Active()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } MOZ_CAN_RUN_SCRIPT static bool set_active(JSContext* cx, JS::Handle obj, void* void_self, JSJitSetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "active", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_SETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); bool arg0; if (!ValueToPrimitive(cx, args[0], "Value being assigned", &arg0)) { return false; } FastErrorResult rv; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vSetActive(arg0, rv))>, "Should be returning void here"); MOZ_KnownLive(self)->SetActive(arg0, rv); if (rv.MaybeSetPendingException(cx, "WebExtensionPolicy.active setter")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); return true; } static const JSJitInfo active_getterinfo = { { get_active }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; static const JSJitInfo active_setterinfo = { { (JSJitGetterOp)set_active }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Setter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_ignoreQuarantine(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "ignoreQuarantine", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); // Have to either root across the getter call or reget after. bool isXray; JS::Rooted slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray)); if (!slotStorage) { return false; } const size_t slotIndex = isXray ? (DOM_EXPANDO_RESERVED_SLOTS + 5) : (DOM_INSTANCE_RESERVED_SLOTS + 5); MOZ_ASSERT(slotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(slotStorage))); { // Scope for cachedVal JS::Value cachedVal = JS::GetNativeObjectReservedSlot(slotStorage, slotIndex); if (!cachedVal.isUndefined()) { args.rval().set(cachedVal); // The cached value is in the compartment of slotStorage, // so wrap into the caller compartment as needed. return MaybeWrapValue(cx, args.rval()); } } bool result(MOZ_KnownLive(self)->IgnoreQuarantine()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); { JS::Rooted conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage); JSAutoRealm ar(cx, conversionScope); do { // block we break out of when done wrapping args.rval().setBoolean(result); break; } while (false); } { // And now store things in the realm of our slotStorage. JSAutoRealm ar(cx, slotStorage); // Make a copy so that we don't do unnecessary wrapping on args.rval(). JS::Rooted storedVal(cx, args.rval()); if (!MaybeWrapValue(cx, &storedVal)) { return false; } JS::SetNativeObjectReservedSlot(slotStorage, slotIndex, storedVal); if (!isXray) { // In the Xray case we don't need to do this, because getting the // expando object already preserved our wrapper. PreserveWrapper(self); } } // And now make sure args.rval() is in the caller realm. return MaybeWrapValue(cx, args.rval()); } MOZ_CAN_RUN_SCRIPT static bool set_ignoreQuarantine(JSContext* cx, JS::Handle obj, void* void_self, JSJitSetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "ignoreQuarantine", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_SETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); bool arg0; if (!ValueToPrimitive(cx, args[0], "Value being assigned", &arg0)) { return false; } // NOTE: This assert does NOT call the function. static_assert(std::is_void_vSetIgnoreQuarantine(arg0))>, "Should be returning void here"); MOZ_KnownLive(self)->SetIgnoreQuarantine(arg0); MOZ_ASSERT(!JS_IsExceptionPending(cx)); ClearCachedIgnoreQuarantineValue(self); return true; } static const JSJitInfo ignoreQuarantine_getterinfo = { { get_ignoreQuarantine }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ true, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ (DOM_INSTANCE_RESERVED_SLOTS + 5) /* Reserved slot index, if we're stored in a slot, else 0. */ }; static_assert((DOM_INSTANCE_RESERVED_SLOTS + 5) <= JSJitInfo::maxSlotIndex, "We won't fit"); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 5) < 8, "There is no slot for us"); static const JSJitInfo ignoreQuarantine_setterinfo = { { (JSJitGetterOp)set_ignoreQuarantine }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Setter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_hasRecommendedState(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "hasRecommendedState", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); // Have to either root across the getter call or reget after. bool isXray; JS::Rooted slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray)); if (!slotStorage) { return false; } const size_t slotIndex = isXray ? (DOM_EXPANDO_RESERVED_SLOTS + 6) : (DOM_INSTANCE_RESERVED_SLOTS + 6); MOZ_ASSERT(slotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(slotStorage))); { // Scope for cachedVal JS::Value cachedVal = JS::GetNativeObjectReservedSlot(slotStorage, slotIndex); if (!cachedVal.isUndefined()) { args.rval().set(cachedVal); // The cached value is in the compartment of slotStorage, // so wrap into the caller compartment as needed. return MaybeWrapValue(cx, args.rval()); } } bool result(MOZ_KnownLive(self)->HasRecommendedState()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); { JS::Rooted conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage); JSAutoRealm ar(cx, conversionScope); do { // block we break out of when done wrapping args.rval().setBoolean(result); break; } while (false); } { // And now store things in the realm of our slotStorage. JSAutoRealm ar(cx, slotStorage); // Make a copy so that we don't do unnecessary wrapping on args.rval(). JS::Rooted storedVal(cx, args.rval()); if (!MaybeWrapValue(cx, &storedVal)) { return false; } JS::SetNativeObjectReservedSlot(slotStorage, slotIndex, storedVal); if (!isXray) { // In the Xray case we don't need to do this, because getting the // expando object already preserved our wrapper. PreserveWrapper(self); } } // And now make sure args.rval() is in the caller realm. return MaybeWrapValue(cx, args.rval()); } static const JSJitInfo hasRecommendedState_getterinfo = { { get_hasRecommendedState }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ true, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ (DOM_INSTANCE_RESERVED_SLOTS + 6) /* Reserved slot index, if we're stored in a slot, else 0. */ }; static_assert((DOM_INSTANCE_RESERVED_SLOTS + 6) <= JSJitInfo::maxSlotIndex, "We won't fit"); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 6) < 8, "There is no slot for us"); MOZ_CAN_RUN_SCRIPT static bool get_useRemoteWebExtensions(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "useRemoteWebExtensions", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } bool result(mozilla::extensions::WebExtensionPolicy::UseRemoteWebExtensions(global)); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } MOZ_CAN_RUN_SCRIPT static bool get_isExtensionProcess(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "isExtensionProcess", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } bool result(mozilla::extensions::WebExtensionPolicy::IsExtensionProcess(global)); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } MOZ_CAN_RUN_SCRIPT static bool get_backgroundServiceWorkerEnabled(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "backgroundServiceWorkerEnabled", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } bool result(mozilla::extensions::WebExtensionPolicy::BackgroundServiceWorkerEnabled(global)); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } MOZ_CAN_RUN_SCRIPT static bool get_quarantinedDomainsEnabled(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "quarantinedDomainsEnabled", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } bool result(mozilla::extensions::WebExtensionPolicy::QuarantinedDomainsEnabled(global)); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } MOZ_CAN_RUN_SCRIPT static bool get_privateBrowsingAllowed(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "privateBrowsingAllowed", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); bool result(MOZ_KnownLive(self)->PrivateBrowsingAllowed()); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo privateBrowsingAllowed_getterinfo = { { get_privateBrowsingAllowed }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ true, /* isInfallible. False in setters. */ true, /* isMovable. Not relevant for setters. */ true, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool canAccessWindow(JSContext* cx_, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { BindingCallContext cx(cx_, "WebExtensionPolicy.canAccessWindow"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "canAccessWindow", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.canAccessWindow", 1)) { return false; } mozilla::dom::WindowProxyHolder arg0; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapWindowProxyArg(cx, source, arg0))) { cx.ThrowErrorMessage("Argument 1", "WindowProxy"); return false; } } else { cx.ThrowErrorMessage("Argument 1", "WindowProxy"); return false; } bool result(MOZ_KnownLive(self)->CanAccessWindow(MOZ_KnownLive(NonNullHelper(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo::ArgType canAccessWindow_methodinfo_argTypes[] = { JSJitInfo::Object, JSJitInfo::ArgTypeListEnd }; static const JSTypedMethodJitInfo canAccessWindow_methodinfo = { { { (JSJitGetterOp)canAccessWindow }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ true, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }, canAccessWindow_methodinfo_argTypes }; MOZ_CAN_RUN_SCRIPT static bool canAccessURI(JSContext* cx_, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { BindingCallContext cx(cx_, "WebExtensionPolicy.canAccessURI"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "canAccessURI", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.canAccessURI", 1)) { return false; } nsIURI* arg0; RefPtr arg0_holder; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapArg(cx, source, getter_AddRefs(arg0_holder)))) { cx.ThrowErrorMessage("Argument 1", "URI"); return false; } MOZ_ASSERT(arg0_holder); arg0 = arg0_holder; } else { cx.ThrowErrorMessage("Argument 1"); return false; } bool arg1; if (args.hasDefined(1)) { if (!ValueToPrimitive(cx, args[1], "Argument 2", &arg1)) { return false; } } else { arg1 = false; } bool arg2; if (args.hasDefined(2)) { if (!ValueToPrimitive(cx, args[2], "Argument 3", &arg2)) { return false; } } else { arg2 = true; } bool arg3; if (args.hasDefined(3)) { if (!ValueToPrimitive(cx, args[3], "Argument 4", &arg3)) { return false; } } else { arg3 = false; } bool result(MOZ_KnownLive(self)->CanAccessURI(MOZ_KnownLive(NonNullHelper(arg0)), arg1, arg2, arg3)); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo canAccessURI_methodinfo = { { (JSJitGetterOp)canAccessURI }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool hasPermission(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "hasPermission", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.hasPermission", 1)) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } bool result(MOZ_KnownLive(self)->HasPermission(NonNullHelper(Constify(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo hasPermission_methodinfo = { { (JSJitGetterOp)hasPermission }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool isQuarantinedURI(JSContext* cx_, unsigned argc, JS::Value* vp) { BindingCallContext cx(cx_, "WebExtensionPolicy.isQuarantinedURI"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "isQuarantinedURI", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!args.requireAtLeast(cx, "WebExtensionPolicy.isQuarantinedURI", 1)) { return false; } GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } nsIURI* arg0; RefPtr arg0_holder; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapArg(cx, source, getter_AddRefs(arg0_holder)))) { cx.ThrowErrorMessage("Argument 1", "URI"); return false; } MOZ_ASSERT(arg0_holder); arg0 = arg0_holder; } else { cx.ThrowErrorMessage("Argument 1"); return false; } bool result(mozilla::extensions::WebExtensionPolicy::IsQuarantinedURI(global, MOZ_KnownLive(NonNullHelper(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } MOZ_CAN_RUN_SCRIPT static bool quarantinedFromURI(JSContext* cx_, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { BindingCallContext cx(cx_, "WebExtensionPolicy.quarantinedFromURI"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "quarantinedFromURI", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.quarantinedFromURI", 1)) { return false; } nsIURI* arg0; RefPtr arg0_holder; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapArg(cx, source, getter_AddRefs(arg0_holder)))) { cx.ThrowErrorMessage("Argument 1", "URI"); return false; } MOZ_ASSERT(arg0_holder); arg0 = arg0_holder; } else { cx.ThrowErrorMessage("Argument 1"); return false; } bool result(MOZ_KnownLive(self)->QuarantinedFromURI(MOZ_KnownLive(NonNullHelper(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo quarantinedFromURI_methodinfo = { { (JSJitGetterOp)quarantinedFromURI }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool isWebAccessiblePath(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "isWebAccessiblePath", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.isWebAccessiblePath", 1)) { return false; } nsAutoCString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } bool result(MOZ_KnownLive(self)->IsWebAccessiblePath(Constify(arg0))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo isWebAccessiblePath_methodinfo = { { (JSJitGetterOp)isWebAccessiblePath }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool sourceMayAccessPath(JSContext* cx_, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { BindingCallContext cx(cx_, "WebExtensionPolicy.sourceMayAccessPath"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "sourceMayAccessPath", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.sourceMayAccessPath", 2)) { return false; } nsIURI* arg0; RefPtr arg0_holder; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapArg(cx, source, getter_AddRefs(arg0_holder)))) { cx.ThrowErrorMessage("Argument 1", "URI"); return false; } MOZ_ASSERT(arg0_holder); arg0 = arg0_holder; } else { cx.ThrowErrorMessage("Argument 1"); return false; } nsAutoCString arg1; if (!ConvertJSValueToString(cx, args[1], eStringify, eStringify, arg1)) { return false; } bool result(MOZ_KnownLive(self)->SourceMayAccessPath(MOZ_KnownLive(NonNullHelper(arg0)), Constify(arg1))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo sourceMayAccessPath_methodinfo = { { (JSJitGetterOp)sourceMayAccessPath }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool localize(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "localize", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.localize", 1)) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vLocalize(NonNullHelper(Constify(arg0)), result))>, "Should be returning void here"); MOZ_KnownLive(self)->Localize(NonNullHelper(Constify(arg0)), result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo localize_methodinfo = { { (JSJitGetterOp)localize }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool getURL(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "getURL", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); nsAutoString arg0; if (args.hasDefined(0)) { if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } } else { arg0.AssignLiteral(u""); } FastErrorResult rv; DOMString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetURL(NonNullHelper(Constify(arg0)), result, rv))>, "Should be returning void here"); MOZ_KnownLive(self)->GetURL(NonNullHelper(Constify(arg0)), result, rv); if (rv.MaybeSetPendingException(cx, "WebExtensionPolicy.getURL")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo getURL_methodinfo = { { (JSJitGetterOp)getURL }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool registerContentScript(JSContext* cx_, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { BindingCallContext cx(cx_, "WebExtensionPolicy.registerContentScript"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "registerContentScript", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.registerContentScript", 1)) { return false; } NonNull arg0; if (args[0].isObject()) { { // Our JSContext should be in the right global to do unwrapping in. nsresult rv = UnwrapObject(args[0], arg0, cx); if (NS_FAILED(rv)) { cx.ThrowErrorMessage("Argument 1", "WebExtensionContentScript"); return false; } } } else { cx.ThrowErrorMessage("Argument 1"); return false; } FastErrorResult rv; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vRegisterContentScript(MOZ_KnownLive(NonNullHelper(arg0)), rv))>, "Should be returning void here"); MOZ_KnownLive(self)->RegisterContentScript(MOZ_KnownLive(NonNullHelper(arg0)), rv); if (rv.MaybeSetPendingException(cx, "WebExtensionPolicy.registerContentScript")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setUndefined(); return true; } static const JSJitInfo registerContentScript_methodinfo = { { (JSJitGetterOp)registerContentScript }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool unregisterContentScript(JSContext* cx_, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { BindingCallContext cx(cx_, "WebExtensionPolicy.unregisterContentScript"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "unregisterContentScript", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.unregisterContentScript", 1)) { return false; } NonNull arg0; if (args[0].isObject()) { { // Our JSContext should be in the right global to do unwrapping in. nsresult rv = UnwrapObject(args[0], arg0, cx); if (NS_FAILED(rv)) { cx.ThrowErrorMessage("Argument 1", "WebExtensionContentScript"); return false; } } } else { cx.ThrowErrorMessage("Argument 1"); return false; } FastErrorResult rv; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vUnregisterContentScript(MOZ_KnownLive(NonNullHelper(arg0)), rv))>, "Should be returning void here"); MOZ_KnownLive(self)->UnregisterContentScript(MOZ_KnownLive(NonNullHelper(arg0)), rv); if (rv.MaybeSetPendingException(cx, "WebExtensionPolicy.unregisterContentScript")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setUndefined(); return true; } static const JSJitInfo unregisterContentScript_methodinfo = { { (JSJitGetterOp)unregisterContentScript }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool injectContentScripts(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "injectContentScripts", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); FastErrorResult rv; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vInjectContentScripts(rv))>, "Should be returning void here"); MOZ_KnownLive(self)->InjectContentScripts(rv); if (rv.MaybeSetPendingException(cx, "WebExtensionPolicy.injectContentScripts")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setUndefined(); return true; } static const JSJitInfo injectContentScripts_methodinfo = { { (JSJitGetterOp)injectContentScripts }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool getActiveExtensions(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "getActiveExtensions", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } nsTArray> result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_v, "Should be returning void here"); mozilla::extensions::WebExtensionPolicy::GetActiveExtensions(global, result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); uint32_t length = result.Length(); JS::Rooted returnArray(cx, JS::NewArrayObject(cx, length)); if (!returnArray) { return false; } // Scope for 'tmp' { JS::Rooted tmp(cx); for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) { // Control block to let us common up the JS_DefineElement calls when there // are different ways to succeed at wrapping the object. do { if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } break; } while (false); if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp, JSPROP_ENUMERATE)) { return false; } } } args.rval().setObject(*returnArray); return true; } MOZ_CAN_RUN_SCRIPT static bool getByID(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "getByID", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!args.requireAtLeast(cx, "WebExtensionPolicy.getByID", 1)) { return false; } GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } auto result(StrongOrRawPtr(mozilla::extensions::WebExtensionPolicy::GetByID(global, NonNullHelper(Constify(arg0))))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } MOZ_CAN_RUN_SCRIPT static bool getByHostname(JSContext* cx_, unsigned argc, JS::Value* vp) { BindingCallContext cx(cx_, "WebExtensionPolicy.getByHostname"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "getByHostname", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!args.requireAtLeast(cx, "WebExtensionPolicy.getByHostname", 1)) { return false; } GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } nsCString arg0; if (!ConvertJSValueToByteString(cx, args[0], false, "argument 1", arg0)) { return false; } auto result(StrongOrRawPtr(mozilla::extensions::WebExtensionPolicy::GetByHostname(global, Constify(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } MOZ_CAN_RUN_SCRIPT static bool getByURI(JSContext* cx_, unsigned argc, JS::Value* vp) { BindingCallContext cx(cx_, "WebExtensionPolicy.getByURI"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "getByURI", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!args.requireAtLeast(cx, "WebExtensionPolicy.getByURI", 1)) { return false; } GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } nsIURI* arg0; RefPtr arg0_holder; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapArg(cx, source, getter_AddRefs(arg0_holder)))) { cx.ThrowErrorMessage("Argument 1", "URI"); return false; } MOZ_ASSERT(arg0_holder); arg0 = arg0_holder; } else { cx.ThrowErrorMessage("Argument 1"); return false; } auto result(StrongOrRawPtr(mozilla::extensions::WebExtensionPolicy::GetByURI(global, MOZ_KnownLive(NonNullHelper(arg0))))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } MOZ_CAN_RUN_SCRIPT static bool isRestrictedURI(JSContext* cx_, unsigned argc, JS::Value* vp) { BindingCallContext cx(cx_, "WebExtensionPolicy.isRestrictedURI"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "isRestrictedURI", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!args.requireAtLeast(cx, "WebExtensionPolicy.isRestrictedURI", 1)) { return false; } GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj)); if (global.Failed()) { return false; } nsIURI* arg0; RefPtr arg0_holder; if (args[0].isObject()) { JS::Rooted source(cx, &args[0].toObject()); if (NS_FAILED(UnwrapArg(cx, source, getter_AddRefs(arg0_holder)))) { cx.ThrowErrorMessage("Argument 1", "URI"); return false; } MOZ_ASSERT(arg0_holder); arg0 = arg0_holder; } else { cx.ThrowErrorMessage("Argument 1"); return false; } bool result(mozilla::extensions::WebExtensionPolicy::IsRestrictedURI(global, MOZ_KnownLive(NonNullHelper(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } MOZ_CAN_RUN_SCRIPT static bool get_readyPromise(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "readyPromise", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); JS::Rooted result(cx); // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetReadyPromise(cx, &result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetReadyPromise(cx, &result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (result) { JS::ExposeObjectToActiveJS(result); } args.rval().setObjectOrNull(result); if (!MaybeWrapObjectOrNullValue(cx, args.rval())) { return false; } return true; } static const JSJitInfo readyPromise_getterinfo = { { get_readyPromise }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool isManifestBackgroundWorker(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "isManifestBackgroundWorker", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "WebExtensionPolicy.isManifestBackgroundWorker", 1)) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } bool result(MOZ_KnownLive(self)->IsManifestBackgroundWorker(NonNullHelper(Constify(arg0)))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setBoolean(result); return true; } static const JSJitInfo isManifestBackgroundWorker_methodinfo = { { (JSJitGetterOp)isManifestBackgroundWorker }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_browsingContextGroupId(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "browsingContextGroupId", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); FastErrorResult rv; uint64_t result(MOZ_KnownLive(self)->GetBrowsingContextGroupId(rv)); if (rv.MaybeSetPendingException(cx, "WebExtensionPolicy.browsingContextGroupId getter")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().set(JS::NumberValue(double(result))); return true; } static const JSJitInfo browsingContextGroupId_getterinfo = { { get_browsingContextGroupId }, { prototypes::id::WebExtensionPolicy }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; static void _finalize(JS::GCContext* gcx, JSObject* obj) { mozilla::extensions::WebExtensionPolicy* self = UnwrapPossiblyNotInitializedDOMObject(obj); if (self) { JS::SetNativeObjectReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue()); ClearWrapper(self, self, obj); if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) { JS::RemoveAssociatedMemory(obj, mallocBytes, JS::MemoryUse::DOMBinding); } AddForDeferredFinalization(self); } } MOZ_GLOBINIT static const JSFunctionSpec sStaticMethods_specs[] = { JS_FNSPEC("isQuarantinedURI", isQuarantinedURI, nullptr, 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("getActiveExtensions", getActiveExtensions, nullptr, 0, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("getByID", getByID, nullptr, 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("getByHostname", getByHostname, nullptr, 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("getByURI", getByURI, nullptr, 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("isRestrictedURI", isRestrictedURI, nullptr, 1, JSPROP_ENUMERATE, nullptr), JS_FS_END }; static const Prefable sStaticMethods[] = { { nullptr, &sStaticMethods_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(6 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); MOZ_GLOBINIT static const JSPropertySpec sStaticAttributes_specs[] = { JSPropertySpec::nativeAccessors("useRemoteWebExtensions", JSPROP_ENUMERATE, get_useRemoteWebExtensions, nullptr, nullptr, nullptr), JSPropertySpec::nativeAccessors("isExtensionProcess", JSPROP_ENUMERATE, get_isExtensionProcess, nullptr, nullptr, nullptr), JSPropertySpec::nativeAccessors("backgroundServiceWorkerEnabled", JSPROP_ENUMERATE, get_backgroundServiceWorkerEnabled, nullptr, nullptr, nullptr), JSPropertySpec::nativeAccessors("quarantinedDomainsEnabled", JSPROP_ENUMERATE, get_quarantinedDomainsEnabled, nullptr, nullptr, nullptr), JS_PS_END }; static const Prefable sStaticAttributes[] = { { nullptr, &sStaticAttributes_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); MOZ_GLOBINIT static const JSFunctionSpec sMethods_specs[] = { JS_FNSPEC("checkGuarded", (GenericMethod), reinterpret_cast(&checkGuarded_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("canAccessWindow", (GenericMethod), reinterpret_cast(&canAccessWindow_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("canAccessURI", (GenericMethod), reinterpret_cast(&canAccessURI_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("hasPermission", (GenericMethod), reinterpret_cast(&hasPermission_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("quarantinedFromURI", (GenericMethod), reinterpret_cast(&quarantinedFromURI_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("isWebAccessiblePath", (GenericMethod), reinterpret_cast(&isWebAccessiblePath_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("sourceMayAccessPath", (GenericMethod), reinterpret_cast(&sourceMayAccessPath_methodinfo), 2, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("localize", (GenericMethod), reinterpret_cast(&localize_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("getURL", (GenericMethod), reinterpret_cast(&getURL_methodinfo), 0, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("registerContentScript", (GenericMethod), reinterpret_cast(®isterContentScript_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("unregisterContentScript", (GenericMethod), reinterpret_cast(&unregisterContentScript_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("injectContentScripts", (GenericMethod), reinterpret_cast(&injectContentScripts_methodinfo), 0, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("isManifestBackgroundWorker", (GenericMethod), reinterpret_cast(&isManifestBackgroundWorker_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FS_END }; static const Prefable sMethods[] = { { nullptr, &sMethods_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(13 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); MOZ_GLOBINIT static const JSPropertySpec sAttributes_specs[] = { JSPropertySpec::nativeAccessors("id", JSPROP_ENUMERATE, GenericGetter, &id_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("mozExtensionHostname", JSPROP_ENUMERATE, GenericGetter, &mozExtensionHostname_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("baseURL", JSPROP_ENUMERATE, GenericGetter, &baseURL_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("name", JSPROP_ENUMERATE, GenericGetter, &name_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("version", JSPROP_ENUMERATE, GenericGetter, &version_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("type", JSPROP_ENUMERATE, GenericGetter, &type_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("isPrivileged", JSPROP_ENUMERATE, GenericGetter, &isPrivileged_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("temporarilyInstalled", JSPROP_ENUMERATE, GenericGetter, &temporarilyInstalled_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("manifestVersion", JSPROP_ENUMERATE, GenericGetter, &manifestVersion_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("baseCSP", JSPROP_ENUMERATE, GenericGetter, &baseCSP_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("extensionPageCSP", JSPROP_ENUMERATE, GenericGetter, &extensionPageCSP_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("sandboxPageCSP", JSPROP_ENUMERATE, GenericGetter, &sandboxPageCSP_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("permissions", JSPROP_ENUMERATE, GenericGetter, &permissions_getterinfo, GenericSetter, &permissions_setterinfo), JSPropertySpec::nativeAccessors("allowedOrigins", JSPROP_ENUMERATE, GenericGetter, &allowedOrigins_getterinfo, GenericSetter, &allowedOrigins_setterinfo), JSPropertySpec::nativeAccessors("fileSchemeAllowed", JSPROP_ENUMERATE, GenericGetter, &fileSchemeAllowed_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("guardSets", JSPROP_ENUMERATE, GenericGetter, &guardSets_getterinfo, GenericSetter, &guardSets_setterinfo), JSPropertySpec::nativeAccessors("contentScripts", JSPROP_ENUMERATE, GenericGetter, &contentScripts_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("active", JSPROP_ENUMERATE, GenericGetter, &active_getterinfo, GenericSetter, &active_setterinfo), JSPropertySpec::nativeAccessors("ignoreQuarantine", JSPROP_ENUMERATE, GenericGetter, &ignoreQuarantine_getterinfo, GenericSetter, &ignoreQuarantine_setterinfo), JSPropertySpec::nativeAccessors("hasRecommendedState", JSPROP_ENUMERATE, GenericGetter, &hasRecommendedState_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("privateBrowsingAllowed", JSPROP_ENUMERATE, GenericGetter, &privateBrowsingAllowed_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("readyPromise", JSPROP_ENUMERATE, GenericGetter, &readyPromise_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("browsingContextGroupId", JSPROP_ENUMERATE, GenericGetter, &browsingContextGroupId_getterinfo, nullptr, nullptr), JS_PS_END }; static const Prefable sAttributes[] = { { nullptr, &sAttributes_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(23 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); static uint16_t sNativeProperties_sortedPropertyIndices[46]; static PropertyInfo sNativeProperties_propertyInfos[46]; static const NativePropertiesN<4> sNativeProperties = { true, 0 /* sStaticMethods */, true, 1 /* sStaticAttributes */, true, 2 /* sMethods */, true, 3 /* sAttributes */, false, 0, false, 0, false, 0, -1, 46, sNativeProperties_sortedPropertyIndices, { { sStaticMethods, &sNativeProperties_propertyInfos[0] }, { sStaticAttributes, &sNativeProperties_propertyInfos[6] }, { sMethods, &sNativeProperties_propertyInfos[10] }, { sAttributes, &sNativeProperties_propertyInfos[23] } } }; static_assert(46 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)), "We have a property info count that is oversized"); // This may allocate too many slots, because we only really need // slots for our non-interface-typed members that we cache. But // allocating slots only for those would make the slot index // computations much more complicated, so let's do this the simple // way for now. DEFINE_XRAY_EXPANDO_CLASS_WITH_OPS(static, sXrayExpandoObjectClass, 7, &xpc::XrayExpandoObjectClassOps); bool sNativePropertiesInited = false; const NativePropertyHooks sNativePropertyHooks = { nullptr, { sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited }, prototypes::id::WebExtensionPolicy, constructors::id::WebExtensionPolicy, &sXrayExpandoObjectClass }; static bool _constructor(JSContext* cx_, unsigned argc, JS::Value* vp) { BindingCallContext cx(cx_, "WebExtensionPolicy constructor"); AUTO_PROFILER_LABEL_DYNAMIC_FAST( "WebExtensionPolicy", "constructor", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!args.isConstructing()) { return ThrowConstructorWithoutNew(cx, "WebExtensionPolicy"); } JS::Rooted desiredProto(cx); if (!GetDesiredProto(cx, args, prototypes::id::WebExtensionPolicy, CreateInterfaceObjects, &desiredProto)) { return false; } if (!args.requireAtLeast(cx, "WebExtensionPolicy constructor", 1)) { return false; } GlobalObject global(cx, obj); if (global.Failed()) { return false; } bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj); binding_detail::FastWebExtensionInit arg0; if (!arg0.Init(cx, args[0], "Argument 1", false)) { return false; } Maybe ar; if (objIsXray) { // Since our object is an Xray, we can just CheckedUnwrapStatic: // we know Xrays have no dynamic unwrap behavior. obj = js::CheckedUnwrapStatic(obj); if (!obj) { return false; } ar.emplace(cx, obj); if (!JS_WrapObject(cx, &desiredProto)) { return false; } } FastErrorResult rv; auto result(StrongOrRawPtr(mozilla::extensions::WebExtensionPolicy::Constructor(global, Constify(arg0), rv))); if (rv.MaybeSetPendingException(cx, "WebExtensionPolicy constructor")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); static_assert(!std::is_pointer_v, "NewObject implies that we need to keep the object alive with a strong reference."); if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const DOMInterfaceInfo sInterfaceObjectInfo = { { _constructor, &sNativePropertyHooks }, JS::GetRealmFunctionPrototypeHandle, PrototypeTraits::Depth, prototypes::id::WebExtensionPolicy, true, 1, "WebExtensionPolicy", }; static const DOMIfaceAndProtoJSClass sPrototypeClass = { { "WebExtensionPolicyPrototype", JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE), JS_NULL_CLASS_OPS, JS_NULL_CLASS_SPEC, JS_NULL_CLASS_EXT, JS_NULL_OBJECT_OPS }, eInterfacePrototype, prototypes::id::WebExtensionPolicy, PrototypeTraits::Depth, &sNativePropertyHooks, JS::GetRealmObjectPrototype }; bool ConstructorEnabled(JSContext* aCx, JS::Handle aObj) { return nsContentUtils::ThreadsafeIsSystemCaller(aCx); } static JS::Handle GetProtoObjectHandle(JSContext* aCx); static const JSClassOps sClassOps = { nullptr, /* addProperty */ nullptr, /* delProperty */ nullptr, /* enumerate */ nullptr, /* newEnumerate */ nullptr, /* resolve */ nullptr, /* mayResolve */ _finalize, /* finalize */ nullptr, /* call */ nullptr, /* construct */ nullptr, /* trace */ }; static const DOMJSClass sClass = { { "WebExtensionPolicy", JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(8) | JSCLASS_PRESERVES_WRAPPER, &sClassOps, JS_NULL_CLASS_SPEC, &NativeTypeHelpers::sClassExtension, JS_NULL_OBJECT_OPS }, { 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 }, std::is_base_of_v, &sNativePropertyHooks, GetProtoObjectHandle, GetCCParticipant::Get(), nullptr, NativeTypeHelpers::GetWrapperCache }; static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS, "Must have the right minimal number of reserved slots."); static_assert(8 >= 8, "Must have enough reserved slots."); static bool UpdateMemberSlots(JSContext* aCx, JS::Handle aWrapper, mozilla::extensions::WebExtensionPolicy* aObject) { JS::Rooted temp(aCx); JSJitGetterCallArgs args(&temp); static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) < JS::shadow::Object::MAX_FIXED_SLOTS, "Not enough fixed slots to fit 'WebExtensionPolicy.id. Ion's visitGetDOMMemberV/visitGetDOMMemberT assume StoreInSlot things are all in fixed slots."); if (!get_id(aCx, aWrapper, aObject, args)) { return false; } // Getter handled setting our reserved slots static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) < JS::shadow::Object::MAX_FIXED_SLOTS, "Not enough fixed slots to fit 'WebExtensionPolicy.mozExtensionHostname. Ion's visitGetDOMMemberV/visitGetDOMMemberT assume StoreInSlot things are all in fixed slots."); if (!get_mozExtensionHostname(aCx, aWrapper, aObject, args)) { return false; } // Getter handled setting our reserved slots return true; } bool Wrap(JSContext* aCx, mozilla::extensions::WebExtensionPolicy* aObject, nsWrapperCache* aCache, JS::Handle aGivenProto, JS::MutableHandle aReflector) { static_assert(!std::is_base_of_v, "Shouldn't have wrappercached things that are not refcounted."); static_assert(std::is_same_v); MOZ_ASSERT(ToSupportsIsCorrect(aObject)); MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx)); MOZ_ASSERT(!aCache->GetWrapper(), "You should probably not be using Wrap() directly; use " "GetOrCreateDOMReflector instead"); MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache), "nsISupports must be on our primary inheritance chain"); // If the wrapper cache contains a dead reflector then finalize that // now, ensuring that the finalizer for the old reflector always // runs before the new reflector is created and attached. This // avoids the awkward situation where there are multiple reflector // objects that contain pointers to the same native. if (JSObject* oldReflector = aCache->GetWrapperMaybeDead()) { _finalize(nullptr /* unused */, oldReflector); MOZ_ASSERT(!aCache->GetWrapperMaybeDead()); } JS::Rooted global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject())); if (!global) { return false; } MOZ_ASSERT(JS_IsGlobalObject(global)); JS::AssertObjectIsNotGray(global); // That might have ended up wrapping us already, due to the wonders // of XBL. Check for that, and bail out as needed. aReflector.set(aCache->GetWrapper()); if (aReflector) { #ifdef DEBUG AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto); #endif // DEBUG return true; } JSAutoRealm ar(aCx, global); JS::Handle canonicalProto = GetProtoObjectHandle(aCx); if (!canonicalProto) { return false; } JS::Rooted proto(aCx); if (aGivenProto) { proto = aGivenProto; // Unfortunately, while aGivenProto was in the compartment of aCx // coming in, we changed compartments to that of "parent" so may need // to wrap the proto here. if (js::GetContextCompartment(aCx) != JS::GetCompartment(proto)) { if (!JS_WrapObject(aCx, &proto)) { return false; } } } else { proto = canonicalProto; } BindingJSObjectCreator creator(aCx); creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector); if (!aReflector) { return false; } aCache->SetWrapper(aReflector); if (!UpdateMemberSlots(aCx, aReflector, aObject)) { aCache->ReleaseWrapper(aObject); aCache->ClearWrapperOnWrapFailure(); return false; } creator.InitializationSucceeded(); MOZ_ASSERT(aCache->GetWrapperPreserveColor() && aCache->GetWrapperPreserveColor() == aReflector); // If proto != canonicalProto, we have to preserve our wrapper; // otherwise we won't be able to properly recreate it later, since // we won't know what proto to use. Note that we don't check // aGivenProto here, since it's entirely possible (and even // somewhat common) to have a non-null aGivenProto which is the // same as canonicalProto. if (proto != canonicalProto) { PreserveWrapper(aObject); } return true; } void ClearCachedPermissionsValue(mozilla::extensions::WebExtensionPolicy* aObject) { JSObject* obj; obj = aObject->GetWrapper(); if (!obj) { return; } JS::SetNativeObjectReservedSlot(obj, (DOM_INSTANCE_RESERVED_SLOTS + 2), JS::UndefinedValue()); ClearXrayExpandoSlots(RootingCx(), obj, (DOM_EXPANDO_RESERVED_SLOTS + 2)); } void ClearCachedGuardSetsValue(mozilla::extensions::WebExtensionPolicy* aObject) { JSObject* obj; obj = aObject->GetWrapper(); if (!obj) { return; } JS::SetNativeObjectReservedSlot(obj, (DOM_INSTANCE_RESERVED_SLOTS + 3), JS::UndefinedValue()); ClearXrayExpandoSlots(RootingCx(), obj, (DOM_EXPANDO_RESERVED_SLOTS + 3)); } void ClearCachedContentScriptsValue(mozilla::extensions::WebExtensionPolicy* aObject) { JSObject* obj; obj = aObject->GetWrapper(); if (!obj) { return; } JS::SetNativeObjectReservedSlot(obj, (DOM_INSTANCE_RESERVED_SLOTS + 4), JS::UndefinedValue()); ClearXrayExpandoSlots(RootingCx(), obj, (DOM_EXPANDO_RESERVED_SLOTS + 4)); } void ClearCachedIgnoreQuarantineValue(mozilla::extensions::WebExtensionPolicy* aObject) { JSObject* obj; obj = aObject->GetWrapper(); if (!obj) { return; } JS::SetNativeObjectReservedSlot(obj, (DOM_INSTANCE_RESERVED_SLOTS + 5), JS::UndefinedValue()); ClearXrayExpandoSlots(RootingCx(), obj, (DOM_EXPANDO_RESERVED_SLOTS + 5)); } void ClearCachedHasRecommendedStateValue(mozilla::extensions::WebExtensionPolicy* aObject) { JSObject* obj; obj = aObject->GetWrapper(); if (!obj) { return; } JS::SetNativeObjectReservedSlot(obj, (DOM_INSTANCE_RESERVED_SLOTS + 6), JS::UndefinedValue()); ClearXrayExpandoSlots(RootingCx(), obj, (DOM_EXPANDO_RESERVED_SLOTS + 6)); } void CreateInterfaceObjects(JSContext* aCx, JS::Handle aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, DefineInterfaceProperty aDefineOnGlobal) { JS::Heap* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::WebExtensionPolicy); JS::Heap* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::WebExtensionPolicy); JS::Handle parentProto(JS::GetRealmObjectPrototypeHandle(aCx)); if (!parentProto) { return; } JS::Handle constructorProto(JS::GetRealmFunctionPrototypeHandle(aCx)); if (!constructorProto) { return; } dom::CreateInterfaceObjects(aCx, aGlobal, parentProto, &sPrototypeClass, protoCache, constructorProto, &sInterfaceObjectInfo, 1, false, Span{}, interfaceCache, sNativeProperties.Upcast(), nullptr, "WebExtensionPolicy", ShouldExpose(aCx, aGlobal, aDefineOnGlobal), nullptr, false, nullptr); } static JS::Handle GetProtoObjectHandle(JSContext* aCx) { /* Get the interface prototype object for this class. This will create the object as needed. */ return GetPerInterfaceObjectHandle(aCx, prototypes::id::WebExtensionPolicy, &CreateInterfaceObjects, DefineInterfaceProperty::CheckExposure); } JS::Handle GetConstructorObjectHandle(JSContext* aCx) { /* Get the interface object for this class. This will create the object as needed. */ return GetPerInterfaceObjectHandle(aCx, constructors::id::WebExtensionPolicy, &CreateInterfaceObjects, DefineInterfaceProperty::CheckExposure); } } // namespace WebExtensionPolicy_Binding } // namespace mozilla::dom