/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* The "Components" xpcom objects for JavaScript. */
class nsXPCComponents_Interfaces final : public nsIXPCComponents_Interfaces, public nsIXPCScriptable, public nsIClassInfo { public: // all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCCOMPONENTS_INTERFACES
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSICLASSINFO
// The nsIXPCScriptable map declaration that will generate stubs for us... #define XPC_MAP_CLASSNAME nsXPCComponents_Interfaces #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Interfaces" #define XPC_MAP_FLAGS \
(XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE) #include"xpc_map_end.h"/* This will #undef the above */
for (uint32_t index = 0; index < nsXPTInterfaceInfo::InterfaceCount();
index++) { const nsXPTInterfaceInfo* interface = nsXPTInterfaceInfo::ByIndex(index); if (!interface) { continue;
}
constchar* name = interface->Name(); if (!name) { continue;
}
RootedString str(cx, id.toString());
JS::UniqueChars name = JS_EncodeStringToLatin1(cx, str);
// we only allow interfaces by name here if (name && name[0] != '{') { const nsXPTInterfaceInfo* info = nsXPTInterfaceInfo::ByName(name.get()); if (!info) { return NS_OK;
}
class nsXPCComponents_Classes final : public nsIXPCComponents_Classes, public nsIXPCScriptable, public nsIClassInfo { public: // all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCCOMPONENTS_CLASSES
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSICLASSINFO
// The nsIXPCScriptable map declaration that will generate stubs for us... #define XPC_MAP_CLASSNAME nsXPCComponents_Classes #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Classes" #define XPC_MAP_FLAGS \
(XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE) #include"xpc_map_end.h"/* This will #undef the above */
// Currently the possible results do not change at runtime, so they are only // cached once (unlike ContractIDs, CLSIDs, and IIDs)
class nsXPCComponents_Results final : public nsIXPCComponents_Results, public nsIXPCScriptable, public nsIClassInfo { public: // all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCCOMPONENTS_RESULTS
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSICLASSINFO
// The nsIXPCScriptable map declaration that will generate stubs for us... #define XPC_MAP_CLASSNAME nsXPCComponents_Results #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Results" #define XPC_MAP_FLAGS \
(XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE) #include"xpc_map_end.h"/* This will #undef the above */
JS::UniqueChars name = JS_EncodeStringToLatin1(cx, id.toString()); if (name) { constchar* rv_name; constvoid* iter = nullptr;
nsresult rv; while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) { if (!strcmp(name.get(), rv_name)) {
*resolvedp = true; if (!JS_DefinePropertyById(cx, obj, id, (uint32_t)rv,
JSPROP_ENUMERATE | JSPROP_READONLY |
JSPROP_PERMANENT | JSPROP_RESOLVING)) { return NS_ERROR_UNEXPECTED;
}
}
}
} return NS_OK;
}
/***************************************************************************/ // JavaScript Constructor for nsIJSID objects (Components.ID)
class nsXPCComponents_ID final : public nsIXPCComponents_ID, public nsIXPCScriptable, public nsIClassInfo { public: // all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCCOMPONENTS_ID
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSICLASSINFO
// static
nsresult nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
JSContext* cx, HandleObject obj, const CallArgs& args, bool* _retval) { // make sure we have at least one arg
if (args.length() < 1) { return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
}
// Prevent non-chrome code from creating ID objects. if (!nsContentUtils::IsCallerChrome()) { return ThrowAndFail(NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED, cx, _retval);
}
// convert the first argument into a string and see if it looks like an id
/***************************************************************************/ // JavaScript Constructor for Exception objects (Components.Exception)
class nsXPCComponents_Exception final : public nsIXPCComponents_Exception, public nsIXPCScriptable, public nsIClassInfo { public: // all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSICLASSINFO
// Public exception parameter values. During construction, these are // initialized to the appropriate defaults. constchar* eMsg;
nsresult eResult;
nsCOMPtr<nsIStackFrame> eStack;
nsCOMPtr<nsISupports> eData;
// Parse the constructor arguments into the above |eFoo| parameter values. bool parse(const CallArgs& args) { /* * The Components.Exception takes a series of arguments, all of them * optional: * * Argument 0: Exception message (defaults to 'exception'). * Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options * object (see below). * Argument 2: Stack (defaults to the current stack, which we trigger * by leaving this nullptr in the parser). * Argument 3: Optional user data (defaults to nullptr). * * To dig our way out of this clunky API, we now support passing an * options object as the second parameter (as opposed to a result code). * If this is the case, all subsequent arguments are ignored, and the * following properties are parsed out of the object (using the * associated default if the property does not exist): * * result: Result code (see argument 1). * stack: Call stack (see argument 2). * data: User data (see argument 3).
*/ if (args.length() > 0 && !parseMessage(args[0])) { returnfalse;
} if (args.length() > 1) { if (args[1].isObject()) {
RootedObject obj(cx, &args[1].toObject()); return parseOptionsObject(obj);
} if (!parseResult(args[1])) { returnfalse;
}
} if (args.length() > 2) { if (!parseStack(args[2])) { returnfalse;
}
} if (args.length() > 3) { if (!parseData(args[3])) { returnfalse;
}
} returntrue;
}
bool parseStack(HandleValue v) { if (!v.isObject()) { // eStack has already been initialized to null, which is what we want // for any non-object values (including null). returntrue;
}
bool parseData(HandleValue v) { if (!v.isObject()) { // eData has already been initialized to null, which is what we want // for any non-object values (including null). returntrue;
}
// Parse the arguments to the Exception constructor.
ExceptionArgParser parser(cx, xpc); if (!parser.parse(args)) { return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
}
RefPtr<Exception> e = new Exception(nsCString(parser.eMsg), parser.eResult, ""_ns, parser.eStack, parser.eData);
RootedObject newObj(cx); if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIException),
newObj.address())) ||
!newObj) { return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
}
/*******************************************************/ // JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
class nsXPCComponents_Constructor final : public nsIXPCComponents_Constructor, public nsIXPCScriptable, public nsIClassInfo { public: // all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSICLASSINFO
// Fetch the property name ids, so we can look them up.
XPCJSRuntime* runtime = XPCJSRuntime::Get();
HandleId classIDProp = runtime->GetStringID(XPCJSContext::IDX_CLASS_ID);
HandleId interfaceIDProp =
runtime->GetStringID(XPCJSContext::IDX_INTERFACE_ID);
HandleId initializerProp =
runtime->GetStringID(XPCJSContext::IDX_INITIALIZER);
// Get properties ('classID', 'interfaceID', and 'initializer') off the // constructor object.
RootedValue classIDv(cx);
RootedValue interfaceID(cx);
RootedValue initializer(cx); if (!JS_GetPropertyById(cx, callee, classIDProp, &classIDv) ||
!JS_GetPropertyById(cx, callee, interfaceIDProp, &interfaceID) ||
!JS_GetPropertyById(cx, callee, initializerProp, &initializer)) { returnfalse;
} if (!classIDv.isObject() || !interfaceID.isObject()) {
XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx); returnfalse;
}
// Call 'createInstance' on the 'classID' object to create the object.
RootedValue instancev(cx);
RootedObject classID(cx, &classIDv.toObject()); if (!JS_CallFunctionName(cx, classID, "createInstance",
HandleValueArray(interfaceID), &instancev)) { returnfalse;
} if (!instancev.isObject()) {
XPCThrower::Throw(NS_ERROR_FAILURE, cx); returnfalse;
}
// Call the method 'initializer' on the instance, passing in our parameters. if (!initializer.isUndefined()) {
RootedValue dummy(cx);
RootedValue initfunc(cx);
RootedId initid(cx);
RootedObject instance(cx, &instancev.toObject()); if (!JS_ValueToId(cx, initializer, &initid) ||
!JS_GetPropertyById(cx, instance, initid, &initfunc) ||
!JS_CallFunctionValue(cx, instance, initfunc, args, &dummy)) { returnfalse;
}
}
// static
nsresult nsXPCComponents_Constructor::CallOrConstruct(
nsIXPConnectWrappedNative* wrapper, JSContext* cx, HandleObject obj, const CallArgs& args, bool* _retval) { // make sure we have at least one arg
if (args.length() < 1) { return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
}
// Fetch the property name ids, so we can look them up.
XPCJSRuntime* runtime = XPCJSRuntime::Get();
HandleId classIDProp = runtime->GetStringID(XPCJSContext::IDX_CLASS_ID);
HandleId interfaceIDProp =
runtime->GetStringID(XPCJSContext::IDX_INTERFACE_ID);
HandleId initializerProp =
runtime->GetStringID(XPCJSContext::IDX_INITIALIZER);
if (!ifaceName) { return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
}
// a new scope to avoid warnings about shadowed names
{
nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
RootedObject ifacesObj(cx);
// we do the lookup by asking the Components.interfaces object // for the property with this name - i.e. we let its caching of these // nsIJSIID objects work for us.
// a new scope to avoid warnings about shadowed names
{ // argv[0] is a contractid name string
// we do the lookup by asking the Components.classes object // for the property with this name - i.e. we let its caching of these // nsIJSCID objects work for us.
class nsXPCComponents_Utils final : public nsIXPCComponents_Utils, public nsIXPCScriptable { public: // all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSIXPCCOMPONENTS_UTILS
// The nsIXPCScriptable map declaration that will generate stubs for us... #define XPC_MAP_CLASSNAME nsXPCComponents_Utils #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Utils" #define XPC_MAP_FLAGS XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE #include"xpc_map_end.h"/* This will #undef the above */
NS_IMETHODIMP
nsXPCComponents_Utils::ReportError(HandleValue error, HandleValue stack,
JSContext* cx) { // This function shall never fail! Silently eat any failure conditions.
nsCOMPtr<nsIConsoleService> console(
do_GetService(NS_CONSOLESERVICE_CONTRACTID)); if (!console) { return NS_OK;
}
Rooted<Maybe<Value>> exception(cx, Some(error)); if (!innerWindowID) { // Leak mitigation: nsConsoleService::ClearMessagesForWindowID needs // a WindowID for cleanup and exception values could hold arbitrary // objects alive.
exception = Nothing();
}
if (!scripterr) {
RootedObject stackObj(cx);
RootedObject stackGlobal(cx); if (stack.isObject()) { if (!JS::IsMaybeWrappedSavedFrame(&stack.toObject())) { return NS_ERROR_INVALID_ARG;
}
// |stack| might be a wrapper, but it must be same-compartment with // the current global.
stackObj = &stack.toObject();
stackGlobal = JS::CurrentGlobalOrNull(cx);
js::AssertSameCompartment(stackObj, stackGlobal);
RootedObject sandbox(cx, &sandboxVal.toObject()); // We only care about sandboxes here, so CheckedUnwrapStatic is fine.
sandbox = js::CheckedUnwrapStatic(sandbox); if (!sandbox || !xpc::IsSandbox(sandbox)) { return NS_ERROR_INVALID_ARG;
}
RootedObject sandbox(cx, &sandboxVal.toObject()); // We only care about sandboxes here, so CheckedUnwrapStatic is fine.
sandbox = js::CheckedUnwrapStatic(sandbox); if (!sandbox || !xpc::IsSandbox(sandbox)) { return NS_ERROR_INVALID_ARG;
}
NS_IMETHODIMP
nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
JSContext* cx) { // Ensure we're working in the scripted caller's realm. This is not guaranteed // to be the current realm because we switch realms when calling cross-realm // functions.
RootedObject global(cx, JS::GetScriptedCallerGlobal(cx));
MOZ_ASSERT(global);
js::AssertSameCompartment(cx, global);
JSAutoRealm ar(cx, global);
// Don't allow doing this if the global is a Window.
nsGlobalWindowInner* win; if (NS_SUCCEEDED(UNWRAP_NON_WRAPPER_OBJECT(Window, global, win))) { return NS_ERROR_NOT_AVAILABLE;
}
if (!JS_CallFunctionValue(cx, nullptr, function,
JS::HandleValueArray::empty(), retval)) { return NS_ERROR_XPC_JAVASCRIPT_ERROR;
}
return NS_OK;
}
NS_IMETHODIMP
nsXPCComponents_Utils::GetGlobalForObject(HandleValue object, JSContext* cx,
MutableHandleValue retval) { // First argument must be an object. if (object.isPrimitive()) { return NS_ERROR_XPC_BAD_CONVERT_JS;
}
// When getting the global for a cross-compartment wrapper, we really want // a wrapper for the foreign global. So we need to unwrap before getting the // global and then wrap the result.
Rooted<JSObject*> obj(cx, &object.toObject());
obj = JS::GetNonCCWObjectGlobal(js::UncheckedUnwrap(obj));
if (!JS_WrapObject(cx, &obj)) { return NS_ERROR_FAILURE;
}
// Get the WindowProxy if necessary.
obj = js::ToWindowProxyIfWindow(obj);
RootedObject obj(cx, &vobj.toObject()); // We need to do a dynamic unwrap, because we apparently want to treat // "failure to unwrap" differently from "not a proxy" (throw for the former, // return false for the latter).
obj = js::CheckedUnwrapDynamic(obj, cx, /* stopAtWindowProxy = */ false);
NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
// We should never have cross-compartment wrappers for dead wrappers.
MOZ_ASSERT_IF(js::IsCrossCompartmentWrapper(&obj.toObject()),
!JS_IsDeadWrapper(js::UncheckedUnwrap(&obj.toObject())));
NS_IMETHODIMP
nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext* cx) { // Determine the compartment of the given object, if any.
JS::Compartment* c =
vobj.isObject()
? JS::GetCompartment(js::UncheckedUnwrap(&vobj.toObject()))
: nullptr;
// If no compartment was given, recompute all. if (!c) {
js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments()); // Otherwise, recompute wrappers for the given compartment.
} else {
js::RecomputeWrappers(cx, js::SingleCompartment(c),
js::AllCompartments()) &&
js::RecomputeWrappers(cx, js::AllCompartments(),
js::SingleCompartment(c));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.