Copy as Markdown

Other Tools

/* THIS FILE IS AUTOGENERATED FROM AddonManager.webidl BY Codegen.py - DO NOT EDIT */
#include <type_traits>
#include "AddonManagerBinding.h"
#include "AtomList.h"
#include "EventTargetBinding.h"
#include "MainThreadUtils.h"
#include "WrapperFactory.h"
#include "js/CallAndConstruct.h"
#include "js/Exception.h"
#include "js/MapAndSet.h"
#include "js/Object.h"
#include "js/PropertyAndElement.h"
#include "js/PropertyDescriptor.h"
#include "js/experimental/JitInfo.h"
#include "mozilla/AddonManagerWebAPI.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/Promise.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/SimpleGlobalObject.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/XrayExpandoClass.h"
#include "nsContentUtils.h"
#include "nsIGlobalObject.h"
namespace mozilla::dom {
namespace binding_detail {}; // Just to make sure it's known as a namespace
using namespace mozilla::dom::binding_detail;
addonInstallOptions::addonInstallOptions()
{
// Safe to pass a null context if we pass a null value
Init(nullptr, JS::NullHandleValue);
}
bool
addonInstallOptions::InitIds(JSContext* cx, addonInstallOptionsAtoms* atomsCache)
{
MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());
// Initialize these in reverse order so that any failure leaves the first one
// uninitialized.
if (!atomsCache->url_id.init(cx, "url") ||
!atomsCache->hash_id.init(cx, "hash")) {
return false;
}
return true;
}
bool
addonInstallOptions::Init(BindingCallContext& cx, JS::Handle<JS::Value> 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());
addonInstallOptionsAtoms* atomsCache = nullptr;
if (cx) {
atomsCache = GetAtomCache<addonInstallOptionsAtoms>(cx);
if (reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) {
return false;
}
}
if (!IsConvertibleToDictionary(val)) {
return cx.ThrowErrorMessage<MSG_CONVERSION_ERROR>(sourceDescription, "dictionary");
}
bool isNull = val.isNullOrUndefined();
// We only need these if !isNull, in which case we have |cx|.
Maybe<JS::Rooted<JSObject *> > object;
Maybe<JS::Rooted<JS::Value> > temp;
if (!isNull) {
MOZ_ASSERT(cx);
object.emplace(cx, &val.toObject());
temp.emplace(cx);
}
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->hash_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, mHash)) {
return false;
}
} else {
mHash.SetIsVoid(true);
}
mIsAnyMemberPresent = true;
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->url_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mUrl)) {
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<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>("'url' member of addonInstallOptions");
}
return true;
}
bool
addonInstallOptions::Init(JSContext* cx_, JS::Handle<JS::Value> 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);
}
bool
addonInstallOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
{
addonInstallOptionsAtoms* atomsCache = GetAtomCache<addonInstallOptionsAtoms>(cx);
if (reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) {
return false;
}
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
if (!obj) {
return false;
}
rval.set(JS::ObjectValue(*obj));
do {
// block for our 'break' successCode and scope for 'temp' and 'currentValue'
JS::Rooted<JS::Value> temp(cx);
nsString const & currentValue = mHash;
if (!xpc::StringToJsval(cx, currentValue, &temp)) {
return false;
}
if (!JS_DefinePropertyById(cx, obj, atomsCache->hash_id, temp, JSPROP_ENUMERATE)) {
return false;
}
break;
} while(false);
do {
// block for our 'break' successCode and scope for 'temp' and 'currentValue'
JS::Rooted<JS::Value> temp(cx);
nsString const & currentValue = mUrl;
if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
return false;
}
if (!JS_DefinePropertyById(cx, obj, atomsCache->url_id, temp, JSPROP_ENUMERATE)) {
return false;
}
break;
} while(false);
return true;
}
void
addonInstallOptions::TraceDictionary(JSTracer* trc)
{
}
addonInstallOptions&
addonInstallOptions::operator=(const addonInstallOptions& aOther)
{
DictionaryBase::operator=(aOther);
mHash = aOther.mHash;
mUrl = aOther.mUrl;
return *this;
}
bool
addonInstallOptions::operator==(const addonInstallOptions& aOther) const
{
if (mHash != aOther.mHash) {
return false;
}
if (mUrl != aOther.mUrl) {
return false;
}
return true;
}
namespace Addon_Binding {
MOZ_CAN_RUN_SCRIPT static bool
get_id(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "id", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
DOMString result;
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetId(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))))>, "Should be returning void here");
MOZ_KnownLive(self)->GetId(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.id getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo id_getterinfo = {
{ get_id },
{ prototypes::id::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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
get_version(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "version", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
DOMString result;
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetVersion(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))))>, "Should be returning void here");
MOZ_KnownLive(self)->GetVersion(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.version getter"))) {
return false;
}
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::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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
get_type(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "type", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
DOMString result;
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetType(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))))>, "Should be returning void here");
MOZ_KnownLive(self)->GetType(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.type getter"))) {
return false;
}
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::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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
get_name(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "name", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
DOMString result;
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetName(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))))>, "Should be returning void here");
MOZ_KnownLive(self)->GetName(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.name getter"))) {
return false;
}
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::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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
get_description(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "description", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
DOMString result;
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetDescription(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))))>, "Should be returning void here");
MOZ_KnownLive(self)->GetDescription(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.description getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo description_getterinfo = {
{ get_description },
{ prototypes::id::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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
get_isEnabled(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "isEnabled", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
bool result(MOZ_KnownLive(self)->GetIsEnabled(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.isEnabled getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo isEnabled_getterinfo = {
{ get_isEnabled },
{ prototypes::id::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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_isActive(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "isActive", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
bool result(MOZ_KnownLive(self)->GetIsActive(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.isActive getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo isActive_getterinfo = {
{ get_isActive },
{ prototypes::id::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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_canUninstall(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "canUninstall", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
bool result(MOZ_KnownLive(self)->GetCanUninstall(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.canUninstall getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo canUninstall_getterinfo = {
{ get_canUninstall },
{ prototypes::id::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Getter,
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
uninstall(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "uninstall", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Uninstall(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.uninstall"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
uninstall_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = uninstall(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo uninstall_methodinfo = {
{ (JSJitGetterOp)uninstall_promiseWrapper },
{ prototypes::id::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_OBJECT, /* 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
setEnabled(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"Addon", "setEnabled", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::Addon*>(void_self);
if (!args.requireAtLeast(cx, "Addon.setEnabled", 1)) {
return false;
}
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
bool arg0;
if (!ValueToPrimitive<bool, eDefault>(cx, args[0], "Argument 1", &arg0)) {
return false;
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->SetEnabled(arg0, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "Addon.setEnabled"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
setEnabled_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = setEnabled(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo setEnabled_methodinfo = {
{ (JSJitGetterOp)setEnabled_promiseWrapper },
{ prototypes::id::Addon },
{ PrototypeTraits<prototypes::id::Addon>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_OBJECT, /* 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 bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::Addon* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Addon>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::Addon* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Addon>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::Addon>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::Addon* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Addon>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::Addon* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Addon>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sChromeStaticMethods_specs[] = {
JS_FNSPEC("_create", Addon::_Create, nullptr, 2, 0, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
{ nullptr, &sChromeStaticMethods_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(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("uninstall", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&uninstall_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("setEnabled", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&setEnabled_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("id", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &id_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("version", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &version_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("type", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &type_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("name", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &name_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("description", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &description_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("isEnabled", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &isEnabled_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("isActive", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &isActive_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("canUninstall", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &canUninstall_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(8 <= 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[10];
static PropertyInfo sNativeProperties_propertyInfos[10];
static const NativePropertiesN<2> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
true, 1 /* sAttributes */,
false, 0,
false, 0,
false, 0,
-1,
10,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[2] }
}
};
static_assert(10 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[1];
static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sChromeOnlyNativeProperties = {
true, 0 /* sChromeStaticMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sChromeOnlyNativeProperties_sortedPropertyIndices,
{
{ sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 1ull << (CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast(), &sNativePropertiesInited },
prototypes::id::Addon,
constructors::id::Addon,
&DefaultXrayExpandoObjectClass
};
static const DOMInterfaceInfo sInterfaceObjectInfo = {
{ ThrowingConstructor, &sNativePropertyHooks },
JS::GetRealmFunctionPrototype,
prototypes::id::Addon,
PrototypeTraits<prototypes::id::Addon>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"AddonPrototype",
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::Addon,
PrototypeTraits<prototypes::id::Addon>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return nsContentUtils::ThreadsafeIsSystemCaller(aCx);
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "Addon",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::Addon, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
std::is_base_of_v<nsISupports, mozilla::dom::Addon>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::Addon>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::Addon>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(1 >= 1,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::Addon* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::Addon>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::Addon*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::Addon> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
aCache->SetWrapper(aReflector);
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
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::Addon);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::Addon);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
sChromeOnlyNativeProperties.Upcast(),
"Addon", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace Addon_Binding
namespace AddonInstall_Binding {
static_assert(IsRefcounted<NativeType>::value == IsRefcounted<EventTarget_Binding::NativeType>::value,
"Can't inherit from an interface with a different ownership model.");
MOZ_CAN_RUN_SCRIPT static bool
get_state(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonInstall", "state", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonInstall*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
DOMString result;
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetState(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))))>, "Should be returning void here");
MOZ_KnownLive(self)->GetState(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonInstall.state getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo state_getterinfo = {
{ get_state },
{ prototypes::id::AddonInstall },
{ PrototypeTraits<prototypes::id::AddonInstall>::Depth },
JSJitInfo::Getter,
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
get_error(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonInstall", "error", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonInstall*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
DOMString result;
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetError(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))))>, "Should be returning void here");
MOZ_KnownLive(self)->GetError(result, rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonInstall.error getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!xpc::StringToJsval(cx, result, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo error_getterinfo = {
{ get_error },
{ prototypes::id::AddonInstall },
{ PrototypeTraits<prototypes::id::AddonInstall>::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
get_progress(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonInstall", "progress", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonInstall*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
int64_t result(MOZ_KnownLive(self)->GetProgress(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonInstall.progress getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().set(JS_NumberValue(double(result)));
return true;
}
static const JSJitInfo progress_getterinfo = {
{ get_progress },
{ prototypes::id::AddonInstall },
{ PrototypeTraits<prototypes::id::AddonInstall>::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. */
};
MOZ_CAN_RUN_SCRIPT static bool
get_maxProgress(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonInstall", "maxProgress", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonInstall*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
int64_t result(MOZ_KnownLive(self)->GetMaxProgress(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonInstall.maxProgress getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().set(JS_NumberValue(double(result)));
return true;
}
static const JSJitInfo maxProgress_getterinfo = {
{ get_maxProgress },
{ prototypes::id::AddonInstall },
{ PrototypeTraits<prototypes::id::AddonInstall>::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. */
};
MOZ_CAN_RUN_SCRIPT static bool
install(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonInstall", "install", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonInstall*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Install(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonInstall.install"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
install_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = install(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo install_methodinfo = {
{ (JSJitGetterOp)install_promiseWrapper },
{ prototypes::id::AddonInstall },
{ PrototypeTraits<prototypes::id::AddonInstall>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_OBJECT, /* 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
cancel(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonInstall", "cancel", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonInstall*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Cancel(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonInstall.cancel"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
cancel_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = cancel(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo cancel_methodinfo = {
{ (JSJitGetterOp)cancel_promiseWrapper },
{ prototypes::id::AddonInstall },
{ PrototypeTraits<prototypes::id::AddonInstall>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_OBJECT, /* 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 bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::AddonInstall* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonInstall>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::AddonInstall* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonInstall>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::AddonInstall>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::AddonInstall* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonInstall>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::AddonInstall* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonInstall>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sChromeStaticMethods_specs[] = {
JS_FNSPEC("_create", AddonInstall::_Create, nullptr, 2, 0, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
{ nullptr, &sChromeStaticMethods_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(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("install", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&install_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("cancel", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&cancel_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("state", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &state_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("error", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &error_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("progress", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &progress_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("maxProgress", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &maxProgress_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(4 <= 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[6];
static PropertyInfo sNativeProperties_propertyInfos[6];
static const NativePropertiesN<2> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
true, 1 /* sAttributes */,
false, 0,
false, 0,
false, 0,
-1,
6,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[2] }
}
};
static_assert(6 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[1];
static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sChromeOnlyNativeProperties = {
true, 0 /* sChromeStaticMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sChromeOnlyNativeProperties_sortedPropertyIndices,
{
{ sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 1ull << (CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast(), &sNativePropertiesInited },
prototypes::id::AddonInstall,
constructors::id::AddonInstall,
&DefaultXrayExpandoObjectClass
};
static const DOMInterfaceInfo sInterfaceObjectInfo = {
{ ThrowingConstructor, &sNativePropertyHooks },
EventTarget_Binding::GetConstructorObject,
prototypes::id::AddonInstall,
PrototypeTraits<prototypes::id::AddonInstall>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"AddonInstallPrototype",
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::AddonInstall,
PrototypeTraits<prototypes::id::AddonInstall>::Depth,
&sNativePropertyHooks,
EventTarget_Binding::GetProtoObject
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return nsContentUtils::ThreadsafeIsSystemCaller(aCx);
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "AddonInstall",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::EventTarget, prototypes::id::AddonInstall, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
std::is_base_of_v<nsISupports, mozilla::dom::AddonInstall>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::AddonInstall>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::AddonInstall>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(1 >= 1,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::AddonInstall* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::AddonInstall>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::AddonInstall*>);
MOZ_ASSERT(static_cast<mozilla::dom::EventTarget*>(aObject) ==
reinterpret_cast<mozilla::dom::EventTarget*>(aObject),
"Multiple inheritance for mozilla::dom::EventTarget is broken.");
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::AddonInstall> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
aCache->SetWrapper(aReflector);
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
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::AddonInstall);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::AddonInstall);
JS::Handle<JSObject*> parentProto(EventTarget_Binding::GetProtoObjectHandle(aCx));
if (!parentProto) {
return;
}
JS::Handle<JSObject*> constructorProto(EventTarget_Binding::GetConstructorObjectHandle(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
sChromeOnlyNativeProperties.Upcast(),
"AddonInstall", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace AddonInstall_Binding
namespace AddonManager_Binding {
static_assert(IsRefcounted<NativeType>::value == IsRefcounted<EventTarget_Binding::NativeType>::value,
"Can't inherit from an interface with a different ownership model.");
MOZ_CAN_RUN_SCRIPT static bool
getAddonByID(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonManager", "getAddonByID", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonManager*>(void_self);
if (!args.requireAtLeast(cx, "AddonManager.getAddonByID", 1)) {
return false;
}
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->GetAddonByID(NonNullHelper(Constify(arg0)), rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonManager.getAddonByID"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
getAddonByID_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = getAddonByID(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo getAddonByID_methodinfo = {
{ (JSJitGetterOp)getAddonByID_promiseWrapper },
{ prototypes::id::AddonManager },
{ PrototypeTraits<prototypes::id::AddonManager>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_OBJECT, /* 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
createInstall(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "AddonManager.createInstall");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonManager", "createInstall", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonManager*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
binding_detail::FastaddonInstallOptions arg0;
if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue, "Argument 1", true)) {
return false;
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->CreateInstall(Constify(arg0), rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonManager.createInstall"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
createInstall_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = createInstall(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo createInstall_methodinfo = {
{ (JSJitGetterOp)createInstall_promiseWrapper },
{ prototypes::id::AddonManager },
{ PrototypeTraits<prototypes::id::AddonManager>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_OBJECT, /* 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
reportAbuse(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonManager", "reportAbuse", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonManager*>(void_self);
if (!args.requireAtLeast(cx, "AddonManager.reportAbuse", 1)) {
return false;
}
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->ReportAbuse(NonNullHelper(Constify(arg0)), rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx)))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonManager.reportAbuse"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
reportAbuse_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = reportAbuse(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo reportAbuse_methodinfo = {
{ (JSJitGetterOp)reportAbuse_promiseWrapper },
{ prototypes::id::AddonManager },
{ PrototypeTraits<prototypes::id::AddonManager>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_OBJECT, /* 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_abuseReportPanelEnabled(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonManager", "abuseReportPanelEnabled", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::AddonManager*>(void_self);
Maybe<JS::Rooted<JSObject*> > unwrappedObj;
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (objIsXray) {
unwrappedObj.emplace(cx, obj);
}
if (objIsXray) {
// Since our object is an Xray, we can just CheckedUnwrapStatic:
// we know Xrays have no dynamic unwrap behavior.
unwrappedObj.ref() = js::CheckedUnwrapStatic(unwrappedObj.ref());
if (!unwrappedObj.ref()) {
return false;
}
}
FastErrorResult rv;
bool result(MOZ_KnownLive(self)->GetAbuseReportPanelEnabled(rv, (unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "AddonManager.abuseReportPanelEnabled getter"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo abuseReportPanelEnabled_getterinfo = {
{ get_abuseReportPanelEnabled },
{ prototypes::id::AddonManager },
{ PrototypeTraits<prototypes::id::AddonManager>::Depth },
JSJitInfo::Getter,
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. */
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::AddonManager* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonManager>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::AddonManager* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonManager>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::AddonManager>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::AddonManager* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonManager>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::AddonManager* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::AddonManager>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sChromeStaticMethods_specs[] = {
JS_FNSPEC("_create", AddonManager::_Create, nullptr, 2, 0, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
{ nullptr, &sChromeStaticMethods_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(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("getAddonByID", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&getAddonByID_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("createInstall", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&createInstall_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("reportAbuse", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&reportAbuse_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("abuseReportPanelEnabled", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &abuseReportPanelEnabled_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(1 <= 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[4];
static PropertyInfo sNativeProperties_propertyInfos[4];
static const NativePropertiesN<2> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
true, 1 /* sAttributes */,
false, 0,
false, 0,
false, 0,
-1,
4,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[3] }
}
};
static_assert(4 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[1];
static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sChromeOnlyNativeProperties = {
true, 0 /* sChromeStaticMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sChromeOnlyNativeProperties_sortedPropertyIndices,
{
{ sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 1ull << (CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast(), &sNativePropertiesInited },
prototypes::id::AddonManager,
constructors::id::AddonManager,
&DefaultXrayExpandoObjectClass
};
static const DOMInterfaceInfo sInterfaceObjectInfo = {
{ ThrowingConstructor, &sNativePropertyHooks },
EventTarget_Binding::GetConstructorObject,
prototypes::id::AddonManager,
PrototypeTraits<prototypes::id::AddonManager>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"AddonManagerPrototype",
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::AddonManager,
PrototypeTraits<prototypes::id::AddonManager>::Depth,
&sNativePropertyHooks,
EventTarget_Binding::GetProtoObject
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return mozilla::AddonManagerWebAPI::IsAPIEnabled(aCx, aObj);
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "AddonManager",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::EventTarget, prototypes::id::AddonManager, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
std::is_base_of_v<nsISupports, mozilla::dom::AddonManager>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::AddonManager>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::AddonManager>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(1 >= 1,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::AddonManager* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::AddonManager>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::AddonManager*>);
MOZ_ASSERT(static_cast<mozilla::dom::EventTarget*>(aObject) ==
reinterpret_cast<mozilla::dom::EventTarget*>(aObject),
"Multiple inheritance for mozilla::dom::EventTarget is broken.");
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::AddonManager> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
aCache->SetWrapper(aReflector);
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
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::AddonManager);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::AddonManager);
JS::Handle<JSObject*> parentProto(EventTarget_Binding::GetProtoObjectHandle(aCx));
if (!parentProto) {
return;
}
JS::Handle<JSObject*> constructorProto(EventTarget_Binding::GetConstructorObjectHandle(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
sChromeOnlyNativeProperties.Upcast(),
"AddonManager", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace AddonManager_Binding
namespace AddonManagerPermissions_Binding {
MOZ_CAN_RUN_SCRIPT static bool
isHostPermitted(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"AddonManagerPermissions", "isHostPermitted", 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<JSObject*> obj(cx, &args.callee());
if (!args.requireAtLeast(cx, "AddonManagerPermissions.isHostPermitted", 1)) {
return false;
}
GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
if (global.Failed()) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
bool result(mozilla::dom::AddonManagerPermissions::IsHostPermitted(global, NonNullHelper(Constify(arg0))));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSFunctionSpec sStaticMethods_specs[] = {
JS_FNSPEC("isHostPermitted", isHostPermitted, nullptr, 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 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[1];
static PropertyInfo sNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sNativeProperties = {
true, 0 /* sStaticMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sNativeProperties_sortedPropertyIndices,
{
{ sStaticMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited },
prototypes::id::_ID_Count,
constructors::id::AddonManagerPermissions,
&DefaultXrayExpandoObjectClass
};
static const DOMIfaceAndProtoJSClass sNamespaceObjectClass = {
{
"AddonManagerPermissions",
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS,
JS_NULL_CLASS_OPS,
JS_NULL_CLASS_SPEC,
JS_NULL_CLASS_EXT,
JS_NULL_OBJECT_OPS
},
eNamespace,
prototypes::id::_ID_Count,
0,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return nsContentUtils::ThreadsafeIsSystemCaller(aCx);
}
void
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!constructorProto) {
return;
}
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::AddonManagerPermissions);
dom::CreateNamespaceObject(aCx, aGlobal, constructorProto,
sNamespaceObjectClass,
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"AddonManagerPermissions", aDefineOnGlobal);
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace AddonManagerPermissions_Binding
already_AddRefed<Promise>
AddonJSImpl::Uninstall(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.uninstall", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JS::Value> callable(cx);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->uninstall_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::empty(), &rval)) {
aRv.NoteJSContextException(cx);
return nullptr;
}
RefPtr<Promise> rvalDecl;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
if (!rval.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of Addon.uninstall");
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrapStatic(&rval.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of Addon.uninstall");
return nullptr;
}
globalObj = JS::GetNonCCWObjectGlobal(unwrappedVal);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> valueToResolve(cx, rval);
if (!JS_WrapValue(cx, &valueToResolve)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rvalDecl = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
already_AddRefed<Promise>
AddonJSImpl::SetEnabled(bool value, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.setEnabled", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
// That threw an exception on the JSContext, and our CallSetup will do
// the right thing with that.
return nullptr;
}
unsigned argc = 1;
do {
argv[0].setBoolean(value);
break;
} while (false);
JS::Rooted<JS::Value> callable(cx);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->setEnabled_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
aRv.NoteJSContextException(cx);
return nullptr;
}
RefPtr<Promise> rvalDecl;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
if (!rval.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of Addon.setEnabled");
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrapStatic(&rval.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of Addon.setEnabled");
return nullptr;
}
globalObj = JS::GetNonCCWObjectGlobal(unwrappedVal);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> valueToResolve(cx, rval);
if (!JS_WrapValue(cx, &valueToResolve)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rvalDecl = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
bool
AddonJSImpl::InitIds(JSContext* cx, AddonAtoms* atomsCache)
{
MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());
// Initialize these in reverse order so that any failure leaves the first one
// uninitialized.
if (!atomsCache->setEnabled_id.init(cx, "setEnabled") ||
!atomsCache->uninstall_id.init(cx, "uninstall") ||
!atomsCache->canUninstall_id.init(cx, "canUninstall") ||
!atomsCache->isActive_id.init(cx, "isActive") ||
!atomsCache->isEnabled_id.init(cx, "isEnabled") ||
!atomsCache->description_id.init(cx, "description") ||
!atomsCache->name_id.init(cx, "name") ||
!atomsCache->type_id.init(cx, "type") ||
!atomsCache->version_id.init(cx, "version") ||
!atomsCache->id_id.init(cx, "id")) {
return false;
}
return true;
}
void
AddonJSImpl::GetId(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.id", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->id_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
binding_detail::FakeString<char16_t> rvalDecl;
if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRetVal = rvalDecl;
}
void
AddonJSImpl::GetVersion(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.version", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->version_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
binding_detail::FakeString<char16_t> rvalDecl;
if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRetVal = rvalDecl;
}
void
AddonJSImpl::GetType(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.type", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->type_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
binding_detail::FakeString<char16_t> rvalDecl;
if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRetVal = rvalDecl;
}
void
AddonJSImpl::GetName(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.name", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->name_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
binding_detail::FakeString<char16_t> rvalDecl;
if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRetVal = rvalDecl;
}
void
AddonJSImpl::GetDescription(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.description", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->description_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
binding_detail::FakeString<char16_t> rvalDecl;
if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRetVal = rvalDecl;
}
bool
AddonJSImpl::GetIsEnabled(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.isEnabled", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return bool(0);
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->isEnabled_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
bool rvalDecl;
if (!ValueToPrimitive<bool, eDefault>(cx, rval, "Return value of Addon.isEnabled", &rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return rvalDecl;
}
bool
AddonJSImpl::GetIsActive(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.isActive", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return bool(0);
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->isActive_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
bool rvalDecl;
if (!ValueToPrimitive<bool, eDefault>(cx, rval, "Return value of Addon.isActive", &rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return rvalDecl;
}
bool
AddonJSImpl::GetCanUninstall(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "Addon.canUninstall", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return bool(0);
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonAtoms* atomsCache = GetAtomCache<AddonAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->canUninstall_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
bool rvalDecl;
if (!ValueToPrimitive<bool, eDefault>(cx, rval, "Return value of Addon.canUninstall", &rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return rvalDecl;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Addon)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Addon)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mImpl)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->ClearWeakReferences();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Addon)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(Addon)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Addon)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Addon)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END
Addon::Addon(JS::Handle<JSObject*> aJSImplObject, JS::Handle<JSObject*> aJSImplGlobal, nsIGlobalObject* aParent)
: mImpl(new AddonJSImpl(nullptr, aJSImplObject, aJSImplGlobal, /* aIncumbentGlobal = */ nullptr)),
mParent(aParent)
{
}
Addon::~Addon()
{
}
nsISupports*
Addon::GetParentObject() const
{
return mParent;
}
JSObject*
Addon::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
JS::Rooted<JSObject*> obj(aCx, Addon_Binding::Wrap(aCx, this, aGivenProto));
if (!obj) {
return nullptr;
}
// Now define it on our chrome object
JSAutoRealm ar(aCx, mImpl->CallbackGlobalOrNull());
if (!JS_WrapObject(aCx, &obj)) {
return nullptr;
}
JS::Rooted<JSObject*> callback(aCx, mImpl->CallbackOrNull());
if (!JS_DefineProperty(aCx, callback, "__DOM_IMPL__", obj, 0)) {
return nullptr;
}
return obj;
}
void
Addon::GetId(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetId(aRetVal, aRv, aRealm);
}
void
Addon::GetVersion(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetVersion(aRetVal, aRv, aRealm);
}
void
Addon::GetType(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetType(aRetVal, aRv, aRealm);
}
void
Addon::GetName(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetName(aRetVal, aRv, aRealm);
}
void
Addon::GetDescription(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetDescription(aRetVal, aRv, aRealm);
}
bool
Addon::GetIsEnabled(ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetIsEnabled(aRv, aRealm);
}
bool
Addon::GetIsActive(ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetIsActive(aRv, aRealm);
}
bool
Addon::GetCanUninstall(ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetCanUninstall(aRv, aRealm);
}
// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
already_AddRefed<Promise>
Addon::Uninstall(ErrorResult& aRv, JS::Realm* aRealm)
{
return mImpl->Uninstall(aRv, aRealm);
}
// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
already_AddRefed<Promise>
Addon::SetEnabled(bool value, ErrorResult& aRv, JS::Realm* aRealm)
{
return mImpl->SetEnabled(value, aRv, aRealm);
}
bool
Addon::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (!args.requireAtLeast(cx, "Addon._create", 2)) {
return false;
}
BindingCallContext callCx(cx, "Addon._create");
if (!args[0].isObject()) {
return callCx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
}
if (!args[1].isObject()) {
return callCx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 2");
}
// GlobalObject will go through wrappers as needed for us, and
// is simpler than the right UnwrapArg incantation.
GlobalObject global(cx, &args[0].toObject());
if (global.Failed()) {
return false;
}
nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
MOZ_ASSERT(globalHolder);
JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
JS::Rooted<JSObject*> argGlobal(cx, JS::CurrentGlobalOrNull(cx));
RefPtr<Addon> impl = new Addon(arg, argGlobal, globalHolder);
MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
return GetOrCreateDOMReflector(cx, impl, args.rval());
}
already_AddRefed<Promise>
AddonInstallJSImpl::Install(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonInstall.install", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JS::Value> callable(cx);
AddonInstallAtoms* atomsCache = GetAtomCache<AddonInstallAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->install_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::empty(), &rval)) {
aRv.NoteJSContextException(cx);
return nullptr;
}
RefPtr<Promise> rvalDecl;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
if (!rval.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonInstall.install");
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrapStatic(&rval.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonInstall.install");
return nullptr;
}
globalObj = JS::GetNonCCWObjectGlobal(unwrappedVal);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> valueToResolve(cx, rval);
if (!JS_WrapValue(cx, &valueToResolve)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rvalDecl = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
already_AddRefed<Promise>
AddonInstallJSImpl::Cancel(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonInstall.cancel", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JS::Value> callable(cx);
AddonInstallAtoms* atomsCache = GetAtomCache<AddonInstallAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->cancel_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::empty(), &rval)) {
aRv.NoteJSContextException(cx);
return nullptr;
}
RefPtr<Promise> rvalDecl;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
if (!rval.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonInstall.cancel");
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrapStatic(&rval.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonInstall.cancel");
return nullptr;
}
globalObj = JS::GetNonCCWObjectGlobal(unwrappedVal);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> valueToResolve(cx, rval);
if (!JS_WrapValue(cx, &valueToResolve)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rvalDecl = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
bool
AddonInstallJSImpl::InitIds(JSContext* cx, AddonInstallAtoms* atomsCache)
{
MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());
// Initialize these in reverse order so that any failure leaves the first one
// uninitialized.
if (!atomsCache->cancel_id.init(cx, "cancel") ||
!atomsCache->install_id.init(cx, "install") ||
!atomsCache->maxProgress_id.init(cx, "maxProgress") ||
!atomsCache->progress_id.init(cx, "progress") ||
!atomsCache->error_id.init(cx, "error") ||
!atomsCache->state_id.init(cx, "state")) {
return false;
}
return true;
}
void
AddonInstallJSImpl::GetState(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonInstall.state", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonInstallAtoms* atomsCache = GetAtomCache<AddonInstallAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->state_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
binding_detail::FakeString<char16_t> rvalDecl;
if (!ConvertJSValueToString(cx, rval, eStringify, eStringify, rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRetVal = rvalDecl;
}
void
AddonInstallJSImpl::GetError(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonInstall.error", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonInstallAtoms* atomsCache = GetAtomCache<AddonInstallAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->error_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
binding_detail::FakeString<char16_t> rvalDecl;
if (!ConvertJSValueToString(cx, rval, eNull, eNull, rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRetVal = rvalDecl;
}
int64_t
AddonInstallJSImpl::GetProgress(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonInstall.progress", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return int64_t(0);
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonInstallAtoms* atomsCache = GetAtomCache<AddonInstallAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->progress_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int64_t(0);
}
int64_t rvalDecl;
if (!ValueToPrimitive<int64_t, eDefault>(cx, rval, "Return value of AddonInstall.progress", &rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int64_t(0);
}
return rvalDecl;
}
int64_t
AddonInstallJSImpl::GetMaxProgress(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonInstall.maxProgress", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return int64_t(0);
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonInstallAtoms* atomsCache = GetAtomCache<AddonInstallAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->maxProgress_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int64_t(0);
}
int64_t rvalDecl;
if (!ValueToPrimitive<int64_t, eDefault>(cx, rval, "Return value of AddonInstall.maxProgress", &rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int64_t(0);
}
return rvalDecl;
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(AddonInstall, mozilla::DOMEventTargetHelper, mImpl, mParent)
NS_IMPL_ADDREF_INHERITED(AddonInstall, mozilla::DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(AddonInstall, mozilla::DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AddonInstall)
NS_INTERFACE_MAP_END_INHERITING(mozilla::DOMEventTargetHelper)
AddonInstall::AddonInstall(JS::Handle<JSObject*> aJSImplObject, JS::Handle<JSObject*> aJSImplGlobal, nsIGlobalObject* aParent)
: mozilla::DOMEventTargetHelper(aParent),
mImpl(new AddonInstallJSImpl(nullptr, aJSImplObject, aJSImplGlobal, /* aIncumbentGlobal = */ nullptr)),
mParent(aParent)
{
}
AddonInstall::~AddonInstall()
{
}
nsISupports*
AddonInstall::GetParentObject() const
{
return mParent;
}
JSObject*
AddonInstall::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
JS::Rooted<JSObject*> obj(aCx, AddonInstall_Binding::Wrap(aCx, this, aGivenProto));
if (!obj) {
return nullptr;
}
// Now define it on our chrome object
JSAutoRealm ar(aCx, mImpl->CallbackGlobalOrNull());
if (!JS_WrapObject(aCx, &obj)) {
return nullptr;
}
JS::Rooted<JSObject*> callback(aCx, mImpl->CallbackOrNull());
if (!JS_DefineProperty(aCx, callback, "__DOM_IMPL__", obj, 0)) {
return nullptr;
}
return obj;
}
void
AddonInstall::GetState(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetState(aRetVal, aRv, aRealm);
}
void
AddonInstall::GetError(nsString& aRetVal, ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetError(aRetVal, aRv, aRealm);
}
int64_t
AddonInstall::GetProgress(ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetProgress(aRv, aRealm);
}
int64_t
AddonInstall::GetMaxProgress(ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetMaxProgress(aRv, aRealm);
}
// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
already_AddRefed<Promise>
AddonInstall::Install(ErrorResult& aRv, JS::Realm* aRealm)
{
return mImpl->Install(aRv, aRealm);
}
// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
already_AddRefed<Promise>
AddonInstall::Cancel(ErrorResult& aRv, JS::Realm* aRealm)
{
return mImpl->Cancel(aRv, aRealm);
}
bool
AddonInstall::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (!args.requireAtLeast(cx, "AddonInstall._create", 2)) {
return false;
}
BindingCallContext callCx(cx, "AddonInstall._create");
if (!args[0].isObject()) {
return callCx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
}
if (!args[1].isObject()) {
return callCx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 2");
}
// GlobalObject will go through wrappers as needed for us, and
// is simpler than the right UnwrapArg incantation.
GlobalObject global(cx, &args[0].toObject());
if (global.Failed()) {
return false;
}
nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
MOZ_ASSERT(globalHolder);
JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
JS::Rooted<JSObject*> argGlobal(cx, JS::CurrentGlobalOrNull(cx));
RefPtr<AddonInstall> impl = new AddonInstall(arg, argGlobal, globalHolder);
MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
return GetOrCreateDOMReflector(cx, impl, args.rval());
}
already_AddRefed<Promise>
AddonManagerJSImpl::GetAddonByID(const nsAString& id, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonManager.getAddonByID", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
// That threw an exception on the JSContext, and our CallSetup will do
// the right thing with that.
return nullptr;
}
unsigned argc = 1;
do {
if (!xpc::NonVoidStringToJsval(cx, id, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
break;
} while (false);
JS::Rooted<JS::Value> callable(cx);
AddonManagerAtoms* atomsCache = GetAtomCache<AddonManagerAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->getAddonByID_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
aRv.NoteJSContextException(cx);
return nullptr;
}
RefPtr<Promise> rvalDecl;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
if (!rval.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonManager.getAddonByID");
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrapStatic(&rval.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonManager.getAddonByID");
return nullptr;
}
globalObj = JS::GetNonCCWObjectGlobal(unwrappedVal);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> valueToResolve(cx, rval);
if (!JS_WrapValue(cx, &valueToResolve)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rvalDecl = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
already_AddRefed<Promise>
AddonManagerJSImpl::CreateInstall(const addonInstallOptions& options, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonManager.createInstall", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
// That threw an exception on the JSContext, and our CallSetup will do
// the right thing with that.
return nullptr;
}
unsigned argc = 1;
do {
if (!options.ToObjectInternal(cx, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
break;
} while (false);
JS::Rooted<JS::Value> callable(cx);
AddonManagerAtoms* atomsCache = GetAtomCache<AddonManagerAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->createInstall_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
aRv.NoteJSContextException(cx);
return nullptr;
}
RefPtr<Promise> rvalDecl;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
if (!rval.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonManager.createInstall");
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrapStatic(&rval.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonManager.createInstall");
return nullptr;
}
globalObj = JS::GetNonCCWObjectGlobal(unwrappedVal);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> valueToResolve(cx, rval);
if (!JS_WrapValue(cx, &valueToResolve)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rvalDecl = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
already_AddRefed<Promise>
AddonManagerJSImpl::ReportAbuse(const nsAString& id, ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonManager.reportAbuse", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
// That threw an exception on the JSContext, and our CallSetup will do
// the right thing with that.
return nullptr;
}
unsigned argc = 1;
do {
if (!xpc::NonVoidStringToJsval(cx, id, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
break;
} while (false);
JS::Rooted<JS::Value> callable(cx);
AddonManagerAtoms* atomsCache = GetAtomCache<AddonManagerAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->reportAbuse_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
aRv.NoteJSContextException(cx);
return nullptr;
}
RefPtr<Promise> rvalDecl;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
if (!rval.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonManager.reportAbuse");
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrapStatic(&rval.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>("return value of AddonManager.reportAbuse");
return nullptr;
}
globalObj = JS::GetNonCCWObjectGlobal(unwrappedVal);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JS::Rooted<JS::Value> valueToResolve(cx, rval);
if (!JS_WrapValue(cx, &valueToResolve)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
rvalDecl = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
void
AddonManagerJSImpl::EventListenerAdded(const nsAString& aType, ErrorResult& aRv, const char* aExecutionReason, ExceptionHandling aExceptionHandling, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "EventListenerAdded", aExceptionHandling, aRealm);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::RootedVector<JS::Value> 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, aType, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JS::Value> callable(cx);
AddonManagerAtoms* atomsCache = GetAtomCache<AddonManagerAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->eventListenerAdded_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
aRv.NoteJSContextException(cx);
return;
}
}
void
AddonManagerJSImpl::EventListenerRemoved(const nsAString& aType, ErrorResult& aRv, const char* aExecutionReason, ExceptionHandling aExceptionHandling, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "EventListenerRemoved", aExceptionHandling, aRealm);
if (aRv.Failed()) {
return;
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::RootedVector<JS::Value> 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, aType, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JS::Value> callable(cx);
AddonManagerAtoms* atomsCache = GetAtomCache<AddonManagerAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) ||
!GetCallableProperty(cx, atomsCache->eventListenerRemoved_id, &callable)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, thisValue, callable,
JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
aRv.NoteJSContextException(cx);
return;
}
}
bool
AddonManagerJSImpl::InitIds(JSContext* cx, AddonManagerAtoms* atomsCache)
{
MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());
// Initialize these in reverse order so that any failure leaves the first one
// uninitialized.
if (!atomsCache->eventListenerRemoved_id.init(cx, "eventListenerRemoved") ||
!atomsCache->eventListenerAdded_id.init(cx, "eventListenerAdded") ||
!atomsCache->abuseReportPanelEnabled_id.init(cx, "abuseReportPanelEnabled") ||
!atomsCache->reportAbuse_id.init(cx, "reportAbuse") ||
!atomsCache->createInstall_id.init(cx, "createInstall") ||
!atomsCache->getAddonByID_id.init(cx, "getAddonByID")) {
return false;
}
return true;
}
bool
AddonManagerJSImpl::GetAbuseReportPanelEnabled(ErrorResult& aRv, JS::Realm* aRealm)
{
CallSetup s(this, aRv, "AddonManager.abuseReportPanelEnabled", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ true);
if (aRv.Failed()) {
return bool(0);
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JSObject *> callback(cx, mCallback);
AddonManagerAtoms* atomsCache = GetAtomCache<AddonManagerAtoms>(cx);
if ((reinterpret_cast<jsid*>(atomsCache)->isVoid()
&& !InitIds(cx, atomsCache)) ||
!JS_GetPropertyById(cx, callback, atomsCache->abuseReportPanelEnabled_id, &rval)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
bool rvalDecl;
if (!ValueToPrimitive<bool, eDefault>(cx, rval, "Return value of AddonManager.abuseReportPanelEnabled", &rvalDecl)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return rvalDecl;
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(AddonManager, mozilla::DOMEventTargetHelper, mImpl, mParent)
NS_IMPL_ADDREF_INHERITED(AddonManager, mozilla::DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(AddonManager, mozilla::DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AddonManager)
NS_INTERFACE_MAP_END_INHERITING(mozilla::DOMEventTargetHelper)
AddonManager::AddonManager(JS::Handle<JSObject*> aJSImplObject, JS::Handle<JSObject*> aJSImplGlobal, nsIGlobalObject* aParent)
: mozilla::DOMEventTargetHelper(aParent),
mImpl(new AddonManagerJSImpl(nullptr, aJSImplObject, aJSImplGlobal, /* aIncumbentGlobal = */ nullptr)),
mParent(aParent)
{
}
AddonManager::~AddonManager()
{
}
nsISupports*
AddonManager::GetParentObject() const
{
return mParent;
}
JSObject*
AddonManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
JS::Rooted<JSObject*> obj(aCx, AddonManager_Binding::Wrap(aCx, this, aGivenProto));
if (!obj) {
return nullptr;
}
// Now define it on our chrome object
JSAutoRealm ar(aCx, mImpl->CallbackGlobalOrNull());
if (!JS_WrapObject(aCx, &obj)) {
return nullptr;
}
JS::Rooted<JSObject*> callback(aCx, mImpl->CallbackOrNull());
if (!JS_DefineProperty(aCx, callback, "__DOM_IMPL__", obj, 0)) {
return nullptr;
}
return obj;
}
// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
already_AddRefed<Promise>
AddonManager::GetAddonByID(const nsAString& id, ErrorResult& aRv, JS::Realm* aRealm)
{
return mImpl->GetAddonByID(id, aRv, aRealm);
}
// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
already_AddRefed<Promise>
AddonManager::CreateInstall(const addonInstallOptions& options, ErrorResult& aRv, JS::Realm* aRealm)
{
return mImpl->CreateInstall(options, aRv, aRealm);
}
// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).
already_AddRefed<Promise>
AddonManager::ReportAbuse(const nsAString& id, ErrorResult& aRv, JS::Realm* aRealm)
{
return mImpl->ReportAbuse(id, aRv, aRealm);
}
bool
AddonManager::GetAbuseReportPanelEnabled(ErrorResult& aRv, JS::Realm* aRealm) const
{
return mImpl->GetAbuseReportPanelEnabled(aRv, aRealm);
}
void
AddonManager::EventListenerAdded(nsAtom* aType)
{
mozilla::DOMEventTargetHelper::EventListenerAdded(aType);
mImpl->EventListenerAdded(Substring(nsDependentAtomString(aType), 2), IgnoreErrors());
}
void
AddonManager::EventListenerRemoved(nsAtom* aType)
{
mozilla::DOMEventTargetHelper::EventListenerRemoved(aType);
mImpl->EventListenerRemoved(Substring(nsDependentAtomString(aType), 2), IgnoreErrors());
}
bool
AddonManager::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (!args.requireAtLeast(cx, "AddonManager._create", 2)) {
return false;
}
BindingCallContext callCx(cx, "AddonManager._create");
if (!args[0].isObject()) {
return callCx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
}
if (!args[1].isObject()) {
return callCx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 2");
}
// GlobalObject will go through wrappers as needed for us, and
// is simpler than the right UnwrapArg incantation.
GlobalObject global(cx, &args[0].toObject());
if (global.Failed()) {
return false;
}
nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
MOZ_ASSERT(globalHolder);
JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
JS::Rooted<JSObject*> argGlobal(cx, JS::CurrentGlobalOrNull(cx));
RefPtr<AddonManager> impl = new AddonManager(arg, argGlobal, globalHolder);
MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
return GetOrCreateDOMReflector(cx, impl, args.rval());
}
} // namespace mozilla::dom