michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim: set ts=8 sts=4 et sw=4 tw=99: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* The "Components" xpcom objects for JavaScript. */ michael@0: michael@0: #include "xpcprivate.h" michael@0: #include "xpcIJSModuleLoader.h" michael@0: #include "XPCJSWeakReference.h" michael@0: #include "WrapperFactory.h" michael@0: #include "nsJSUtils.h" michael@0: #include "mozJSComponentLoader.h" michael@0: #include "nsContentUtils.h" michael@0: #include "jsfriendapi.h" michael@0: #include "js/StructuredClone.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsJSEnvironment.h" michael@0: #include "mozilla/XPTInterfaceInfoManager.h" michael@0: #include "mozilla/dom/DOMException.h" michael@0: #include "mozilla/dom/DOMExceptionBinding.h" michael@0: #include "mozilla/dom/BindingUtils.h" michael@0: #include "mozilla/dom/StructuredCloneTags.h" michael@0: #include "nsZipArchive.h" michael@0: #include "nsIDOMFile.h" michael@0: #include "nsIDOMFileList.h" michael@0: #include "nsWindowMemoryReporter.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace JS; michael@0: using namespace js; michael@0: using namespace xpc; michael@0: using mozilla::dom::Exception; michael@0: michael@0: /***************************************************************************/ michael@0: // stuff used by all michael@0: michael@0: nsresult michael@0: xpc::ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval) michael@0: { michael@0: XPCThrower::Throw(errNum, cx); michael@0: *retval = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: static bool michael@0: JSValIsInterfaceOfType(JSContext *cx, HandleValue v, REFNSIID iid) michael@0: { michael@0: michael@0: nsCOMPtr wn; michael@0: nsCOMPtr sup; michael@0: nsISupports* iface; michael@0: michael@0: if (v.isPrimitive()) michael@0: return false; michael@0: michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: RootedObject obj(cx, &v.toObject()); michael@0: if (NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) && wn && michael@0: NS_SUCCEEDED(wn->Native()->QueryInterface(iid, (void**)&iface)) && iface) michael@0: { michael@0: NS_RELEASE(iface); michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: char * michael@0: xpc::CloneAllAccess() michael@0: { michael@0: static const char allAccess[] = "AllAccess"; michael@0: return (char*)nsMemory::Clone(allAccess, sizeof(allAccess)); michael@0: } michael@0: michael@0: char * michael@0: xpc::CheckAccessList(const char16_t *wideName, const char *const list[]) michael@0: { michael@0: nsAutoCString asciiName; michael@0: CopyUTF16toUTF8(nsDependentString(wideName), asciiName); michael@0: michael@0: for (const char* const* p = list; *p; p++) michael@0: if (!strcmp(*p, asciiName.get())) michael@0: return CloneAllAccess(); michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: michael@0: michael@0: class nsXPCComponents_Interfaces : michael@0: public nsIXPCComponents_Interfaces, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_INTERFACES michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: public: michael@0: nsXPCComponents_Interfaces(); michael@0: virtual ~nsXPCComponents_Interfaces(); michael@0: michael@0: private: michael@0: nsCOMArray mInterfaces; michael@0: }; michael@0: michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_Interfaces) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_Interfaces"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetFlags(uint32_t *aFlags) michael@0: { michael@0: // Mark ourselves as a DOM object so that instances may be created in michael@0: // unprivileged scopes. michael@0: *aFlags = nsIClassInfo::DOM_OBJECT; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_Interfaces::nsXPCComponents_Interfaces() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Interfaces) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Interfaces) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_Interfaces) michael@0: NS_IMPL_RELEASE(nsXPCComponents_Interfaces) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_Interfaces michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Interfaces" michael@0: #define XPC_MAP_WANT_NEWRESOLVE michael@0: #define XPC_MAP_WANT_NEWENUMERATE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\ michael@0: nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: michael@0: /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * obj, michael@0: uint32_t enum_op, jsval * statep, michael@0: jsid * idp, bool *_retval) michael@0: { michael@0: switch (enum_op) { michael@0: case JSENUMERATE_INIT: michael@0: case JSENUMERATE_INIT_ALL: michael@0: { michael@0: // Lazily init the list of interfaces when someone tries to michael@0: // enumerate them. michael@0: if (mInterfaces.IsEmpty()) { michael@0: XPTInterfaceInfoManager::GetSingleton()-> michael@0: GetScriptableInterfaces(mInterfaces); michael@0: } michael@0: michael@0: *statep = JSVAL_ZERO; michael@0: if (idp) michael@0: *idp = INT_TO_JSID(mInterfaces.Length()); michael@0: return NS_OK; michael@0: } michael@0: case JSENUMERATE_NEXT: michael@0: { michael@0: uint32_t idx = JSVAL_TO_INT(*statep); michael@0: nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx); michael@0: *statep = UINT_TO_JSVAL(idx + 1); michael@0: michael@0: if (interface) { michael@0: const char* name; michael@0: michael@0: RootedId id(cx); michael@0: if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) { michael@0: RootedString idstr(cx, JS_NewStringCopyZ(cx, name)); michael@0: if (idstr && JS_StringToId(cx, idstr, &id)) { michael@0: *idp = id; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: } michael@0: // fall through michael@0: } michael@0: michael@0: case JSENUMERATE_DESTROY: michael@0: default: michael@0: *statep = JSVAL_NULL; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, JSObject *objArg, michael@0: jsid idArg, JSObject **objp, michael@0: bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: RootedId id(cx, idArg); michael@0: michael@0: if (!JSID_IS_STRING(id)) michael@0: return NS_OK; michael@0: michael@0: JSAutoByteString name; michael@0: RootedString str(cx, JSID_TO_STRING(id)); michael@0: michael@0: // we only allow interfaces by name here michael@0: if (name.encodeLatin1(cx, str) && name.ptr()[0] != '{') { michael@0: nsCOMPtr info; michael@0: XPTInterfaceInfoManager::GetSingleton()-> michael@0: GetInfoForName(name.ptr(), getter_AddRefs(info)); michael@0: if (!info) michael@0: return NS_OK; michael@0: michael@0: nsCOMPtr nsid = nsJSIID::NewID(info); michael@0: michael@0: if (nsid) { michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: nsCOMPtr holder; michael@0: if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, michael@0: static_cast(nsid), michael@0: NS_GET_IID(nsIJSIID), michael@0: getter_AddRefs(holder)))) { michael@0: RootedObject idobj(cx); michael@0: if (holder && michael@0: // Assign, not compare michael@0: (idobj = holder->GetJSObject())) { michael@0: *objp = obj; michael@0: *_retval = JS_DefinePropertyById(cx, obj, id, michael@0: OBJECT_TO_JSVAL(idobj), michael@0: nullptr, nullptr, michael@0: JSPROP_ENUMERATE | michael@0: JSPROP_READONLY | michael@0: JSPROP_PERMANENT); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: michael@0: class nsXPCComponents_InterfacesByID : michael@0: public nsIXPCComponents_InterfacesByID, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: public: michael@0: nsXPCComponents_InterfacesByID(); michael@0: virtual ~nsXPCComponents_InterfacesByID(); michael@0: michael@0: private: michael@0: nsCOMArray mInterfaces; michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_InterfacesByID) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_InterfacesByID"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetFlags(uint32_t *aFlags) michael@0: { michael@0: // Mark ourselves as a DOM object so that instances may be created in michael@0: // unprivileged scopes. michael@0: *aFlags = nsIClassInfo::DOM_OBJECT; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_InterfacesByID::nsXPCComponents_InterfacesByID() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_InterfacesByID::~nsXPCComponents_InterfacesByID() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_InterfacesByID) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_InterfacesByID) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_InterfacesByID) michael@0: NS_IMPL_RELEASE(nsXPCComponents_InterfacesByID) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_InterfacesByID michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_InterfacesByID" michael@0: #define XPC_MAP_WANT_NEWRESOLVE michael@0: #define XPC_MAP_WANT_NEWENUMERATE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\ michael@0: nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * obj, michael@0: uint32_t enum_op, jsval * statep, michael@0: jsid * idp, bool *_retval) michael@0: { michael@0: switch (enum_op) { michael@0: case JSENUMERATE_INIT: michael@0: case JSENUMERATE_INIT_ALL: michael@0: { michael@0: // Lazily init the list of interfaces when someone tries to michael@0: // enumerate them. michael@0: if (mInterfaces.IsEmpty()) { michael@0: XPTInterfaceInfoManager::GetSingleton()-> michael@0: GetScriptableInterfaces(mInterfaces); michael@0: } michael@0: michael@0: *statep = JSVAL_ZERO; michael@0: if (idp) michael@0: *idp = INT_TO_JSID(mInterfaces.Length()); michael@0: return NS_OK; michael@0: } michael@0: case JSENUMERATE_NEXT: michael@0: { michael@0: uint32_t idx = JSVAL_TO_INT(*statep); michael@0: nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx); michael@0: *statep = UINT_TO_JSVAL(idx + 1); michael@0: if (interface) { michael@0: nsIID const *iid; michael@0: char idstr[NSID_LENGTH]; michael@0: michael@0: if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) { michael@0: iid->ToProvidedString(idstr); michael@0: RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr)); michael@0: RootedId id(cx); michael@0: if (jsstr && JS_StringToId(cx, jsstr, &id)) { michael@0: *idp = id; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: } michael@0: // FALL THROUGH michael@0: } michael@0: michael@0: case JSENUMERATE_DESTROY: michael@0: default: michael@0: *statep = JSVAL_NULL; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_InterfacesByID::NewResolve(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, JSObject *objArg, michael@0: jsid idArg, JSObject **objp, michael@0: bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: RootedId id(cx, idArg); michael@0: michael@0: if (!JSID_IS_STRING(id)) michael@0: return NS_OK; michael@0: michael@0: RootedString str(cx, JSID_TO_STRING(id)); michael@0: if (38 != JS_GetStringLength(str)) michael@0: return NS_OK; michael@0: michael@0: if (const jschar *name = JS_GetInternedStringChars(str)) { michael@0: nsID iid; michael@0: if (!iid.Parse(NS_ConvertUTF16toUTF8(name).get())) michael@0: return NS_OK; michael@0: michael@0: nsCOMPtr info; michael@0: XPTInterfaceInfoManager::GetSingleton()-> michael@0: GetInfoForIID(&iid, getter_AddRefs(info)); michael@0: if (!info) michael@0: return NS_OK; michael@0: michael@0: nsCOMPtr nsid = nsJSIID::NewID(info); michael@0: michael@0: if (!nsid) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: nsCOMPtr holder; michael@0: if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, michael@0: static_cast(nsid), michael@0: NS_GET_IID(nsIJSIID), michael@0: getter_AddRefs(holder)))) { michael@0: RootedObject idobj(cx); michael@0: if (holder && michael@0: // Assign, not compare michael@0: (idobj = holder->GetJSObject())) { michael@0: *objp = obj; michael@0: *_retval = michael@0: JS_DefinePropertyById(cx, obj, id, michael@0: OBJECT_TO_JSVAL(idobj), michael@0: nullptr, nullptr, michael@0: JSPROP_ENUMERATE | michael@0: JSPROP_READONLY | michael@0: JSPROP_PERMANENT); michael@0: } michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: michael@0: michael@0: michael@0: class nsXPCComponents_Classes : michael@0: public nsIXPCComponents_Classes, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_CLASSES michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: public: michael@0: nsXPCComponents_Classes(); michael@0: virtual ~nsXPCComponents_Classes(); michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_Classes) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_Classes"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetFlags(uint32_t *aFlags) michael@0: { michael@0: *aFlags = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_Classes::nsXPCComponents_Classes() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_Classes::~nsXPCComponents_Classes() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Classes) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Classes) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Classes) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_Classes) michael@0: NS_IMPL_RELEASE(nsXPCComponents_Classes) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_Classes michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Classes" michael@0: #define XPC_MAP_WANT_NEWRESOLVE michael@0: #define XPC_MAP_WANT_NEWENUMERATE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\ michael@0: nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: michael@0: /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * obj, michael@0: uint32_t enum_op, jsval * statep, michael@0: jsid * idp, bool *_retval) michael@0: { michael@0: nsISimpleEnumerator* e; michael@0: michael@0: switch (enum_op) { michael@0: case JSENUMERATE_INIT: michael@0: case JSENUMERATE_INIT_ALL: michael@0: { michael@0: nsCOMPtr compMgr; michael@0: if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr || michael@0: NS_FAILED(compMgr->EnumerateContractIDs(&e)) || !e ) { michael@0: *statep = JSVAL_NULL; michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: *statep = PRIVATE_TO_JSVAL(e); michael@0: if (idp) michael@0: *idp = INT_TO_JSID(0); // indicate that we don't know the count michael@0: return NS_OK; michael@0: } michael@0: case JSENUMERATE_NEXT: michael@0: { michael@0: nsCOMPtr isup; michael@0: bool hasMore; michael@0: e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep); michael@0: michael@0: if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore && michael@0: NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) { michael@0: nsCOMPtr holder(do_QueryInterface(isup)); michael@0: if (holder) { michael@0: nsAutoCString name; michael@0: if (NS_SUCCEEDED(holder->GetData(name))) { michael@0: RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length())); michael@0: RootedId id(cx); michael@0: if (idstr && JS_StringToId(cx, idstr, &id)) { michael@0: *idp = id; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: // else... FALL THROUGH michael@0: } michael@0: michael@0: case JSENUMERATE_DESTROY: michael@0: default: michael@0: e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep); michael@0: NS_IF_RELEASE(e); michael@0: *statep = JSVAL_NULL; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Classes::NewResolve(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, JSObject *objArg, michael@0: jsid idArg, JSObject **objp, michael@0: bool *_retval) michael@0: michael@0: { michael@0: RootedId id(cx, idArg); michael@0: RootedObject obj(cx, objArg); michael@0: michael@0: JSAutoByteString name; michael@0: if (JSID_IS_STRING(id) && michael@0: name.encodeLatin1(cx, JSID_TO_STRING(id)) && michael@0: name.ptr()[0] != '{') { // we only allow contractids here michael@0: nsCOMPtr nsid = nsJSCID::NewID(name.ptr()); michael@0: if (nsid) { michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: nsCOMPtr holder; michael@0: if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, michael@0: static_cast(nsid), michael@0: NS_GET_IID(nsIJSCID), michael@0: getter_AddRefs(holder)))) { michael@0: RootedObject idobj(cx); michael@0: if (holder && michael@0: // Assign, not compare michael@0: (idobj = holder->GetJSObject())) { michael@0: *objp = obj; michael@0: *_retval = JS_DefinePropertyById(cx, obj, id, michael@0: OBJECT_TO_JSVAL(idobj), michael@0: nullptr, nullptr, michael@0: JSPROP_ENUMERATE | michael@0: JSPROP_READONLY | michael@0: JSPROP_PERMANENT); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: michael@0: class nsXPCComponents_ClassesByID : michael@0: public nsIXPCComponents_ClassesByID, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: public: michael@0: nsXPCComponents_ClassesByID(); michael@0: virtual ~nsXPCComponents_ClassesByID(); michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_ClassesByID) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_ClassesByID"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetFlags(uint32_t *aFlags) michael@0: { michael@0: *aFlags = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_ClassesByID::nsXPCComponents_ClassesByID() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_ClassesByID::~nsXPCComponents_ClassesByID() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ClassesByID) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ClassesByID) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ClassesByID) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_ClassesByID) michael@0: NS_IMPL_RELEASE(nsXPCComponents_ClassesByID) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_ClassesByID michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ClassesByID" michael@0: #define XPC_MAP_WANT_NEWRESOLVE michael@0: #define XPC_MAP_WANT_NEWENUMERATE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\ michael@0: nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * obj, michael@0: uint32_t enum_op, jsval * statep, michael@0: jsid * idp, bool *_retval) michael@0: { michael@0: nsISimpleEnumerator* e; michael@0: michael@0: switch (enum_op) { michael@0: case JSENUMERATE_INIT: michael@0: case JSENUMERATE_INIT_ALL: michael@0: { michael@0: nsCOMPtr compMgr; michael@0: if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr || michael@0: NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e ) { michael@0: *statep = JSVAL_NULL; michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: *statep = PRIVATE_TO_JSVAL(e); michael@0: if (idp) michael@0: *idp = INT_TO_JSID(0); // indicate that we don't know the count michael@0: return NS_OK; michael@0: } michael@0: case JSENUMERATE_NEXT: michael@0: { michael@0: nsCOMPtr isup; michael@0: bool hasMore; michael@0: e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep); michael@0: michael@0: if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore && michael@0: NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) { michael@0: nsCOMPtr holder(do_QueryInterface(isup)); michael@0: if (holder) { michael@0: char* name; michael@0: if (NS_SUCCEEDED(holder->ToString(&name)) && name) { michael@0: RootedString idstr(cx, JS_NewStringCopyZ(cx, name)); michael@0: nsMemory::Free(name); michael@0: RootedId id(cx); michael@0: if (idstr && JS_StringToId(cx, idstr, &id)) { michael@0: *idp = id; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: // else... FALL THROUGH michael@0: } michael@0: michael@0: case JSENUMERATE_DESTROY: michael@0: default: michael@0: e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep); michael@0: NS_IF_RELEASE(e); michael@0: *statep = JSVAL_NULL; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: static bool michael@0: IsRegisteredCLSID(const char* str) michael@0: { michael@0: bool registered; michael@0: nsID id; michael@0: michael@0: if (!id.Parse(str)) michael@0: return false; michael@0: michael@0: nsCOMPtr compMgr; michael@0: if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr || michael@0: NS_FAILED(compMgr->IsCIDRegistered(id, ®istered))) michael@0: return false; michael@0: michael@0: return registered; michael@0: } michael@0: michael@0: /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ClassesByID::NewResolve(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, JSObject *objArg, michael@0: jsid idArg, JSObject **objp, michael@0: bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: RootedId id(cx, idArg); michael@0: michael@0: if (!JSID_IS_STRING(id)) michael@0: return NS_OK; michael@0: michael@0: JSAutoByteString name; michael@0: RootedString str(cx, JSID_TO_STRING(id)); michael@0: if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' && michael@0: IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here michael@0: { michael@0: nsCOMPtr nsid = nsJSCID::NewID(name.ptr()); michael@0: if (nsid) { michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: nsCOMPtr holder; michael@0: if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, michael@0: static_cast(nsid), michael@0: NS_GET_IID(nsIJSCID), michael@0: getter_AddRefs(holder)))) { michael@0: RootedObject idobj(cx); michael@0: if (holder && michael@0: // Assign, not compare michael@0: (idobj = holder->GetJSObject())) { michael@0: *objp = obj; michael@0: *_retval = JS_DefinePropertyById(cx, obj, id, michael@0: ObjectValue(*idobj), michael@0: nullptr, nullptr, michael@0: JSPROP_ENUMERATE | michael@0: JSPROP_READONLY | michael@0: JSPROP_PERMANENT); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: // Currently the possible results do not change at runtime, so they are only michael@0: // cached once (unlike ContractIDs, CLSIDs, and IIDs) michael@0: michael@0: class nsXPCComponents_Results : michael@0: public nsIXPCComponents_Results, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_RESULTS michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: public: michael@0: nsXPCComponents_Results(); michael@0: virtual ~nsXPCComponents_Results(); michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_Results) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_Results"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetFlags(uint32_t *aFlags) michael@0: { michael@0: // Mark ourselves as a DOM object so that instances may be created in michael@0: // unprivileged scopes. michael@0: *aFlags = nsIClassInfo::DOM_OBJECT; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_Results::nsXPCComponents_Results() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_Results::~nsXPCComponents_Results() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Results) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Results) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Results) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_Results) michael@0: NS_IMPL_RELEASE(nsXPCComponents_Results) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_Results michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Results" michael@0: #define XPC_MAP_WANT_NEWRESOLVE michael@0: #define XPC_MAP_WANT_NEWENUMERATE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\ michael@0: nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * obj, michael@0: uint32_t enum_op, jsval * statep, michael@0: jsid * idp, bool *_retval) michael@0: { michael@0: const void** iter; michael@0: michael@0: switch (enum_op) { michael@0: case JSENUMERATE_INIT: michael@0: case JSENUMERATE_INIT_ALL: michael@0: { michael@0: if (idp) michael@0: *idp = INT_TO_JSID(nsXPCException::GetNSResultCount()); michael@0: michael@0: void** space = (void**) new char[sizeof(void*)]; michael@0: *space = nullptr; michael@0: *statep = PRIVATE_TO_JSVAL(space); michael@0: return NS_OK; michael@0: } michael@0: case JSENUMERATE_NEXT: michael@0: { michael@0: const char* name; michael@0: iter = (const void**) JSVAL_TO_PRIVATE(*statep); michael@0: if (nsXPCException::IterateNSResults(nullptr, &name, nullptr, iter)) { michael@0: RootedString idstr(cx, JS_NewStringCopyZ(cx, name)); michael@0: JS::RootedId id(cx); michael@0: if (idstr && JS_StringToId(cx, idstr, &id)) { michael@0: *idp = id; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: // else... FALL THROUGH michael@0: } michael@0: michael@0: case JSENUMERATE_DESTROY: michael@0: default: michael@0: iter = (const void**) JSVAL_TO_PRIVATE(*statep); michael@0: delete [] (char*) iter; michael@0: *statep = JSVAL_NULL; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: michael@0: /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, JSObject *objArg, michael@0: jsid idArg, JSObject * *objp, michael@0: bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: RootedId id(cx, idArg); michael@0: JSAutoByteString name; michael@0: michael@0: if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) { michael@0: const char* rv_name; michael@0: const void* iter = nullptr; michael@0: nsresult rv; michael@0: while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) { michael@0: if (!strcmp(name.ptr(), rv_name)) { michael@0: jsval val = JS_NumberValue((double)rv); michael@0: michael@0: *objp = obj; michael@0: if (!JS_DefinePropertyById(cx, obj, id, val, michael@0: nullptr, nullptr, michael@0: JSPROP_ENUMERATE | michael@0: JSPROP_READONLY | michael@0: JSPROP_PERMANENT)) { michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // JavaScript Constructor for nsIJSID objects (Components.ID) michael@0: michael@0: class nsXPCComponents_ID : michael@0: public nsIXPCComponents_ID, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_ID michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: michael@0: public: michael@0: nsXPCComponents_ID(); michael@0: virtual ~nsXPCComponents_ID(); michael@0: michael@0: private: michael@0: static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, HandleObject obj, michael@0: const CallArgs &args, bool *_retval); michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_ID) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_ID"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetFlags(uint32_t *aFlags) michael@0: { michael@0: *aFlags = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_ID::nsXPCComponents_ID() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_ID::~nsXPCComponents_ID() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ID) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ID) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ID) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_ID) michael@0: NS_IMPL_RELEASE(nsXPCComponents_ID) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_ID michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ID" michael@0: #define XPC_MAP_WANT_CALL michael@0: #define XPC_MAP_WANT_CONSTRUCT michael@0: #define XPC_MAP_WANT_HASINSTANCE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: michael@0: /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: } michael@0: michael@0: /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: } michael@0: michael@0: // static michael@0: nsresult michael@0: nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, HandleObject obj, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: // make sure we have at least one arg michael@0: michael@0: if (args.length() < 1) michael@0: return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval); michael@0: michael@0: // Do the security check if necessary michael@0: michael@0: nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager(); michael@0: if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsJSID::GetCID()))) { michael@0: // the security manager vetoed. It should have set an exception. michael@0: *_retval = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // convert the first argument into a string and see if it looks like an id michael@0: michael@0: JSString* jsstr; michael@0: JSAutoByteString bytes; michael@0: nsID id; michael@0: michael@0: if (!(jsstr = ToString(cx, args[0])) || michael@0: !bytes.encodeLatin1(cx, jsstr) || michael@0: !id.Parse(bytes.ptr())) { michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval); michael@0: } michael@0: michael@0: // make the new object and return it. michael@0: michael@0: JSObject* newobj = xpc_NewIDObject(cx, obj, id); michael@0: if (!newobj) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: args.rval().setObject(*newobj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, JSObject *obj, michael@0: HandleValue val, bool *bp, bool *_retval) michael@0: { michael@0: if (bp) michael@0: *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIJSID)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // JavaScript Constructor for nsIXPCException objects (Components.Exception) michael@0: michael@0: class nsXPCComponents_Exception : michael@0: public nsIXPCComponents_Exception, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_EXCEPTION michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: michael@0: public: michael@0: nsXPCComponents_Exception(); michael@0: virtual ~nsXPCComponents_Exception(); michael@0: michael@0: private: michael@0: static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, HandleObject obj, michael@0: const CallArgs &args, bool *_retval); michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_Exception) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_Exception"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetFlags(uint32_t *aFlags) michael@0: { michael@0: *aFlags = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_Exception::nsXPCComponents_Exception() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_Exception::~nsXPCComponents_Exception() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Exception) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Exception) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Exception) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_Exception) michael@0: NS_IMPL_RELEASE(nsXPCComponents_Exception) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_Exception michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Exception" michael@0: #define XPC_MAP_WANT_CALL michael@0: #define XPC_MAP_WANT_CONSTRUCT michael@0: #define XPC_MAP_WANT_HASINSTANCE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: michael@0: /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: } michael@0: michael@0: /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, michael@0: JSObject *objArg, const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: } michael@0: michael@0: struct MOZ_STACK_CLASS ExceptionArgParser michael@0: { michael@0: ExceptionArgParser(JSContext *context, michael@0: nsXPConnect *xpconnect) michael@0: : eMsg("exception") michael@0: , eResult(NS_ERROR_FAILURE) michael@0: , cx(context) michael@0: , xpc(xpconnect) michael@0: {} michael@0: michael@0: // Public exception parameter values. During construction, these are michael@0: // initialized to the appropriate defaults. michael@0: const char* eMsg; michael@0: nsresult eResult; michael@0: nsCOMPtr eStack; michael@0: nsCOMPtr eData; michael@0: michael@0: // Parse the constructor arguments into the above |eFoo| parameter values. michael@0: bool parse(const CallArgs &args) { michael@0: /* michael@0: * The Components.Exception takes a series of arguments, all of them michael@0: * optional: michael@0: * michael@0: * Argument 0: Exception message (defaults to 'exception'). michael@0: * Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options michael@0: * object (see below). michael@0: * Argument 2: Stack (defaults to the current stack, which we trigger michael@0: * by leaving this nullptr in the parser). michael@0: * Argument 3: Optional user data (defaults to nullptr). michael@0: * michael@0: * To dig our way out of this clunky API, we now support passing an michael@0: * options object as the second parameter (as opposed to a result code). michael@0: * If this is the case, all subsequent arguments are ignored, and the michael@0: * following properties are parsed out of the object (using the michael@0: * associated default if the property does not exist): michael@0: * michael@0: * result: Result code (see argument 1). michael@0: * stack: Call stack (see argument 2). michael@0: * data: User data (see argument 3). michael@0: */ michael@0: if (args.length() > 0 && !parseMessage(args[0])) michael@0: return false; michael@0: if (args.length() > 1) { michael@0: if (args[1].isObject()) { michael@0: RootedObject obj(cx, &args[1].toObject()); michael@0: return parseOptionsObject(obj); michael@0: } michael@0: if (!parseResult(args[1])) michael@0: return false; michael@0: } michael@0: if (args.length() > 2) { michael@0: if (!parseStack(args[2])) michael@0: return false; michael@0: } michael@0: if (args.length() > 3) { michael@0: if (!parseData(args[3])) michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: protected: michael@0: michael@0: /* michael@0: * Parsing helpers. michael@0: */ michael@0: michael@0: bool parseMessage(HandleValue v) { michael@0: JSString *str = ToString(cx, v); michael@0: if (!str) michael@0: return false; michael@0: eMsg = messageBytes.encodeLatin1(cx, str); michael@0: return !!eMsg; michael@0: } michael@0: michael@0: bool parseResult(HandleValue v) { michael@0: return JS::ToUint32(cx, v, (uint32_t*) &eResult); michael@0: } michael@0: michael@0: bool parseStack(HandleValue v) { michael@0: if (!v.isObject()) { michael@0: // eStack has already been initialized to null, which is what we want michael@0: // for any non-object values (including null). michael@0: return true; michael@0: } michael@0: michael@0: return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(), michael@0: NS_GET_IID(nsIStackFrame), michael@0: getter_AddRefs(eStack))); michael@0: } michael@0: michael@0: bool parseData(HandleValue v) { michael@0: if (!v.isObject()) { michael@0: // eData has already been initialized to null, which is what we want michael@0: // for any non-object values (including null). michael@0: return true; michael@0: } michael@0: michael@0: return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(), michael@0: NS_GET_IID(nsISupports), michael@0: getter_AddRefs(eData))); michael@0: } michael@0: michael@0: bool parseOptionsObject(HandleObject obj) { michael@0: RootedValue v(cx); michael@0: michael@0: if (!getOption(obj, "result", &v) || michael@0: (!v.isUndefined() && !parseResult(v))) michael@0: return false; michael@0: michael@0: if (!getOption(obj, "stack", &v) || michael@0: (!v.isUndefined() && !parseStack(v))) michael@0: return false; michael@0: michael@0: if (!getOption(obj, "data", &v) || michael@0: (!v.isUndefined() && !parseData(v))) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool getOption(HandleObject obj, const char *name, MutableHandleValue rv) { michael@0: // Look for the property. michael@0: bool found; michael@0: if (!JS_HasProperty(cx, obj, name, &found)) michael@0: return false; michael@0: michael@0: // If it wasn't found, indicate with undefined. michael@0: if (!found) { michael@0: rv.setUndefined(); michael@0: return true; michael@0: } michael@0: michael@0: // Get the property. michael@0: return JS_GetProperty(cx, obj, name, rv); michael@0: } michael@0: michael@0: /* michael@0: * Internal data members. michael@0: */ michael@0: michael@0: // If there's a non-default exception string, hold onto the allocated bytes. michael@0: JSAutoByteString messageBytes; michael@0: michael@0: // Various bits and pieces that are helpful to have around. michael@0: JSContext *cx; michael@0: nsXPConnect *xpc; michael@0: }; michael@0: michael@0: // static michael@0: nsresult michael@0: nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, HandleObject obj, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: michael@0: // Do the security check if necessary michael@0: michael@0: nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager(); michael@0: if (sm && NS_FAILED(sm->CanCreateInstance(cx, Exception::GetCID()))) { michael@0: // the security manager vetoed. It should have set an exception. michael@0: *_retval = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Parse the arguments to the Exception constructor. michael@0: ExceptionArgParser parser(cx, xpc); michael@0: if (!parser.parse(args)) michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval); michael@0: michael@0: nsCOMPtr e = new Exception(nsCString(parser.eMsg), michael@0: parser.eResult, michael@0: EmptyCString(), michael@0: parser.eStack, michael@0: parser.eData); michael@0: michael@0: nsCOMPtr holder; michael@0: RootedObject newObj(cx); michael@0: michael@0: if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException), michael@0: getter_AddRefs(holder))) || !holder || michael@0: // Assign, not compare michael@0: !(newObj = holder->GetJSObject())) { michael@0: return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval); michael@0: } michael@0: michael@0: args.rval().setObject(*newObj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * obj, michael@0: HandleValue val, bool *bp, michael@0: bool *_retval) michael@0: { michael@0: using namespace mozilla::dom; michael@0: michael@0: RootedValue v(cx, val); michael@0: if (bp) { michael@0: Exception* e; michael@0: *bp = NS_SUCCEEDED(UNWRAP_OBJECT(Exception, v.toObjectOrNull(), e)) || michael@0: JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException)); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // This class is for the thing returned by "new Component.Constructor". michael@0: michael@0: // XXXjband we use this CID for security check, but security system can't see michael@0: // it since it has no registed factory. Security really kicks in when we try michael@0: // to build a wrapper around an instance. michael@0: michael@0: // {B4A95150-E25A-11d3-8F61-0010A4E73D9A} michael@0: #define NS_XPCCONSTRUCTOR_CID \ michael@0: { 0xb4a95150, 0xe25a, 0x11d3, \ michael@0: { 0x8f, 0x61, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } } michael@0: michael@0: class nsXPCConstructor : michael@0: public nsIXPCConstructor, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID) michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCONSTRUCTOR michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: public: michael@0: nsXPCConstructor(); // not implemented michael@0: nsXPCConstructor(nsIJSCID* aClassID, michael@0: nsIJSIID* aInterfaceID, michael@0: const char* aInitializer); michael@0: virtual ~nsXPCConstructor(); michael@0: michael@0: private: michael@0: nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, HandleObject obj, michael@0: const CallArgs &args, bool *_retval); michael@0: private: michael@0: nsRefPtr mClassID; michael@0: nsRefPtr mInterfaceID; michael@0: char* mInitializer; michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCConstructor) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCConstructor"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetFlags(uint32_t *aFlags) michael@0: { michael@0: *aFlags = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCConstructor::nsXPCConstructor(nsIJSCID* aClassID, michael@0: nsIJSIID* aInterfaceID, michael@0: const char* aInitializer) michael@0: : mClassID(aClassID), michael@0: mInterfaceID(aInterfaceID) michael@0: { michael@0: mInitializer = aInitializer ? michael@0: (char*) nsMemory::Clone(aInitializer, strlen(aInitializer)+1) : michael@0: nullptr; michael@0: } michael@0: michael@0: nsXPCConstructor::~nsXPCConstructor() michael@0: { michael@0: if (mInitializer) michael@0: nsMemory::Free(mInitializer); michael@0: } michael@0: michael@0: /* readonly attribute nsIJSCID classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetClassID(nsIJSCID * *aClassID) michael@0: { michael@0: nsRefPtr rval = mClassID; michael@0: rval.forget(aClassID); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsIJSIID interfaceID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetInterfaceID(nsIJSIID * *aInterfaceID) michael@0: { michael@0: nsRefPtr rval = mInterfaceID; michael@0: rval.forget(aInterfaceID); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string initializer; */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::GetInitializer(char * *aInitializer) michael@0: { michael@0: XPC_STRING_GETTER_BODY(aInitializer, mInitializer); michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCConstructor) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCConstructor) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCConstructor) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCConstructor) michael@0: NS_IMPL_RELEASE(nsXPCConstructor) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCConstructor michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCConstructor" michael@0: #define XPC_MAP_WANT_CALL michael@0: #define XPC_MAP_WANT_CONSTRUCT michael@0: #define XPC_MAP_FLAGS 0 michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: michael@0: /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: michael@0: } michael@0: michael@0: /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: } michael@0: michael@0: // static michael@0: nsresult michael@0: nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,JSContext *cx, michael@0: HandleObject obj, const CallArgs &args, bool *_retval) michael@0: { michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: michael@0: // security check not required because we are going to call through the michael@0: // code which is reflected into JS which will do that for us later. michael@0: michael@0: nsCOMPtr cidHolder; michael@0: nsCOMPtr iidHolder; michael@0: RootedObject cidObj(cx); michael@0: RootedObject iidObj(cx); michael@0: michael@0: if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID), michael@0: getter_AddRefs(cidHolder))) || !cidHolder || michael@0: // Assign, not compare michael@0: !(cidObj = cidHolder->GetJSObject()) || michael@0: NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID), michael@0: getter_AddRefs(iidHolder))) || !iidHolder || michael@0: // Assign, not compare michael@0: !(iidObj = iidHolder->GetJSObject())) { michael@0: return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval); michael@0: } michael@0: michael@0: JS::Rooted arg(cx, ObjectValue(*iidObj)); michael@0: RootedValue rval(cx); michael@0: if (!JS_CallFunctionName(cx, cidObj, "createInstance", arg, &rval) || michael@0: rval.isPrimitive()) { michael@0: // createInstance will have thrown an exception michael@0: *_retval = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: args.rval().set(rval); michael@0: michael@0: // call initializer method if supplied michael@0: if (mInitializer) { michael@0: RootedObject newObj(cx, &rval.toObject()); michael@0: // first check existence of function property for better error reporting michael@0: RootedValue fun(cx); michael@0: if (!JS_GetProperty(cx, newObj, mInitializer, &fun) || michael@0: fun.isPrimitive()) { michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_INITIALIZER_NAME, cx, _retval); michael@0: } michael@0: michael@0: RootedValue dummy(cx); michael@0: if (!JS_CallFunctionValue(cx, newObj, fun, args, &dummy)) { michael@0: // function should have thrown an exception michael@0: *_retval = false; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /*******************************************************/ michael@0: // JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor) michael@0: michael@0: class nsXPCComponents_Constructor : michael@0: public nsIXPCComponents_Constructor, michael@0: public nsIXPCScriptable, michael@0: public nsIClassInfo michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSICLASSINFO michael@0: michael@0: public: michael@0: nsXPCComponents_Constructor(); michael@0: virtual ~nsXPCComponents_Constructor(); michael@0: michael@0: private: michael@0: static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, HandleObject obj, michael@0: const CallArgs &args, bool *_retval); michael@0: }; michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCComponents_Constructor) michael@0: PUSH_IID(nsIXPCScriptable) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: *retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "XPCComponents_Constructor"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetFlags(uint32_t *aFlags) michael@0: { michael@0: *aFlags = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsXPCComponents_Constructor::nsXPCComponents_Constructor() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents_Constructor::~nsXPCComponents_Constructor() michael@0: { michael@0: // empty michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Constructor) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Constructor) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Constructor) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_Constructor) michael@0: NS_IMPL_RELEASE(nsXPCComponents_Constructor) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_Constructor michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Constructor" michael@0: #define XPC_MAP_WANT_CALL michael@0: #define XPC_MAP_WANT_CONSTRUCT michael@0: #define XPC_MAP_WANT_HASINSTANCE michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: michael@0: /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, michael@0: JSObject *objArg, const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: } michael@0: michael@0: /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, michael@0: JSObject *objArg, const CallArgs &args, bool *_retval) michael@0: { michael@0: RootedObject obj(cx, objArg); michael@0: return CallOrConstruct(wrapper, cx, obj, args, _retval); michael@0: } michael@0: michael@0: // static michael@0: nsresult michael@0: nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext *cx, HandleObject obj, michael@0: const CallArgs &args, bool *_retval) michael@0: { michael@0: // make sure we have at least one arg michael@0: michael@0: if (args.length() < 1) michael@0: return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval); michael@0: michael@0: // get the various other object pointers we need michael@0: michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: XPCWrappedNativeScope* scope = GetObjectScope(obj); michael@0: nsCOMPtr comp; michael@0: michael@0: if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents()))) michael@0: return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval); michael@0: michael@0: // Do the security check if necessary michael@0: michael@0: nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager(); michael@0: if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCConstructor::GetCID()))) { michael@0: // the security manager vetoed. It should have set an exception. michael@0: *_retval = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // initialization params for the Constructor object we will create michael@0: nsCOMPtr cClassID; michael@0: nsCOMPtr cInterfaceID; michael@0: const char* cInitializer = nullptr; michael@0: JSAutoByteString cInitializerBytes; michael@0: michael@0: if (args.length() >= 3) { michael@0: // args[2] is an initializer function or property name michael@0: RootedString str(cx, ToString(cx, args[2])); michael@0: if (!str || !(cInitializer = cInitializerBytes.encodeLatin1(cx, str))) michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval); michael@0: } michael@0: michael@0: if (args.length() >= 2) { michael@0: // args[1] is an iid name string michael@0: // XXXjband support passing "Components.interfaces.foo"? michael@0: michael@0: nsCOMPtr ifaces; michael@0: nsCOMPtr holder; michael@0: RootedObject ifacesObj(cx); michael@0: michael@0: // we do the lookup by asking the Components.interfaces object michael@0: // for the property with this name - i.e. we let its caching of these michael@0: // nsIJSIID objects work for us. michael@0: michael@0: if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) || michael@0: NS_FAILED(xpc->WrapNative(cx, obj, ifaces, michael@0: NS_GET_IID(nsIXPCComponents_Interfaces), michael@0: getter_AddRefs(holder))) || !holder || michael@0: // Assign, not compare michael@0: !(ifacesObj = holder->GetJSObject())) { michael@0: return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval); michael@0: } michael@0: michael@0: RootedString str(cx, ToString(cx, args[1])); michael@0: RootedId id(cx); michael@0: if (!str || !JS_StringToId(cx, str, &id)) michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval); michael@0: michael@0: RootedValue val(cx); michael@0: if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive()) michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval); michael@0: michael@0: nsCOMPtr wn; michael@0: if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(), michael@0: getter_AddRefs(wn))) || !wn || michael@0: !(cInterfaceID = do_QueryWrappedNative(wn))) { michael@0: return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval); michael@0: } michael@0: } else { michael@0: nsCOMPtr info; michael@0: xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info)); michael@0: michael@0: if (info) { michael@0: cInterfaceID = nsJSIID::NewID(info); michael@0: } michael@0: if (!cInterfaceID) michael@0: return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval); michael@0: } michael@0: michael@0: // a new scope to avoid warnings about shadowed names michael@0: { michael@0: // argv[0] is a contractid name string michael@0: // XXXjband support passing "Components.classes.foo"? michael@0: michael@0: // we do the lookup by asking the Components.classes object michael@0: // for the property with this name - i.e. we let its caching of these michael@0: // nsIJSCID objects work for us. michael@0: michael@0: nsCOMPtr classes; michael@0: nsCOMPtr holder; michael@0: RootedObject classesObj(cx); michael@0: michael@0: if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) || michael@0: NS_FAILED(xpc->WrapNative(cx, obj, classes, michael@0: NS_GET_IID(nsIXPCComponents_Classes), michael@0: getter_AddRefs(holder))) || !holder || michael@0: // Assign, not compare michael@0: !(classesObj = holder->GetJSObject())) { michael@0: return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval); michael@0: } michael@0: michael@0: RootedString str(cx, ToString(cx, args[0])); michael@0: RootedId id(cx); michael@0: if (!str || !JS_StringToId(cx, str, &id)) michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval); michael@0: michael@0: RootedValue val(cx); michael@0: if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive()) michael@0: return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval); michael@0: michael@0: nsCOMPtr wn; michael@0: if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val), michael@0: getter_AddRefs(wn))) || !wn || michael@0: !(cClassID = do_QueryWrappedNative(wn))) { michael@0: return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval); michael@0: } michael@0: } michael@0: michael@0: nsCOMPtr ctor = new nsXPCConstructor(cClassID, cInterfaceID, cInitializer); michael@0: nsCOMPtr holder2; michael@0: RootedObject newObj(cx); michael@0: michael@0: if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor), michael@0: getter_AddRefs(holder2))) || !holder2 || michael@0: // Assign, not compare michael@0: !(newObj = holder2->GetJSObject())) { michael@0: return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval); michael@0: } michael@0: michael@0: args.rval().setObject(*newObj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * obj, michael@0: HandleValue val, bool *bp, michael@0: bool *_retval) michael@0: { michael@0: if (bp) michael@0: *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIXPCConstructor)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: class nsXPCComponents_Utils : michael@0: public nsIXPCComponents_Utils, michael@0: public nsIXPCScriptable michael@0: { michael@0: public: michael@0: // all the interface method declarations... michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: NS_DECL_NSIXPCCOMPONENTS_UTILS michael@0: michael@0: public: michael@0: nsXPCComponents_Utils() { } michael@0: virtual ~nsXPCComponents_Utils() { } michael@0: michael@0: private: michael@0: nsCOMPtr mSandbox; michael@0: }; michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(nsXPCComponents_Utils) michael@0: NS_IMPL_RELEASE(nsXPCComponents_Utils) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME nsXPCComponents_Utils michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Utils" michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox **aSandbox) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aSandbox); michael@0: if (!mSandbox) michael@0: mSandbox = NewSandboxConstructor(); michael@0: michael@0: nsCOMPtr rval = mSandbox; michael@0: rval.forget(aSandbox); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void reportError (); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::ReportError(HandleValue error, JSContext *cx) michael@0: { michael@0: // This function shall never fail! Silently eat any failure conditions. michael@0: michael@0: nsCOMPtr console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); michael@0: michael@0: nsCOMPtr scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); michael@0: michael@0: if (!scripterr || !console) michael@0: return NS_OK; michael@0: michael@0: const uint64_t innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx); michael@0: michael@0: RootedObject errorObj(cx, error.isObject() ? &error.toObject() : nullptr); michael@0: JSErrorReport *err = errorObj ? JS_ErrorFromException(cx, errorObj) : nullptr; michael@0: if (err) { michael@0: // It's a proper JS Error michael@0: nsAutoString fileUni; michael@0: CopyUTF8toUTF16(err->filename, fileUni); michael@0: michael@0: uint32_t column = err->uctokenptr - err->uclinebuf; michael@0: michael@0: const char16_t* ucmessage = michael@0: static_cast(err->ucmessage); michael@0: const char16_t* uclinebuf = michael@0: static_cast(err->uclinebuf); michael@0: michael@0: nsresult rv = scripterr->InitWithWindowID( michael@0: ucmessage ? nsDependentString(ucmessage) : EmptyString(), michael@0: fileUni, michael@0: uclinebuf ? nsDependentString(uclinebuf) : EmptyString(), michael@0: err->lineno, michael@0: column, err->flags, "XPConnect JavaScript", innerWindowID); michael@0: NS_ENSURE_SUCCESS(rv, NS_OK); michael@0: michael@0: console->LogMessage(scripterr); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // It's not a JS Error object, so we synthesize as best we're able. michael@0: RootedString msgstr(cx, ToString(cx, error)); michael@0: if (!msgstr) michael@0: return NS_OK; michael@0: michael@0: nsCOMPtr frame; michael@0: nsXPConnect *xpc = nsXPConnect::XPConnect(); michael@0: xpc->GetCurrentJSStack(getter_AddRefs(frame)); michael@0: michael@0: nsString fileName; michael@0: int32_t lineNo = 0; michael@0: if (frame) { michael@0: frame->GetFilename(fileName); michael@0: frame->GetLineNumber(&lineNo); michael@0: } michael@0: michael@0: const jschar *msgchars = JS_GetStringCharsZ(cx, msgstr); michael@0: if (!msgchars) michael@0: return NS_OK; michael@0: michael@0: nsresult rv = scripterr->InitWithWindowID( michael@0: nsDependentString(static_cast(msgchars)), michael@0: fileName, EmptyString(), lineNo, 0, 0, michael@0: "XPConnect JavaScript", innerWindowID); michael@0: NS_ENSURE_SUCCESS(rv, NS_OK); michael@0: michael@0: console->LogMessage(scripterr); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void evalInSandbox(in AString source, in nativeobj sandbox); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::EvalInSandbox(const nsAString& source, michael@0: HandleValue sandboxVal, michael@0: HandleValue version, michael@0: const nsACString& filenameArg, michael@0: int32_t lineNumber, michael@0: JSContext *cx, michael@0: uint8_t optionalArgc, michael@0: MutableHandleValue retval) michael@0: { michael@0: RootedObject sandbox(cx); michael@0: if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: // Optional third argument: JS version, as a string. michael@0: JSVersion jsVersion = JSVERSION_DEFAULT; michael@0: if (optionalArgc >= 1) { michael@0: JSString *jsVersionStr = ToString(cx, version); michael@0: if (!jsVersionStr) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: JSAutoByteString bytes(cx, jsVersionStr); michael@0: if (!bytes) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: jsVersion = JS_StringToVersion(bytes.ptr()); michael@0: // Explicitly check for "latest", which we support for sandboxes but michael@0: // isn't in the set of web-exposed version strings. michael@0: if (jsVersion == JSVERSION_UNKNOWN && michael@0: !strcmp(bytes.ptr(), "latest")) michael@0: { michael@0: jsVersion = JSVERSION_LATEST; michael@0: } michael@0: if (jsVersion == JSVERSION_UNKNOWN) michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: // Optional fourth and fifth arguments: filename and line number. michael@0: int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1; michael@0: nsCString filename; michael@0: if (!filenameArg.IsVoid()) { michael@0: filename.Assign(filenameArg); michael@0: } else { michael@0: // Get the current source info from xpc. michael@0: nsresult rv; michael@0: nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID(), &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr frame; michael@0: xpc->GetCurrentJSStack(getter_AddRefs(frame)); michael@0: if (frame) { michael@0: nsString frameFile; michael@0: frame->GetFilename(frameFile); michael@0: CopyUTF16toUTF8(frameFile, filename); michael@0: frame->GetLineNumber(&lineNo); michael@0: } michael@0: } michael@0: michael@0: return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo, michael@0: jsVersion, false, retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal, michael@0: JSContext *cx, MutableHandleValue rval) michael@0: { michael@0: if (!sandboxVal.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: RootedObject sandbox(cx, &sandboxVal.toObject()); michael@0: sandbox = js::CheckedUnwrap(sandbox); michael@0: if (!sandbox || !xpc::IsSandbox(sandbox)) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: return xpc::GetSandboxMetadata(cx, sandbox, rval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal, michael@0: HandleValue metadataVal, michael@0: JSContext *cx) michael@0: { michael@0: if (!sandboxVal.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: RootedObject sandbox(cx, &sandboxVal.toObject()); michael@0: sandbox = js::CheckedUnwrap(sandbox); michael@0: if (!sandbox || !xpc::IsSandbox(sandbox)) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadataVal); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* JSObject import (in AUTF8String registryLocation, michael@0: * [optional] in JSObject targetObj); michael@0: */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::Import(const nsACString& registryLocation, michael@0: HandleValue targetObj, michael@0: JSContext* cx, michael@0: uint8_t optionalArgc, michael@0: MutableHandleValue retval) michael@0: { michael@0: nsCOMPtr moduleloader = michael@0: do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID); michael@0: if (!moduleloader) michael@0: return NS_ERROR_FAILURE; michael@0: return moduleloader->Import(registryLocation, targetObj, cx, optionalArgc, retval); michael@0: } michael@0: michael@0: /* unload (in AUTF8String registryLocation); michael@0: */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::Unload(const nsACString & registryLocation) michael@0: { michael@0: nsCOMPtr moduleloader = michael@0: do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID); michael@0: if (!moduleloader) michael@0: return NS_ERROR_FAILURE; michael@0: return moduleloader->Unload(registryLocation); michael@0: } michael@0: michael@0: /* michael@0: * JSObject importGlobalProperties (in jsval aPropertyList); michael@0: */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList, michael@0: JSContext* cx) michael@0: { michael@0: RootedObject global(cx, CurrentGlobalOrNull(cx)); michael@0: MOZ_ASSERT(global); michael@0: GlobalProperties options(false); michael@0: NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG); michael@0: RootedObject propertyList(cx, &aPropertyList.toObject()); michael@0: NS_ENSURE_TRUE(JS_IsArrayObject(cx, propertyList), NS_ERROR_INVALID_ARG); michael@0: if (!options.Parse(cx, propertyList) || michael@0: !options.Define(cx, global)) michael@0: { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* xpcIJSWeakReference getWeakReference (); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext *cx, michael@0: xpcIJSWeakReference **_retval) michael@0: { michael@0: nsRefPtr ref = new xpcJSWeakReference(); michael@0: nsresult rv = ref->Init(cx, object); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: ref.forget(_retval); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void forceGC (); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::ForceGC() michael@0: { michael@0: JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); michael@0: PrepareForFullGC(rt); michael@0: GCForReason(rt, gcreason::COMPONENT_UTILS); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void forceCC (); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::ForceCC() michael@0: { michael@0: nsJSContext::CycleCollectNow(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void forceShrinkingGC (); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::ForceShrinkingGC() michael@0: { michael@0: JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); michael@0: PrepareForFullGC(rt); michael@0: ShrinkingGC(rt, gcreason::COMPONENT_UTILS); michael@0: return NS_OK; michael@0: } michael@0: michael@0: class PreciseGCRunnable : public nsRunnable michael@0: { michael@0: public: michael@0: PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking) michael@0: : mCallback(aCallback), mShrinking(aShrinking) {} michael@0: michael@0: NS_IMETHOD Run() michael@0: { michael@0: JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); michael@0: michael@0: JSContext *cx; michael@0: JSContext *iter = nullptr; michael@0: while ((cx = JS_ContextIterator(rt, &iter)) != nullptr) { michael@0: if (JS_IsRunning(cx)) { michael@0: return NS_DispatchToMainThread(this); michael@0: } michael@0: } michael@0: michael@0: PrepareForFullGC(rt); michael@0: if (mShrinking) michael@0: ShrinkingGC(rt, gcreason::COMPONENT_UTILS); michael@0: else michael@0: GCForReason(rt, gcreason::COMPONENT_UTILS); michael@0: michael@0: mCallback->Callback(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: private: michael@0: nsRefPtr mCallback; michael@0: bool mShrinking; michael@0: }; michael@0: michael@0: /* void schedulePreciseGC(in ScheduledGCCallback callback); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback) michael@0: { michael@0: nsRefPtr event = new PreciseGCRunnable(aCallback, false); michael@0: return NS_DispatchToMainThread(event); michael@0: } michael@0: michael@0: /* void schedulePreciseShrinkingGC(in ScheduledGCCallback callback); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback) michael@0: { michael@0: nsRefPtr event = new PreciseGCRunnable(aCallback, true); michael@0: return NS_DispatchToMainThread(event); michael@0: } michael@0: michael@0: /* void unlinkGhostWindows(); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::UnlinkGhostWindows() michael@0: { michael@0: #ifdef DEBUG michael@0: nsWindowMemoryReporter::UnlinkGhostWindows(); michael@0: return NS_OK; michael@0: #else michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: #endif michael@0: } michael@0: michael@0: /* [implicit_jscontext] jsval nondeterministicGetWeakMapKeys(in jsval aMap); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(HandleValue aMap, michael@0: JSContext *aCx, michael@0: MutableHandleValue aKeys) michael@0: { michael@0: if (!aMap.isObject()) { michael@0: aKeys.setUndefined(); michael@0: return NS_OK; michael@0: } michael@0: RootedObject objRet(aCx); michael@0: RootedObject mapObj(aCx, &aMap.toObject()); michael@0: if (!JS_NondeterministicGetWeakMapKeys(aCx, mapObj, &objRet)) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: aKeys.set(objRet ? ObjectValue(*objRet) : UndefinedValue()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void getDebugObject(); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx, michael@0: MutableHandleValue retval) michael@0: { michael@0: JSObject *obj = js::GetTestingFunctions(cx); michael@0: if (!obj) michael@0: return NS_ERROR_XPC_JAVASCRIPT_ERROR; michael@0: retval.setObject(*obj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void getGlobalForObject(); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetGlobalForObject(HandleValue object, michael@0: JSContext *cx, michael@0: MutableHandleValue retval) michael@0: { michael@0: // First argument must be an object. michael@0: if (object.isPrimitive()) michael@0: return NS_ERROR_XPC_BAD_CONVERT_JS; michael@0: michael@0: // Wrappers are parented to their the global in their home compartment. But michael@0: // when getting the global for a cross-compartment wrapper, we really want michael@0: // a wrapper for the foreign global. So we need to unwrap before getting the michael@0: // parent, enter the compartment for the duration of the call, and wrap the michael@0: // result. michael@0: Rooted obj(cx, &object.toObject()); michael@0: obj = js::UncheckedUnwrap(obj); michael@0: { michael@0: JSAutoCompartment ac(cx, obj); michael@0: obj = JS_GetGlobalForObject(cx, obj); michael@0: } michael@0: michael@0: if (!JS_WrapObject(cx, &obj)) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // Outerize if necessary. michael@0: if (JSObjectOp outerize = js::GetObjectClass(obj)->ext.outerObject) michael@0: obj = outerize(cx, obj); michael@0: michael@0: retval.setObject(*obj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* jsval createObjectIn(in jsval vobj); */ michael@0: bool michael@0: xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectInOptions &options, michael@0: MutableHandleValue rval) michael@0: { michael@0: if (!vobj.isObject()) { michael@0: JS_ReportError(cx, "Expected an object as the target scope"); michael@0: return false; michael@0: } michael@0: michael@0: RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject())); michael@0: if (!scope) { michael@0: JS_ReportError(cx, "Permission denied to create object in the target scope"); michael@0: return false; michael@0: } michael@0: michael@0: bool define = !JSID_IS_VOID(options.defineAs); michael@0: michael@0: if (define && js::IsScriptedProxy(scope)) { michael@0: JS_ReportError(cx, "Defining property on proxy object is not allowed"); michael@0: return false; michael@0: } michael@0: michael@0: RootedObject obj(cx); michael@0: { michael@0: JSAutoCompartment ac(cx, scope); michael@0: obj = JS_NewObject(cx, nullptr, JS::NullPtr(), scope); michael@0: if (!obj) michael@0: return false; michael@0: michael@0: if (define) { michael@0: if (!JS_DefinePropertyById(cx, scope, options.defineAs, ObjectValue(*obj), michael@0: JS_PropertyStub, JS_StrictPropertyStub, michael@0: JSPROP_ENUMERATE)) michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: rval.setObject(*obj); michael@0: if (!WrapperFactory::WaiveXrayAndWrap(cx, rval)) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: /* boolean isProxy(in value vobj); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext *cx, bool *rval) michael@0: { michael@0: if (!vobj.isObject()) { michael@0: *rval = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: RootedObject obj(cx, &vobj.toObject()); michael@0: obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false); michael@0: NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE); michael@0: michael@0: *rval = js::IsScriptedProxy(obj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* jsval evalInWindow(in string source, in jsval window); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::EvalInWindow(const nsAString &source, HandleValue window, michael@0: JSContext *cx, MutableHandleValue rval) michael@0: { michael@0: if (!window.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: RootedObject rwindow(cx, &window.toObject()); michael@0: if (!xpc::EvalInWindow(cx, source, rwindow, rval)) michael@0: return NS_ERROR_FAILURE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* jsval exportFunction(in jsval vfunction, in jsval vscope, in jsval voptions); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::ExportFunction(HandleValue vfunction, HandleValue vscope, michael@0: HandleValue voptions, JSContext *cx, michael@0: MutableHandleValue rval) michael@0: { michael@0: if (!xpc::ExportFunction(cx, vfunction, vscope, voptions, rval)) michael@0: return NS_ERROR_FAILURE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* jsval createObjectIn(in jsval vobj, [optional] in jsval voptions); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::CreateObjectIn(HandleValue vobj, HandleValue voptions, michael@0: JSContext *cx, MutableHandleValue rval) michael@0: { michael@0: RootedObject optionsObject(cx, voptions.isObject() ? &voptions.toObject() michael@0: : nullptr); michael@0: CreateObjectInOptions options(cx, optionsObject); michael@0: if (voptions.isObject() && michael@0: !options.Parse()) michael@0: { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: if (!xpc::CreateObjectIn(cx, vobj, options, rval)) michael@0: return NS_ERROR_FAILURE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void makeObjectPropsNormal(jsval vobj); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::MakeObjectPropsNormal(HandleValue vobj, JSContext *cx) michael@0: { michael@0: if (!cx) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // first argument must be an object michael@0: if (vobj.isPrimitive()) michael@0: return NS_ERROR_XPC_BAD_CONVERT_JS; michael@0: michael@0: RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject())); michael@0: JSAutoCompartment ac(cx, obj); michael@0: AutoIdArray ida(cx, JS_Enumerate(cx, obj)); michael@0: if (!ida) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: RootedId id(cx); michael@0: RootedValue v(cx); michael@0: for (size_t i = 0; i < ida.length(); ++i) { michael@0: id = ida[i]; michael@0: michael@0: if (!JS_GetPropertyById(cx, obj, id, &v)) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: if (v.isPrimitive()) michael@0: continue; michael@0: michael@0: RootedObject propobj(cx, &v.toObject()); michael@0: // TODO Deal with non-functions. michael@0: if (!js::IsWrapper(propobj) || !JS_ObjectIsCallable(cx, propobj)) michael@0: continue; michael@0: michael@0: if (!NewFunctionForwarder(cx, id, propobj, /* doclone = */ false, &v) || michael@0: !JS_SetPropertyById(cx, obj, id, v)) michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::IsDeadWrapper(HandleValue obj, bool *out) michael@0: { michael@0: *out = false; michael@0: if (obj.isPrimitive()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: // Make sure to unwrap first. Once a proxy is nuked, it ceases to be a michael@0: // wrapper, meaning that, if passed to another compartment, we'll generate michael@0: // a CCW for it. Make sure that IsDeadWrapper sees through the confusion. michael@0: *out = JS_IsDeadWrapper(js::CheckedUnwrap(&obj.toObject())); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void recomputerWrappers(jsval vobj); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext *cx) michael@0: { michael@0: // Determine the compartment of the given object, if any. michael@0: JSCompartment *c = vobj.isObject() michael@0: ? js::GetObjectCompartment(js::UncheckedUnwrap(&vobj.toObject())) michael@0: : nullptr; michael@0: michael@0: // If no compartment was given, recompute all. michael@0: if (!c) michael@0: js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments()); michael@0: // Otherwise, recompute wrappers for the given compartment. michael@0: else michael@0: js::RecomputeWrappers(cx, js::SingleCompartment(c), js::AllCompartments()) && michael@0: js::RecomputeWrappers(cx, js::AllCompartments(), js::SingleCompartment(c)); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* jsval setWantXrays(jsval vscope); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::SetWantXrays(HandleValue vscope, JSContext *cx) michael@0: { michael@0: if (!vscope.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject()); michael@0: JSCompartment *compartment = js::GetObjectCompartment(scopeObj); michael@0: EnsureCompartmentPrivate(scopeObj)->wantXrays = true; michael@0: bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment), michael@0: js::AllCompartments()); michael@0: NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* jsval forcePrivilegedComponentsForScope(jsval vscope); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::ForcePrivilegedComponentsForScope(HandleValue vscope, michael@0: JSContext *cx) michael@0: { michael@0: if (!vscope.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject()); michael@0: XPCWrappedNativeScope *scope = GetObjectScope(scopeObj); michael@0: scope->ForcePrivilegedComponents(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* jsval getComponentsForScope(jsval vscope); */ michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext *cx, michael@0: MutableHandleValue rval) michael@0: { michael@0: if (!vscope.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject()); michael@0: XPCWrappedNativeScope *scope = GetObjectScope(scopeObj); michael@0: RootedObject components(cx); michael@0: if (!scope->GetComponentsJSObject(&components)) michael@0: return NS_ERROR_FAILURE; michael@0: if (!JS_WrapObject(cx, &components)) michael@0: return NS_ERROR_FAILURE; michael@0: rval.setObject(*components); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope, michael@0: JSContext *cx) michael@0: { michael@0: RootedValue runnable(cx, runnableArg); michael@0: // Enter the given compartment, if any, and rewrap runnable. michael@0: Maybe ac; michael@0: if (scope.isObject()) { michael@0: JSObject *scopeObj = js::UncheckedUnwrap(&scope.toObject()); michael@0: if (!scopeObj) michael@0: return NS_ERROR_FAILURE; michael@0: ac.construct(cx, scopeObj); michael@0: if (!JS_WrapValue(cx, &runnable)) michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: // Get an XPCWrappedJS for |runnable|. michael@0: if (!runnable.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: nsCOMPtr run; michael@0: nsresult rv = nsXPConnect::XPConnect()->WrapJS(cx, &runnable.toObject(), michael@0: NS_GET_IID(nsIRunnable), michael@0: getter_AddRefs(run)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: MOZ_ASSERT(run); michael@0: michael@0: // Dispatch. michael@0: return NS_DispatchToMainThread(run); michael@0: } michael@0: michael@0: #define GENERATE_JSCONTEXTOPTION_GETTER_SETTER(_attr, _getter, _setter) \ michael@0: NS_IMETHODIMP \ michael@0: nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \ michael@0: { \ michael@0: *aValue = ContextOptionsRef(cx)._getter(); \ michael@0: return NS_OK; \ michael@0: } \ michael@0: NS_IMETHODIMP \ michael@0: nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \ michael@0: { \ michael@0: ContextOptionsRef(cx)._setter(aValue); \ michael@0: return NS_OK; \ michael@0: } michael@0: michael@0: #define GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(_attr, _getter, _setter) \ michael@0: NS_IMETHODIMP \ michael@0: nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \ michael@0: { \ michael@0: *aValue = RuntimeOptionsRef(cx)._getter(); \ michael@0: return NS_OK; \ michael@0: } \ michael@0: NS_IMETHODIMP \ michael@0: nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \ michael@0: { \ michael@0: RuntimeOptionsRef(cx)._setter(aValue); \ michael@0: return NS_OK; \ michael@0: } michael@0: michael@0: GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings) michael@0: GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Werror, werror, setWerror) michael@0: GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode) michael@0: GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Ion, ion, setIon) michael@0: michael@0: #undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER michael@0: #undef GENERATE_JSRUNTIMEOPTION_GETTER_SETTER michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx) michael@0: { michael@0: #ifdef JS_GC_ZEAL michael@0: JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ); michael@0: #endif michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext *cx) michael@0: { michael@0: NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG); michael@0: JSObject *wrapper = &obj.toObject(); michael@0: NS_ENSURE_TRUE(IsWrapper(wrapper), NS_ERROR_INVALID_ARG); michael@0: JSObject *sb = UncheckedUnwrap(wrapper); michael@0: NS_ENSURE_TRUE(IsSandbox(sb), NS_ERROR_INVALID_ARG); michael@0: NukeCrossCompartmentWrappers(cx, AllCompartments(), michael@0: SingleCompartment(GetObjectCompartment(sb)), michael@0: NukeWindowReferences); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg, michael@0: JSContext *cx) michael@0: { michael@0: NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG); michael@0: RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(), michael@0: /* stopAtOuter = */ false)); michael@0: NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG); michael@0: if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) { michael@0: JS_ReportError(cx, "Script may not be disabled for system globals"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: Scriptability::Get(global).Block(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg, michael@0: JSContext *cx) michael@0: { michael@0: NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG); michael@0: RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(), michael@0: /* stopAtOuter = */ false)); michael@0: NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG); michael@0: if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) { michael@0: JS_ReportError(cx, "Script may not be disabled for system globals"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: Scriptability::Get(global).Unblock(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::IsXrayWrapper(HandleValue obj, bool* aRetval) michael@0: { michael@0: *aRetval = michael@0: obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::WaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval) michael@0: { michael@0: RootedValue value(aCx, aVal); michael@0: if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value)) michael@0: return NS_ERROR_FAILURE; michael@0: aRetval.set(value); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::UnwaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval) michael@0: { michael@0: if (!aVal.isObject()) { michael@0: aRetval.set(aVal); michael@0: return NS_OK; michael@0: } michael@0: michael@0: RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject())); michael@0: if (!JS_WrapObject(aCx, &obj)) michael@0: return NS_ERROR_FAILURE; michael@0: aRetval.setObject(*obj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap, JSContext *aCx, char **aRv) michael@0: { michael@0: if (!aObj.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: RootedObject obj(aCx, &aObj.toObject()); michael@0: if (aUnwrap) michael@0: obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false); michael@0: *aRv = NS_strdup(js::GetObjectClass(obj)->name); michael@0: NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetDOMClassInfo(const nsAString& aClassName, michael@0: nsIClassInfo** aClassInfo) michael@0: { michael@0: *aClassInfo = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetIncumbentGlobal(HandleValue aCallback, michael@0: JSContext *aCx, MutableHandleValue aOut) michael@0: { michael@0: nsCOMPtr global = mozilla::dom::GetIncumbentGlobal(); michael@0: RootedValue globalVal(aCx); michael@0: michael@0: if (!global) { michael@0: globalVal = NullValue(); michael@0: } else { michael@0: // Note: We rely on the wrap call for outerization. michael@0: globalVal = ObjectValue(*global->GetGlobalJSObject()); michael@0: if (!JS_WrapValue(aCx, &globalVal)) michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: // Invoke the callback, if passed. michael@0: if (aCallback.isObject()) { michael@0: RootedValue ignored(aCx); michael@0: if (!JS_CallFunctionValue(aCx, JS::NullPtr(), aCallback, globalVal, &ignored)) michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: aOut.set(globalVal); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* michael@0: * Below is a bunch of awkward junk to allow JS test code to trigger the michael@0: * creation of an XPCWrappedJS, such that it ends up in the map. We need to michael@0: * hand the caller some sort of reference to hold onto (to prevent the michael@0: * refcount from dropping to zero as soon as the function returns), but trying michael@0: * to return a bonafide XPCWrappedJS to script causes all sorts of trouble. So michael@0: * we create a benign holder class instead, which acts as an opaque reference michael@0: * that script can use to keep the XPCWrappedJS alive and in the map. michael@0: */ michael@0: michael@0: class WrappedJSHolder : public nsISupports michael@0: { michael@0: NS_DECL_ISUPPORTS michael@0: WrappedJSHolder() {} michael@0: virtual ~WrappedJSHolder() {} michael@0: michael@0: nsRefPtr mWrappedJS; michael@0: }; michael@0: NS_IMPL_ISUPPORTS0(WrappedJSHolder); michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GenerateXPCWrappedJS(HandleValue aObj, HandleValue aScope, michael@0: JSContext *aCx, nsISupports **aOut) michael@0: { michael@0: if (!aObj.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: RootedObject obj(aCx, &aObj.toObject()); michael@0: RootedObject scope(aCx, aScope.isObject() ? js::UncheckedUnwrap(&aScope.toObject()) michael@0: : CurrentGlobalOrNull(aCx)); michael@0: JSAutoCompartment ac(aCx, scope); michael@0: if (!JS_WrapObject(aCx, &obj)) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: nsRefPtr holder = new WrappedJSHolder(); michael@0: nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports), michael@0: getter_AddRefs(holder->mWrappedJS)); michael@0: holder.forget(aOut); michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory, PRTime *aOut) michael@0: { michael@0: WatchdogTimestampCategory category; michael@0: if (aCategory.EqualsLiteral("RuntimeStateChange")) michael@0: category = TimestampRuntimeStateChange; michael@0: else if (aCategory.EqualsLiteral("WatchdogWakeup")) michael@0: category = TimestampWatchdogWakeup; michael@0: else if (aCategory.EqualsLiteral("WatchdogHibernateStart")) michael@0: category = TimestampWatchdogHibernateStart; michael@0: else if (aCategory.EqualsLiteral("WatchdogHibernateStop")) michael@0: category = TimestampWatchdogHibernateStop; michael@0: else michael@0: return NS_ERROR_INVALID_ARG; michael@0: *aOut = XPCJSRuntime::Get()->GetWatchdogTimestamp(category); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext *cx, MutableHandleValue rval) michael@0: { michael@0: RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr())); michael@0: if (!obj) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT; michael@0: michael@0: size_t i = JS_SetProtoCalled(cx); michael@0: RootedValue v(cx, DoubleValue(i)); michael@0: if (!JS_DefineProperty(cx, obj, "setProto", v, attrs)) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: i = JS_GetCustomIteratorCount(cx); michael@0: v.setDouble(i); michael@0: if (!JS_DefineProperty(cx, obj, "customIter", v, attrs)) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: rval.setObject(*obj); michael@0: return NS_OK; michael@0: } michael@0: michael@0: class MOZ_STACK_CLASS CloneIntoOptions : public OptionsBase michael@0: { michael@0: public: michael@0: CloneIntoOptions(JSContext *cx = xpc_GetSafeJSContext(), michael@0: JSObject *options = nullptr) michael@0: : OptionsBase(cx, options) michael@0: , cloneFunctions(false) michael@0: {} michael@0: michael@0: virtual bool Parse() michael@0: { michael@0: return ParseBoolean("cloneFunctions", &cloneFunctions); michael@0: } michael@0: michael@0: bool cloneFunctions; michael@0: }; michael@0: michael@0: class MOZ_STACK_CLASS CloneIntoCallbacksData michael@0: { michael@0: public: michael@0: CloneIntoCallbacksData(JSContext *aCx, CloneIntoOptions *aOptions) michael@0: : mOptions(aOptions) michael@0: , mFunctions(aCx) michael@0: {} michael@0: michael@0: CloneIntoOptions *mOptions; michael@0: AutoObjectVector mFunctions; michael@0: }; michael@0: michael@0: static JSObject* michael@0: CloneIntoReadStructuredClone(JSContext *cx, michael@0: JSStructuredCloneReader *reader, michael@0: uint32_t tag, michael@0: uint32_t value, michael@0: void* closure) michael@0: { michael@0: CloneIntoCallbacksData* data = static_cast(closure); michael@0: MOZ_ASSERT(data); michael@0: michael@0: if (tag == mozilla::dom::SCTAG_DOM_BLOB || tag == mozilla::dom::SCTAG_DOM_FILELIST) { michael@0: MOZ_ASSERT(!value, "Data should be empty"); michael@0: michael@0: nsISupports *supports; michael@0: if (JS_ReadBytes(reader, &supports, sizeof(supports))) { michael@0: RootedValue val(cx); michael@0: if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val))) michael@0: return val.toObjectOrNull(); michael@0: } michael@0: } michael@0: michael@0: if (tag == mozilla::dom::SCTAG_DOM_FUNCTION) { michael@0: MOZ_ASSERT(value < data->mFunctions.length()); michael@0: michael@0: RootedValue functionValue(cx); michael@0: RootedObject obj(cx, data->mFunctions[value]); michael@0: michael@0: if (!JS_WrapObject(cx, &obj)) michael@0: return nullptr; michael@0: michael@0: if (!xpc::NewFunctionForwarder(cx, obj, false, &functionValue)) michael@0: return nullptr; michael@0: michael@0: return &functionValue.toObject(); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: static bool michael@0: CloneIntoWriteStructuredClone(JSContext *cx, michael@0: JSStructuredCloneWriter *writer, michael@0: HandleObject obj, michael@0: void *closure) michael@0: { michael@0: CloneIntoCallbacksData* data = static_cast(closure); michael@0: MOZ_ASSERT(data); michael@0: michael@0: nsCOMPtr wrappedNative; michael@0: nsContentUtils::XPConnect()->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative)); michael@0: if (wrappedNative) { michael@0: uint32_t scTag = 0; michael@0: nsISupports *supports = wrappedNative->Native(); michael@0: michael@0: nsCOMPtr blob = do_QueryInterface(supports); michael@0: if (blob) michael@0: scTag = mozilla::dom::SCTAG_DOM_BLOB; michael@0: else { michael@0: nsCOMPtr list = do_QueryInterface(supports); michael@0: if (list) michael@0: scTag = mozilla::dom::SCTAG_DOM_FILELIST; michael@0: } michael@0: michael@0: if (scTag) { michael@0: return JS_WriteUint32Pair(writer, scTag, 0) && michael@0: JS_WriteBytes(writer, &supports, sizeof(supports)); michael@0: } michael@0: } michael@0: michael@0: if (data->mOptions->cloneFunctions && JS_ObjectIsCallable(cx, obj)) { michael@0: data->mFunctions.append(obj); michael@0: return JS_WriteUint32Pair(writer, mozilla::dom::SCTAG_DOM_FUNCTION, michael@0: data->mFunctions.length() - 1); michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: // These functions serialize raw XPCOM pointers in the data stream, and thus michael@0: // should only be used when the read and write are done together michael@0: // synchronously. michael@0: static JSStructuredCloneCallbacks CloneIntoCallbacks = { michael@0: CloneIntoReadStructuredClone, michael@0: CloneIntoWriteStructuredClone, michael@0: nullptr michael@0: }; michael@0: michael@0: bool michael@0: xpc::CloneInto(JSContext *aCx, HandleValue aValue, HandleValue aScope, michael@0: HandleValue aOptions, MutableHandleValue aCloned) michael@0: { michael@0: if (!aScope.isObject()) michael@0: return false; michael@0: michael@0: RootedObject scope(aCx, &aScope.toObject()); michael@0: scope = js::CheckedUnwrap(scope); michael@0: if(!scope) { michael@0: JS_ReportError(aCx, "Permission denied to clone object into scope"); michael@0: return false; michael@0: } michael@0: michael@0: if (!aOptions.isUndefined() && !aOptions.isObject()) { michael@0: JS_ReportError(aCx, "Invalid argument"); michael@0: return false; michael@0: } michael@0: michael@0: RootedObject optionsObject(aCx, aOptions.isObject() ? &aOptions.toObject() michael@0: : nullptr); michael@0: CloneIntoOptions options(aCx, optionsObject); michael@0: if (aOptions.isObject() && !options.Parse()) michael@0: return false; michael@0: michael@0: { michael@0: CloneIntoCallbacksData data(aCx, &options); michael@0: JSAutoCompartment ac(aCx, scope); michael@0: if (!JS_StructuredClone(aCx, aValue, aCloned, &CloneIntoCallbacks, &data)) michael@0: return false; michael@0: } michael@0: michael@0: return JS_WrapValue(aCx, aCloned); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope, michael@0: HandleValue aOptions, JSContext *aCx, michael@0: MutableHandleValue aCloned) michael@0: { michael@0: return xpc::CloneInto(aCx, aValue, aScope, aOptions, aCloned) ? michael@0: NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal **aResult) michael@0: { michael@0: // This API may only be when the Entry Settings Object corresponds to a michael@0: // JS-implemented WebIDL call. In all other cases, the value will be null, michael@0: // and we throw. michael@0: nsCOMPtr callerPrin = mozilla::dom::GetWebIDLCallerPrincipal(); michael@0: if (!callerPrin) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: callerPrin.forget(aResult); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext *cx, michael@0: nsIPrincipal **result) michael@0: { michael@0: if (!val.isObject()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: RootedObject obj(cx, &val.toObject()); michael@0: obj = js::CheckedUnwrap(obj); michael@0: MOZ_ASSERT(obj); michael@0: michael@0: nsCOMPtr prin = nsContentUtils::GetObjectPrincipal(obj); michael@0: prin.forget(result); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: /***************************************************************************/ michael@0: michael@0: michael@0: nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope) michael@0: : mScope(aScope) michael@0: { michael@0: MOZ_ASSERT(aScope, "aScope must not be null"); michael@0: } michael@0: michael@0: nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope) michael@0: : nsXPCComponentsBase(aScope) michael@0: { michael@0: } michael@0: michael@0: nsXPCComponentsBase::~nsXPCComponentsBase() michael@0: { michael@0: } michael@0: michael@0: nsXPCComponents::~nsXPCComponents() michael@0: { michael@0: } michael@0: michael@0: void michael@0: nsXPCComponentsBase::ClearMembers() michael@0: { michael@0: mInterfaces = nullptr; michael@0: mInterfacesByID = nullptr; michael@0: mResults = nullptr; michael@0: } michael@0: michael@0: void michael@0: nsXPCComponents::ClearMembers() michael@0: { michael@0: mClasses = nullptr; michael@0: mClassesByID = nullptr; michael@0: mID = nullptr; michael@0: mException = nullptr; michael@0: mConstructor = nullptr; michael@0: mUtils = nullptr; michael@0: michael@0: nsXPCComponentsBase::ClearMembers(); michael@0: } michael@0: michael@0: /*******************************************/ michael@0: #define XPC_IMPL_GET_OBJ_METHOD(_class, _n) \ michael@0: NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n * *a##_n) { \ michael@0: NS_ENSURE_ARG_POINTER(a##_n); \ michael@0: if (!m##_n) \ michael@0: m##_n = new nsXPCComponents_##_n(); \ michael@0: nsRefPtr ret = m##_n; \ michael@0: ret.forget(a##_n); \ michael@0: return NS_OK; \ michael@0: } michael@0: michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Interfaces) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, InterfacesByID) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ClassesByID) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Results) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor) michael@0: XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils) michael@0: michael@0: #undef XPC_IMPL_GET_OBJ_METHOD michael@0: /*******************************************/ michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponentsBase::IsSuccessCode(nsresult result, bool *out) michael@0: { michael@0: *out = NS_SUCCEEDED(result); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents::GetStack(nsIStackFrame * *aStack) michael@0: { michael@0: nsresult rv; michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: rv = xpc->GetCurrentJSStack(aStack); michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents::GetManager(nsIComponentManager * *aManager) michael@0: { michael@0: MOZ_ASSERT(aManager, "bad param"); michael@0: return NS_GetComponentManager(aManager); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents::GetLastResult(JSContext *aCx, MutableHandleValue aOut) michael@0: { michael@0: XPCContext* xpcc = XPCContext::GetXPCContext(aCx); michael@0: if (!xpcc) michael@0: return NS_ERROR_FAILURE; michael@0: nsresult res = xpcc->GetLastResult(); michael@0: aOut.setNumber(static_cast(res)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents::GetReturnCode(JSContext *aCx, MutableHandleValue aOut) michael@0: { michael@0: XPCContext* xpcc = XPCContext::GetXPCContext(aCx); michael@0: if (!xpcc) michael@0: return NS_ERROR_FAILURE; michael@0: nsresult res = xpcc->GetPendingResult(); michael@0: aOut.setNumber(static_cast(res)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXPCComponents::SetReturnCode(JSContext *aCx, HandleValue aCode) michael@0: { michael@0: XPCContext* xpcc = XPCContext::GetXPCContext(aCx); michael@0: if (!xpcc) michael@0: return NS_ERROR_FAILURE; michael@0: nsresult rv; michael@0: if (!ToUint32(aCx, aCode, (uint32_t*)&rv)) michael@0: return NS_ERROR_FAILURE; michael@0: xpcc->SetPendingResult(rv); michael@0: xpcc->SetLastResult(rv); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // static michael@0: /* void reportError (); */ michael@0: NS_IMETHODIMP nsXPCComponents::ReportError(HandleValue error, JSContext *cx) michael@0: { michael@0: NS_WARNING("Components.reportError deprecated, use Components.utils.reportError"); michael@0: michael@0: nsCOMPtr utils; michael@0: nsresult rv = GetUtils(getter_AddRefs(utils)); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: return utils->ReportError(error, cx); michael@0: } michael@0: michael@0: /**********************************************/ michael@0: michael@0: class ComponentsSH : public nsIXPCScriptable michael@0: { michael@0: public: michael@0: ComponentsSH(unsigned dummy) michael@0: { michael@0: } michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIXPCSCRIPTABLE michael@0: // The NS_IMETHODIMP isn't really accurate here, but NS_CALLBACK requires michael@0: // the referent to be declared __stdcall on Windows, and this is the only michael@0: // macro that does that. michael@0: static NS_IMETHODIMP Get(uint32_t aLangId, nsISupports **helper) michael@0: { michael@0: *helper = &singleton; michael@0: return NS_OK; michael@0: } michael@0: michael@0: private: michael@0: static ComponentsSH singleton; michael@0: }; michael@0: michael@0: ComponentsSH ComponentsSH::singleton(0); michael@0: michael@0: // Singleton refcounting. michael@0: NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::AddRef(void) { return 1; } michael@0: NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::Release(void) { return 1; } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(ComponentsSH) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupports) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: #define NSXPCCOMPONENTSBASE_CID \ michael@0: { 0xc62998e5, 0x95f1, 0x4058, \ michael@0: { 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 } } michael@0: michael@0: #define NSXPCCOMPONENTS_CID \ michael@0: { 0x3649f405, 0xf0ec, 0x4c28, \ michael@0: { 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 } } michael@0: michael@0: NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID) michael@0: NS_IMPL_ISUPPORTS_CI(nsXPCComponentsBase, nsIXPCComponentsBase) michael@0: michael@0: NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTS_CID) michael@0: // Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like michael@0: // if it existed. michael@0: NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase) michael@0: NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase) michael@0: NS_INTERFACE_MAP_BEGIN(nsXPCComponents) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCComponents) michael@0: NS_IMPL_QUERY_CLASSINFO(nsXPCComponents) michael@0: NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase) michael@0: NS_IMPL_CI_INTERFACE_GETTER(nsXPCComponents, nsIXPCComponents) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us michael@0: #define XPC_MAP_CLASSNAME ComponentsSH michael@0: #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents" michael@0: #define XPC_MAP_WANT_PRECREATE michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: NS_IMETHODIMP michael@0: ComponentsSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj) michael@0: { michael@0: nsXPCComponentsBase *self = static_cast(nativeObj); michael@0: // this should never happen michael@0: if (!self->GetScope()) { michael@0: NS_WARNING("mScope must not be null when nsXPCComponents::PreCreate is called"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: *parentObj = self->GetScope()->GetGlobalJSObject(); michael@0: return NS_OK; michael@0: }