3560 lines
110 KiB
C++
3560 lines
110 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/* The "Components" xpcom objects for JavaScript. */
|
|
|
|
#include "xpcprivate.h"
|
|
#include "xpcIJSModuleLoader.h"
|
|
#include "XPCJSWeakReference.h"
|
|
#include "WrapperFactory.h"
|
|
#include "nsJSUtils.h"
|
|
#include "mozJSComponentLoader.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsCycleCollector.h"
|
|
#include "jsfriendapi.h"
|
|
#include "js/StructuredClone.h"
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "nsJSEnvironment.h"
|
|
#include "mozilla/TimeStamp.h"
|
|
#include "mozilla/XPTInterfaceInfoManager.h"
|
|
#include "mozilla/dom/DOMException.h"
|
|
#include "mozilla/dom/DOMExceptionBinding.h"
|
|
#include "mozilla/dom/BindingUtils.h"
|
|
#include "mozilla/dom/StructuredCloneTags.h"
|
|
#include "mozilla/dom/WindowBinding.h"
|
|
#include "nsZipArchive.h"
|
|
#include "nsIDOMFileList.h"
|
|
#include "nsWindowMemoryReporter.h"
|
|
#include "nsDOMClassInfo.h"
|
|
#include "ShimInterfaceInfo.h"
|
|
#include "nsIAddonInterposition.h"
|
|
#include "nsISimpleEnumerator.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace JS;
|
|
using namespace js;
|
|
using namespace xpc;
|
|
using mozilla::dom::Exception;
|
|
|
|
/***************************************************************************/
|
|
// stuff used by all
|
|
|
|
nsresult
|
|
xpc::ThrowAndFail(nsresult errNum, JSContext* cx, bool* retval)
|
|
{
|
|
XPCThrower::Throw(errNum, cx);
|
|
*retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
static bool
|
|
JSValIsInterfaceOfType(JSContext* cx, HandleValue v, REFNSIID iid)
|
|
{
|
|
|
|
nsCOMPtr<nsIXPConnectWrappedNative> wn;
|
|
nsCOMPtr<nsISupports> sup;
|
|
nsCOMPtr<nsISupports> iface;
|
|
|
|
if (v.isPrimitive())
|
|
return false;
|
|
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
RootedObject obj(cx, &v.toObject());
|
|
return NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) && wn &&
|
|
NS_SUCCEEDED(wn->Native()->QueryInterface(iid, getter_AddRefs(iface))) && iface;
|
|
}
|
|
|
|
char*
|
|
xpc::CloneAllAccess()
|
|
{
|
|
static const char allAccess[] = "AllAccess";
|
|
return (char*)nsMemory::Clone(allAccess, sizeof(allAccess));
|
|
}
|
|
|
|
char*
|
|
xpc::CheckAccessList(const char16_t* wideName, const char* const list[])
|
|
{
|
|
nsAutoCString asciiName;
|
|
CopyUTF16toUTF8(nsDependentString(wideName), asciiName);
|
|
|
|
for (const char* const* p = list; *p; p++)
|
|
if (!strcmp(*p, asciiName.get()))
|
|
return CloneAllAccess();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
|
|
|
|
class nsXPCComponents_Interfaces final :
|
|
public nsIXPCComponents_Interfaces,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_INTERFACES
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
public:
|
|
nsXPCComponents_Interfaces();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_Interfaces();
|
|
|
|
nsCOMArray<nsIInterfaceInfo> mInterfaces;
|
|
};
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_Interfaces)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_Interfaces";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::GetFlags(uint32_t* aFlags)
|
|
{
|
|
// Mark ourselves as a DOM object so that instances may be created in
|
|
// unprivileged scopes.
|
|
*aFlags = nsIClassInfo::DOM_OBJECT;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_Interfaces::nsXPCComponents_Interfaces()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Interfaces)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Interfaces)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_Interfaces)
|
|
NS_IMPL_RELEASE(nsXPCComponents_Interfaces)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_Interfaces
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Interfaces"
|
|
#define XPC_MAP_WANT_RESOLVE
|
|
#define XPC_MAP_WANT_NEWENUMERATE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* obj,
|
|
JS::AutoIdVector& properties,
|
|
bool* _retval)
|
|
{
|
|
|
|
// Lazily init the list of interfaces when someone tries to
|
|
// enumerate them.
|
|
if (mInterfaces.IsEmpty()) {
|
|
XPTInterfaceInfoManager::GetSingleton()->
|
|
GetScriptableInterfaces(mInterfaces);
|
|
}
|
|
|
|
if (!properties.reserve(mInterfaces.Length())) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
for (uint32_t index = 0; index < mInterfaces.Length(); index++) {
|
|
nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(index);
|
|
if (!interface)
|
|
continue;
|
|
|
|
const char* name;
|
|
if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) {
|
|
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
|
|
if (!idstr) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
RootedId id(cx);
|
|
if (!JS_StringToId(cx, idstr, &id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
properties.infallibleAppend(id);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Interfaces::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* objArg,
|
|
jsid idArg, bool* resolvedp,
|
|
bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
RootedId id(cx, idArg);
|
|
|
|
if (!JSID_IS_STRING(id))
|
|
return NS_OK;
|
|
|
|
JSAutoByteString name;
|
|
RootedString str(cx, JSID_TO_STRING(id));
|
|
|
|
// we only allow interfaces by name here
|
|
if (name.encodeLatin1(cx, str) && name.ptr()[0] != '{') {
|
|
nsCOMPtr<nsIInterfaceInfo> info =
|
|
ShimInterfaceInfo::MaybeConstruct(name.ptr(), cx);
|
|
if (!info) {
|
|
XPTInterfaceInfoManager::GetSingleton()->
|
|
GetInfoForName(name.ptr(), getter_AddRefs(info));
|
|
}
|
|
if (!info)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
|
|
|
|
if (nsid) {
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
RootedObject idobj(cx);
|
|
if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
|
|
static_cast<nsIJSIID*>(nsid),
|
|
NS_GET_IID(nsIJSIID),
|
|
idobj.address()))) {
|
|
if (idobj) {
|
|
*resolvedp = true;
|
|
*_retval = JS_DefinePropertyById(cx, obj, id, idobj,
|
|
JSPROP_ENUMERATE |
|
|
JSPROP_READONLY |
|
|
JSPROP_PERMANENT |
|
|
JSPROP_RESOLVING);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
|
|
class nsXPCComponents_InterfacesByID final :
|
|
public nsIXPCComponents_InterfacesByID,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
public:
|
|
nsXPCComponents_InterfacesByID();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_InterfacesByID();
|
|
|
|
nsCOMArray<nsIInterfaceInfo> mInterfaces;
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_InterfacesByID)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_InterfacesByID";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::GetFlags(uint32_t* aFlags)
|
|
{
|
|
// Mark ourselves as a DOM object so that instances may be created in
|
|
// unprivileged scopes.
|
|
*aFlags = nsIClassInfo::DOM_OBJECT;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_InterfacesByID::nsXPCComponents_InterfacesByID()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_InterfacesByID::~nsXPCComponents_InterfacesByID()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_InterfacesByID)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_InterfacesByID)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_InterfacesByID)
|
|
NS_IMPL_RELEASE(nsXPCComponents_InterfacesByID)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_InterfacesByID
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_InterfacesByID"
|
|
#define XPC_MAP_WANT_RESOLVE
|
|
#define XPC_MAP_WANT_NEWENUMERATE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* obj,
|
|
JS::AutoIdVector& properties,
|
|
bool* _retval)
|
|
{
|
|
|
|
if (mInterfaces.IsEmpty()) {
|
|
XPTInterfaceInfoManager::GetSingleton()->
|
|
GetScriptableInterfaces(mInterfaces);
|
|
}
|
|
|
|
if (!properties.reserve(mInterfaces.Length())) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
for (uint32_t index = 0; index < mInterfaces.Length(); index++) {
|
|
nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(index);
|
|
if (!interface)
|
|
continue;
|
|
|
|
nsIID const* iid;
|
|
if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
|
|
char idstr[NSID_LENGTH];
|
|
iid->ToProvidedString(idstr);
|
|
RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr));
|
|
if (!jsstr) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
RootedId id(cx);
|
|
if (!JS_StringToId(cx, jsstr, &id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
properties.infallibleAppend(id);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_InterfacesByID::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* objArg,
|
|
jsid idArg, bool* resolvedp,
|
|
bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
RootedId id(cx, idArg);
|
|
|
|
if (!JSID_IS_STRING(id))
|
|
return NS_OK;
|
|
|
|
RootedString str(cx, JSID_TO_STRING(id));
|
|
if (38 != JS_GetStringLength(str))
|
|
return NS_OK;
|
|
|
|
JSAutoByteString utf8str;
|
|
if (utf8str.encodeUtf8(cx, str)) {
|
|
nsID iid;
|
|
if (!iid.Parse(utf8str.ptr()))
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIInterfaceInfo> info;
|
|
XPTInterfaceInfoManager::GetSingleton()->
|
|
GetInfoForIID(&iid, getter_AddRefs(info));
|
|
if (!info)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
|
|
|
|
if (!nsid)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
RootedObject idobj(cx);
|
|
if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
|
|
static_cast<nsIJSIID*>(nsid),
|
|
NS_GET_IID(nsIJSIID),
|
|
idobj.address()))) {
|
|
if (idobj) {
|
|
*resolvedp = true;
|
|
*_retval =
|
|
JS_DefinePropertyById(cx, obj, id, idobj,
|
|
JSPROP_ENUMERATE |
|
|
JSPROP_READONLY |
|
|
JSPROP_PERMANENT |
|
|
JSPROP_RESOLVING);
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
class nsXPCComponents_Classes final :
|
|
public nsIXPCComponents_Classes,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_CLASSES
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
public:
|
|
nsXPCComponents_Classes();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_Classes();
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_Classes)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_Classes";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::GetFlags(uint32_t* aFlags)
|
|
{
|
|
*aFlags = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_Classes::nsXPCComponents_Classes()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_Classes::~nsXPCComponents_Classes()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Classes)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Classes)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Classes)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_Classes)
|
|
NS_IMPL_RELEASE(nsXPCComponents_Classes)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_Classes
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Classes"
|
|
#define XPC_MAP_WANT_RESOLVE
|
|
#define XPC_MAP_WANT_NEWENUMERATE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* obj,
|
|
JS::AutoIdVector& properties,
|
|
bool* _retval)
|
|
{
|
|
nsCOMPtr<nsIComponentRegistrar> compMgr;
|
|
if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr)
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> e;
|
|
if (NS_FAILED(compMgr->EnumerateContractIDs(getter_AddRefs(e))) || !e)
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
bool hasMore;
|
|
nsCOMPtr<nsISupports> isup;
|
|
while(NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
|
|
NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
|
|
nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
|
|
if (!holder)
|
|
continue;
|
|
|
|
nsAutoCString name;
|
|
if (NS_SUCCEEDED(holder->GetData(name))) {
|
|
RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
|
|
if (!idstr) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
RootedId id(cx);
|
|
if (!JS_StringToId(cx, idstr, &id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!properties.append(id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Classes::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* objArg,
|
|
jsid idArg, bool* resolvedp,
|
|
bool* _retval)
|
|
|
|
{
|
|
RootedId id(cx, idArg);
|
|
RootedObject obj(cx, objArg);
|
|
|
|
JSAutoByteString name;
|
|
if (JSID_IS_STRING(id) &&
|
|
name.encodeLatin1(cx, JSID_TO_STRING(id)) &&
|
|
name.ptr()[0] != '{') { // we only allow contractids here
|
|
nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
|
|
if (nsid) {
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
RootedObject idobj(cx);
|
|
if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
|
|
static_cast<nsIJSCID*>(nsid),
|
|
NS_GET_IID(nsIJSCID),
|
|
idobj.address()))) {
|
|
if (idobj) {
|
|
*resolvedp = true;
|
|
*_retval = JS_DefinePropertyById(cx, obj, id, idobj,
|
|
JSPROP_ENUMERATE |
|
|
JSPROP_READONLY |
|
|
JSPROP_PERMANENT |
|
|
JSPROP_RESOLVING);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
|
|
class nsXPCComponents_ClassesByID final :
|
|
public nsIXPCComponents_ClassesByID,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
public:
|
|
nsXPCComponents_ClassesByID();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_ClassesByID();
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_ClassesByID)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_ClassesByID";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::GetFlags(uint32_t* aFlags)
|
|
{
|
|
*aFlags = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_ClassesByID::nsXPCComponents_ClassesByID()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_ClassesByID::~nsXPCComponents_ClassesByID()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ClassesByID)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ClassesByID)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ClassesByID)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_ClassesByID)
|
|
NS_IMPL_RELEASE(nsXPCComponents_ClassesByID)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_ClassesByID
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ClassesByID"
|
|
#define XPC_MAP_WANT_RESOLVE
|
|
#define XPC_MAP_WANT_NEWENUMERATE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* obj,
|
|
JS::AutoIdVector& properties,
|
|
bool* _retval)
|
|
{
|
|
|
|
nsCOMPtr<nsIComponentRegistrar> compMgr;
|
|
if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr)
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
nsISimpleEnumerator* e;
|
|
if (NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e)
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
bool hasMore;
|
|
nsCOMPtr<nsISupports> isup;
|
|
while(NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
|
|
NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
|
|
nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
|
|
if (!holder)
|
|
continue;
|
|
|
|
char* name;
|
|
if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
|
|
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
|
|
if (!idstr) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
RootedId id(cx);
|
|
if (!JS_StringToId(cx, idstr, &id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!properties.append(id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
static bool
|
|
IsRegisteredCLSID(const char* str)
|
|
{
|
|
bool registered;
|
|
nsID id;
|
|
|
|
if (!id.Parse(str))
|
|
return false;
|
|
|
|
nsCOMPtr<nsIComponentRegistrar> compMgr;
|
|
if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
|
|
NS_FAILED(compMgr->IsCIDRegistered(id, ®istered)))
|
|
return false;
|
|
|
|
return registered;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ClassesByID::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* objArg,
|
|
jsid idArg, bool* resolvedp,
|
|
bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
RootedId id(cx, idArg);
|
|
|
|
if (!JSID_IS_STRING(id))
|
|
return NS_OK;
|
|
|
|
JSAutoByteString name;
|
|
RootedString str(cx, JSID_TO_STRING(id));
|
|
if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' &&
|
|
IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
|
|
{
|
|
nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
|
|
if (nsid) {
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
RootedObject idobj(cx);
|
|
if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
|
|
static_cast<nsIJSCID*>(nsid),
|
|
NS_GET_IID(nsIJSCID),
|
|
idobj.address()))) {
|
|
if (idobj) {
|
|
*resolvedp = true;
|
|
*_retval = JS_DefinePropertyById(cx, obj, id, idobj,
|
|
JSPROP_ENUMERATE |
|
|
JSPROP_READONLY |
|
|
JSPROP_PERMANENT |
|
|
JSPROP_RESOLVING);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
// Currently the possible results do not change at runtime, so they are only
|
|
// cached once (unlike ContractIDs, CLSIDs, and IIDs)
|
|
|
|
class nsXPCComponents_Results final :
|
|
public nsIXPCComponents_Results,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_RESULTS
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
public:
|
|
nsXPCComponents_Results();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_Results();
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_Results)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_Results";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::GetFlags(uint32_t* aFlags)
|
|
{
|
|
// Mark ourselves as a DOM object so that instances may be created in
|
|
// unprivileged scopes.
|
|
*aFlags = nsIClassInfo::DOM_OBJECT;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_Results::nsXPCComponents_Results()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_Results::~nsXPCComponents_Results()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Results)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Results)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Results)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_Results)
|
|
NS_IMPL_RELEASE(nsXPCComponents_Results)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_Results
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Results"
|
|
#define XPC_MAP_WANT_RESOLVE
|
|
#define XPC_MAP_WANT_NEWENUMERATE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* obj,
|
|
JS::AutoIdVector& properties,
|
|
bool* _retval)
|
|
{
|
|
const char* name;
|
|
const void* iter = nullptr;
|
|
while (nsXPCException::IterateNSResults(nullptr, &name, nullptr, &iter)) {
|
|
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
|
|
if (!idstr) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
RootedId id(cx);
|
|
if (!JS_StringToId(cx, idstr, &id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!properties.append(id)) {
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Results::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* objArg,
|
|
jsid idArg, bool* resolvedp,
|
|
bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
RootedId id(cx, idArg);
|
|
JSAutoByteString name;
|
|
|
|
if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) {
|
|
const char* rv_name;
|
|
const void* iter = nullptr;
|
|
nsresult rv;
|
|
while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) {
|
|
if (!strcmp(name.ptr(), rv_name)) {
|
|
*resolvedp = true;
|
|
if (!JS_DefinePropertyById(cx, obj, id, (uint32_t)rv,
|
|
JSPROP_ENUMERATE |
|
|
JSPROP_READONLY |
|
|
JSPROP_PERMANENT |
|
|
JSPROP_RESOLVING)) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
// JavaScript Constructor for nsIJSID objects (Components.ID)
|
|
|
|
class nsXPCComponents_ID final :
|
|
public nsIXPCComponents_ID,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_ID
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
|
|
public:
|
|
nsXPCComponents_ID();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_ID();
|
|
static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, HandleObject obj,
|
|
const CallArgs& args, bool* _retval);
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_ID)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_ID";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::GetFlags(uint32_t* aFlags)
|
|
{
|
|
*aFlags = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_ID::nsXPCComponents_ID()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_ID::~nsXPCComponents_ID()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ID)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ID)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ID)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_ID)
|
|
NS_IMPL_RELEASE(nsXPCComponents_ID)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_ID
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ID"
|
|
#define XPC_MAP_WANT_CALL
|
|
#define XPC_MAP_WANT_CONSTRUCT
|
|
#define XPC_MAP_WANT_HASINSTANCE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
}
|
|
|
|
// static
|
|
nsresult
|
|
nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, HandleObject obj,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
// make sure we have at least one arg
|
|
|
|
if (args.length() < 1)
|
|
return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
|
|
|
|
// Do the security check if necessary
|
|
|
|
if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(cx, nsJSID::GetCID()))) {
|
|
// the security manager vetoed. It should have set an exception.
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
// convert the first argument into a string and see if it looks like an id
|
|
|
|
JSString* jsstr;
|
|
JSAutoByteString bytes;
|
|
nsID id;
|
|
|
|
if (!(jsstr = ToString(cx, args[0])) ||
|
|
!bytes.encodeLatin1(cx, jsstr) ||
|
|
!id.Parse(bytes.ptr())) {
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
|
|
}
|
|
|
|
// make the new object and return it.
|
|
|
|
JSObject* newobj = xpc_NewIDObject(cx, obj, id);
|
|
if (!newobj)
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
args.rval().setObject(*newobj);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, JSObject* obj,
|
|
HandleValue val, bool* bp, bool* _retval)
|
|
{
|
|
if (bp)
|
|
*bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIJSID));
|
|
return NS_OK;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
// JavaScript Constructor for nsIXPCException objects (Components.Exception)
|
|
|
|
class nsXPCComponents_Exception final :
|
|
public nsIXPCComponents_Exception,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
|
|
public:
|
|
nsXPCComponents_Exception();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_Exception();
|
|
static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, HandleObject obj,
|
|
const CallArgs& args, bool* _retval);
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_Exception)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_Exception";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::GetFlags(uint32_t* aFlags)
|
|
{
|
|
*aFlags = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_Exception::nsXPCComponents_Exception()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_Exception::~nsXPCComponents_Exception()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Exception)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Exception)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Exception)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_Exception)
|
|
NS_IMPL_RELEASE(nsXPCComponents_Exception)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_Exception
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Exception"
|
|
#define XPC_MAP_WANT_CALL
|
|
#define XPC_MAP_WANT_CONSTRUCT
|
|
#define XPC_MAP_WANT_HASINSTANCE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
|
|
JSObject* objArg, const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
}
|
|
|
|
struct MOZ_STACK_CLASS ExceptionArgParser
|
|
{
|
|
ExceptionArgParser(JSContext* context,
|
|
nsXPConnect* xpconnect)
|
|
: eMsg("exception")
|
|
, eResult(NS_ERROR_FAILURE)
|
|
, cx(context)
|
|
, xpc(xpconnect)
|
|
{}
|
|
|
|
// Public exception parameter values. During construction, these are
|
|
// initialized to the appropriate defaults.
|
|
const char* eMsg;
|
|
nsresult eResult;
|
|
nsCOMPtr<nsIStackFrame> eStack;
|
|
nsCOMPtr<nsISupports> eData;
|
|
|
|
// Parse the constructor arguments into the above |eFoo| parameter values.
|
|
bool parse(const CallArgs& args) {
|
|
/*
|
|
* The Components.Exception takes a series of arguments, all of them
|
|
* optional:
|
|
*
|
|
* Argument 0: Exception message (defaults to 'exception').
|
|
* Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options
|
|
* object (see below).
|
|
* Argument 2: Stack (defaults to the current stack, which we trigger
|
|
* by leaving this nullptr in the parser).
|
|
* Argument 3: Optional user data (defaults to nullptr).
|
|
*
|
|
* To dig our way out of this clunky API, we now support passing an
|
|
* options object as the second parameter (as opposed to a result code).
|
|
* If this is the case, all subsequent arguments are ignored, and the
|
|
* following properties are parsed out of the object (using the
|
|
* associated default if the property does not exist):
|
|
*
|
|
* result: Result code (see argument 1).
|
|
* stack: Call stack (see argument 2).
|
|
* data: User data (see argument 3).
|
|
*/
|
|
if (args.length() > 0 && !parseMessage(args[0]))
|
|
return false;
|
|
if (args.length() > 1) {
|
|
if (args[1].isObject()) {
|
|
RootedObject obj(cx, &args[1].toObject());
|
|
return parseOptionsObject(obj);
|
|
}
|
|
if (!parseResult(args[1]))
|
|
return false;
|
|
}
|
|
if (args.length() > 2) {
|
|
if (!parseStack(args[2]))
|
|
return false;
|
|
}
|
|
if (args.length() > 3) {
|
|
if (!parseData(args[3]))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
protected:
|
|
|
|
/*
|
|
* Parsing helpers.
|
|
*/
|
|
|
|
bool parseMessage(HandleValue v) {
|
|
JSString* str = ToString(cx, v);
|
|
if (!str)
|
|
return false;
|
|
eMsg = messageBytes.encodeLatin1(cx, str);
|
|
return !!eMsg;
|
|
}
|
|
|
|
bool parseResult(HandleValue v) {
|
|
return JS::ToUint32(cx, v, (uint32_t*) &eResult);
|
|
}
|
|
|
|
bool parseStack(HandleValue v) {
|
|
if (!v.isObject()) {
|
|
// eStack has already been initialized to null, which is what we want
|
|
// for any non-object values (including null).
|
|
return true;
|
|
}
|
|
|
|
return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
|
|
NS_GET_IID(nsIStackFrame),
|
|
getter_AddRefs(eStack)));
|
|
}
|
|
|
|
bool parseData(HandleValue v) {
|
|
if (!v.isObject()) {
|
|
// eData has already been initialized to null, which is what we want
|
|
// for any non-object values (including null).
|
|
return true;
|
|
}
|
|
|
|
return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
|
|
NS_GET_IID(nsISupports),
|
|
getter_AddRefs(eData)));
|
|
}
|
|
|
|
bool parseOptionsObject(HandleObject obj) {
|
|
RootedValue v(cx);
|
|
|
|
if (!getOption(obj, "result", &v) ||
|
|
(!v.isUndefined() && !parseResult(v)))
|
|
return false;
|
|
|
|
if (!getOption(obj, "stack", &v) ||
|
|
(!v.isUndefined() && !parseStack(v)))
|
|
return false;
|
|
|
|
if (!getOption(obj, "data", &v) ||
|
|
(!v.isUndefined() && !parseData(v)))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool getOption(HandleObject obj, const char* name, MutableHandleValue rv) {
|
|
// Look for the property.
|
|
bool found;
|
|
if (!JS_HasProperty(cx, obj, name, &found))
|
|
return false;
|
|
|
|
// If it wasn't found, indicate with undefined.
|
|
if (!found) {
|
|
rv.setUndefined();
|
|
return true;
|
|
}
|
|
|
|
// Get the property.
|
|
return JS_GetProperty(cx, obj, name, rv);
|
|
}
|
|
|
|
/*
|
|
* Internal data members.
|
|
*/
|
|
|
|
// If there's a non-default exception string, hold onto the allocated bytes.
|
|
JSAutoByteString messageBytes;
|
|
|
|
// Various bits and pieces that are helpful to have around.
|
|
JSContext* cx;
|
|
nsXPConnect* xpc;
|
|
};
|
|
|
|
// static
|
|
nsresult
|
|
nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, HandleObject obj,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
|
|
// Do the security check if necessary
|
|
|
|
if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(cx, Exception::GetCID()))) {
|
|
// the security manager vetoed. It should have set an exception.
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
// Parse the arguments to the Exception constructor.
|
|
ExceptionArgParser parser(cx, xpc);
|
|
if (!parser.parse(args))
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
|
|
|
|
nsCOMPtr<nsIException> e = new Exception(nsCString(parser.eMsg),
|
|
parser.eResult,
|
|
EmptyCString(),
|
|
parser.eStack,
|
|
parser.eData);
|
|
|
|
RootedObject newObj(cx);
|
|
if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException), newObj.address())) || !newObj) {
|
|
return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
|
|
}
|
|
|
|
args.rval().setObject(*newObj);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext * cx, JSObject * obj,
|
|
HandleValue val, bool* bp,
|
|
bool* _retval)
|
|
{
|
|
using namespace mozilla::dom;
|
|
|
|
RootedValue v(cx, val);
|
|
if (bp) {
|
|
Exception* e;
|
|
*bp = NS_SUCCEEDED(UNWRAP_OBJECT(Exception, v.toObjectOrNull(), e)) ||
|
|
JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException));
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
// This class is for the thing returned by "new Component.Constructor".
|
|
|
|
// XXXjband we use this CID for security check, but security system can't see
|
|
// it since it has no registed factory. Security really kicks in when we try
|
|
// to build a wrapper around an instance.
|
|
|
|
// {B4A95150-E25A-11d3-8F61-0010A4E73D9A}
|
|
#define NS_XPCCONSTRUCTOR_CID \
|
|
{ 0xb4a95150, 0xe25a, 0x11d3, \
|
|
{ 0x8f, 0x61, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
|
|
|
|
class nsXPCConstructor :
|
|
public nsIXPCConstructor,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID)
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCONSTRUCTOR
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
public:
|
|
nsXPCConstructor(); // not implemented
|
|
nsXPCConstructor(nsIJSCID* aClassID,
|
|
nsIJSIID* aInterfaceID,
|
|
const char* aInitializer);
|
|
|
|
private:
|
|
virtual ~nsXPCConstructor();
|
|
nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, HandleObject obj,
|
|
const CallArgs& args, bool* _retval);
|
|
private:
|
|
RefPtr<nsIJSCID> mClassID;
|
|
RefPtr<nsIJSIID> mInterfaceID;
|
|
char* mInitializer;
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCConstructor)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCConstructor";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetFlags(uint32_t* aFlags)
|
|
{
|
|
*aFlags = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCConstructor::nsXPCConstructor(nsIJSCID* aClassID,
|
|
nsIJSIID* aInterfaceID,
|
|
const char* aInitializer)
|
|
: mClassID(aClassID),
|
|
mInterfaceID(aInterfaceID)
|
|
{
|
|
mInitializer = aInitializer ?
|
|
(char*) nsMemory::Clone(aInitializer, strlen(aInitializer)+1) :
|
|
nullptr;
|
|
}
|
|
|
|
nsXPCConstructor::~nsXPCConstructor()
|
|
{
|
|
if (mInitializer)
|
|
free(mInitializer);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetClassID(nsIJSCID * *aClassID)
|
|
{
|
|
RefPtr<nsIJSCID> rval = mClassID;
|
|
rval.forget(aClassID);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetInterfaceID(nsIJSIID * *aInterfaceID)
|
|
{
|
|
RefPtr<nsIJSIID> rval = mInterfaceID;
|
|
rval.forget(aInterfaceID);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::GetInitializer(char * *aInitializer)
|
|
{
|
|
XPC_STRING_GETTER_BODY(aInitializer, mInitializer);
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCConstructor)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCConstructor)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCConstructor)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCConstructor)
|
|
NS_IMPL_RELEASE(nsXPCConstructor)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCConstructor
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCConstructor"
|
|
#define XPC_MAP_WANT_CALL
|
|
#define XPC_MAP_WANT_CONSTRUCT
|
|
#define XPC_MAP_FLAGS 0
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCConstructor::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
}
|
|
|
|
// static
|
|
nsresult
|
|
nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,JSContext* cx,
|
|
HandleObject obj, const CallArgs& args, bool* _retval)
|
|
{
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
|
|
// security check not required because we are going to call through the
|
|
// code which is reflected into JS which will do that for us later.
|
|
|
|
RootedObject cidObj(cx);
|
|
RootedObject iidObj(cx);
|
|
|
|
if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID), cidObj.address())) || !cidObj ||
|
|
NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID), iidObj.address())) || !iidObj) {
|
|
return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
|
|
}
|
|
|
|
JS::Rooted<JS::Value> arg(cx, ObjectValue(*iidObj));
|
|
RootedValue rval(cx);
|
|
if (!JS_CallFunctionName(cx, cidObj, "createInstance", JS::HandleValueArray(arg), &rval) ||
|
|
rval.isPrimitive()) {
|
|
// createInstance will have thrown an exception
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
args.rval().set(rval);
|
|
|
|
// call initializer method if supplied
|
|
if (mInitializer) {
|
|
RootedObject newObj(cx, &rval.toObject());
|
|
// first check existence of function property for better error reporting
|
|
RootedValue fun(cx);
|
|
if (!JS_GetProperty(cx, newObj, mInitializer, &fun) ||
|
|
fun.isPrimitive()) {
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_INITIALIZER_NAME, cx, _retval);
|
|
}
|
|
|
|
RootedValue dummy(cx);
|
|
if (!JS_CallFunctionValue(cx, newObj, fun, args, &dummy)) {
|
|
// function should have thrown an exception
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/*******************************************************/
|
|
// JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
|
|
|
|
class nsXPCComponents_Constructor final :
|
|
public nsIXPCComponents_Constructor,
|
|
public nsIXPCScriptable,
|
|
public nsIClassInfo
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
public:
|
|
nsXPCComponents_Constructor();
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_Constructor();
|
|
static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, HandleObject obj,
|
|
const CallArgs& args, bool* _retval);
|
|
};
|
|
|
|
/***************************************************************************/
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::GetInterfaces(uint32_t* aCount, nsIID * **aArray)
|
|
{
|
|
const uint32_t count = 2;
|
|
*aCount = count;
|
|
nsIID** array;
|
|
*aArray = array = static_cast<nsIID**>(moz_xmalloc(count * sizeof(nsIID*)));
|
|
if (!array)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
uint32_t index = 0;
|
|
nsIID* clone;
|
|
#define PUSH_IID(id) \
|
|
clone = static_cast<nsIID*>(nsMemory::Clone(&NS_GET_IID( id ), \
|
|
sizeof(nsIID))); \
|
|
if (!clone) \
|
|
goto oom; \
|
|
array[index++] = clone;
|
|
|
|
PUSH_IID(nsIXPCComponents_Constructor)
|
|
PUSH_IID(nsIXPCScriptable)
|
|
#undef PUSH_IID
|
|
|
|
return NS_OK;
|
|
oom:
|
|
while (index)
|
|
free(array[--index]);
|
|
free(array);
|
|
*aArray = nullptr;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::GetScriptableHelper(nsIXPCScriptable** retval)
|
|
{
|
|
*retval = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::GetContractID(char * *aContractID)
|
|
{
|
|
*aContractID = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::GetClassDescription(char * *aClassDescription)
|
|
{
|
|
static const char classDescription[] = "XPCComponents_Constructor";
|
|
*aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
|
|
return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::GetClassID(nsCID * *aClassID)
|
|
{
|
|
*aClassID = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::GetFlags(uint32_t* aFlags)
|
|
{
|
|
*aFlags = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
nsXPCComponents_Constructor::nsXPCComponents_Constructor()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents_Constructor::~nsXPCComponents_Constructor()
|
|
{
|
|
// empty
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Constructor)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Constructor)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Constructor)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_Constructor)
|
|
NS_IMPL_RELEASE(nsXPCComponents_Constructor)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_Constructor
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Constructor"
|
|
#define XPC_MAP_WANT_CALL
|
|
#define XPC_MAP_WANT_CONSTRUCT
|
|
#define XPC_MAP_WANT_HASINSTANCE
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
|
|
JSObject* objArg, const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
|
|
JSObject* objArg, const CallArgs& args, bool* _retval)
|
|
{
|
|
RootedObject obj(cx, objArg);
|
|
return CallOrConstruct(wrapper, cx, obj, args, _retval);
|
|
}
|
|
|
|
// static
|
|
nsresult
|
|
nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext* cx, HandleObject obj,
|
|
const CallArgs& args, bool* _retval)
|
|
{
|
|
// make sure we have at least one arg
|
|
|
|
if (args.length() < 1)
|
|
return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
|
|
|
|
// get the various other object pointers we need
|
|
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
XPCWrappedNativeScope* scope = ObjectScope(obj);
|
|
nsCOMPtr<nsIXPCComponents> comp;
|
|
|
|
if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents())))
|
|
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
|
|
|
// Do the security check if necessary
|
|
|
|
if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(cx, nsXPCConstructor::GetCID()))) {
|
|
// the security manager vetoed. It should have set an exception.
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
// initialization params for the Constructor object we will create
|
|
nsCOMPtr<nsIJSCID> cClassID;
|
|
nsCOMPtr<nsIJSIID> cInterfaceID;
|
|
const char* cInitializer = nullptr;
|
|
JSAutoByteString cInitializerBytes;
|
|
|
|
if (args.length() >= 3) {
|
|
// args[2] is an initializer function or property name
|
|
RootedString str(cx, ToString(cx, args[2]));
|
|
if (!str || !(cInitializer = cInitializerBytes.encodeLatin1(cx, str)))
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
|
|
}
|
|
|
|
if (args.length() >= 2) {
|
|
// args[1] is an iid name string
|
|
// XXXjband support passing "Components.interfaces.foo"?
|
|
|
|
nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
|
|
RootedObject ifacesObj(cx);
|
|
|
|
// we do the lookup by asking the Components.interfaces object
|
|
// for the property with this name - i.e. we let its caching of these
|
|
// nsIJSIID objects work for us.
|
|
|
|
if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
|
|
NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
|
|
NS_GET_IID(nsIXPCComponents_Interfaces),
|
|
ifacesObj.address())) || !ifacesObj) {
|
|
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
|
}
|
|
|
|
RootedString str(cx, ToString(cx, args[1]));
|
|
RootedId id(cx);
|
|
if (!str || !JS_StringToId(cx, str, &id))
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
|
|
|
|
RootedValue val(cx);
|
|
if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive())
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
|
|
|
|
nsCOMPtr<nsIXPConnectWrappedNative> wn;
|
|
if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(),
|
|
getter_AddRefs(wn))) || !wn ||
|
|
!(cInterfaceID = do_QueryWrappedNative(wn))) {
|
|
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
|
}
|
|
} else {
|
|
nsCOMPtr<nsIInterfaceInfo> info;
|
|
xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info));
|
|
|
|
if (info) {
|
|
cInterfaceID = nsJSIID::NewID(info);
|
|
}
|
|
if (!cInterfaceID)
|
|
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
|
}
|
|
|
|
// a new scope to avoid warnings about shadowed names
|
|
{
|
|
// argv[0] is a contractid name string
|
|
// XXXjband support passing "Components.classes.foo"?
|
|
|
|
// we do the lookup by asking the Components.classes object
|
|
// for the property with this name - i.e. we let its caching of these
|
|
// nsIJSCID objects work for us.
|
|
|
|
nsCOMPtr<nsIXPCComponents_Classes> classes;
|
|
RootedObject classesObj(cx);
|
|
|
|
if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
|
|
NS_FAILED(xpc->WrapNative(cx, obj, classes,
|
|
NS_GET_IID(nsIXPCComponents_Classes),
|
|
classesObj.address())) || !classesObj) {
|
|
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
|
}
|
|
|
|
RootedString str(cx, ToString(cx, args[0]));
|
|
RootedId id(cx);
|
|
if (!str || !JS_StringToId(cx, str, &id))
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
|
|
|
|
RootedValue val(cx);
|
|
if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive())
|
|
return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
|
|
|
|
nsCOMPtr<nsIXPConnectWrappedNative> wn;
|
|
if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, val.toObjectOrNull(),
|
|
getter_AddRefs(wn))) || !wn ||
|
|
!(cClassID = do_QueryWrappedNative(wn))) {
|
|
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
|
}
|
|
}
|
|
|
|
nsCOMPtr<nsIXPCConstructor> ctor = new nsXPCConstructor(cClassID, cInterfaceID, cInitializer);
|
|
RootedObject newObj(cx);
|
|
|
|
if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor), newObj.address())) || !newObj) {
|
|
return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
|
|
}
|
|
|
|
args.rval().setObject(*newObj);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative* wrapper,
|
|
JSContext * cx, JSObject * obj,
|
|
HandleValue val, bool* bp,
|
|
bool* _retval)
|
|
{
|
|
if (bp)
|
|
*bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIXPCConstructor));
|
|
return NS_OK;
|
|
}
|
|
|
|
class nsXPCComponents_Utils final :
|
|
public nsIXPCComponents_Utils,
|
|
public nsIXPCScriptable
|
|
{
|
|
public:
|
|
// all the interface method declarations...
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
NS_DECL_NSIXPCCOMPONENTS_UTILS
|
|
|
|
public:
|
|
nsXPCComponents_Utils() { }
|
|
|
|
private:
|
|
virtual ~nsXPCComponents_Utils() { }
|
|
nsCOMPtr<nsIXPCComponents_utils_Sandbox> mSandbox;
|
|
};
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF(nsXPCComponents_Utils)
|
|
NS_IMPL_RELEASE(nsXPCComponents_Utils)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us...
|
|
#define XPC_MAP_CLASSNAME nsXPCComponents_Utils
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Utils"
|
|
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox** aSandbox)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSandbox);
|
|
if (!mSandbox)
|
|
mSandbox = NewSandboxConstructor();
|
|
|
|
nsCOMPtr<nsIXPCComponents_utils_Sandbox> rval = mSandbox;
|
|
rval.forget(aSandbox);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ReportError(HandleValue error, JSContext* cx)
|
|
{
|
|
// This function shall never fail! Silently eat any failure conditions.
|
|
|
|
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
|
|
|
nsCOMPtr<nsIScriptError> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
|
|
|
|
if (!scripterr || !console)
|
|
return NS_OK;
|
|
|
|
const uint64_t innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
|
|
|
|
RootedObject errorObj(cx, error.isObject() ? &error.toObject() : nullptr);
|
|
JSErrorReport* err = errorObj ? JS_ErrorFromException(cx, errorObj) : nullptr;
|
|
if (err) {
|
|
// It's a proper JS Error
|
|
nsAutoString fileUni;
|
|
CopyUTF8toUTF16(err->filename, fileUni);
|
|
|
|
uint32_t column = err->tokenOffset();
|
|
|
|
const char16_t* ucmessage = err->ucmessage;
|
|
const char16_t* linebuf = err->linebuf();
|
|
|
|
nsresult rv = scripterr->InitWithWindowID(
|
|
ucmessage ? nsDependentString(ucmessage) : EmptyString(),
|
|
fileUni,
|
|
linebuf ? nsDependentString(linebuf, err->linebufLength()) : EmptyString(),
|
|
err->lineno,
|
|
column, err->flags, "XPConnect JavaScript", innerWindowID);
|
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
|
|
|
console->LogMessage(scripterr);
|
|
return NS_OK;
|
|
}
|
|
|
|
// It's not a JS Error object, so we synthesize as best we're able.
|
|
RootedString msgstr(cx, ToString(cx, error));
|
|
if (!msgstr)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIStackFrame> frame;
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
xpc->GetCurrentJSStack(getter_AddRefs(frame));
|
|
|
|
nsString fileName;
|
|
int32_t lineNo = 0;
|
|
if (frame) {
|
|
frame->GetFilename(fileName);
|
|
frame->GetLineNumber(&lineNo);
|
|
}
|
|
|
|
nsAutoJSString msg;
|
|
if (!msg.init(cx, msgstr))
|
|
return NS_OK;
|
|
|
|
nsresult rv = scripterr->InitWithWindowID(
|
|
msg, fileName, EmptyString(), lineNo, 0, 0,
|
|
"XPConnect JavaScript", innerWindowID);
|
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
|
|
|
console->LogMessage(scripterr);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
|
|
HandleValue sandboxVal,
|
|
HandleValue version,
|
|
const nsACString& filenameArg,
|
|
int32_t lineNumber,
|
|
JSContext* cx,
|
|
uint8_t optionalArgc,
|
|
MutableHandleValue retval)
|
|
{
|
|
RootedObject sandbox(cx);
|
|
if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox)
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
// Optional third argument: JS version, as a string.
|
|
JSVersion jsVersion = JSVERSION_DEFAULT;
|
|
if (optionalArgc >= 1) {
|
|
JSString* jsVersionStr = ToString(cx, version);
|
|
if (!jsVersionStr)
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
JSAutoByteString bytes(cx, jsVersionStr);
|
|
if (!bytes)
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
jsVersion = JS_StringToVersion(bytes.ptr());
|
|
// Explicitly check for "latest", which we support for sandboxes but
|
|
// isn't in the set of web-exposed version strings.
|
|
if (jsVersion == JSVERSION_UNKNOWN &&
|
|
!strcmp(bytes.ptr(), "latest"))
|
|
{
|
|
jsVersion = JSVERSION_LATEST;
|
|
}
|
|
if (jsVersion == JSVERSION_UNKNOWN)
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
// Optional fourth and fifth arguments: filename and line number.
|
|
int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1;
|
|
nsCString filename;
|
|
if (!filenameArg.IsVoid()) {
|
|
filename.Assign(filenameArg);
|
|
} else {
|
|
// Get the current source info from xpc.
|
|
nsresult rv;
|
|
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIStackFrame> frame;
|
|
xpc->GetCurrentJSStack(getter_AddRefs(frame));
|
|
if (frame) {
|
|
nsString frameFile;
|
|
frame->GetFilename(frameFile);
|
|
CopyUTF16toUTF8(frameFile, filename);
|
|
frame->GetLineNumber(&lineNo);
|
|
}
|
|
}
|
|
|
|
return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo,
|
|
jsVersion, retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetSandboxAddonId(HandleValue sandboxVal,
|
|
JSContext* cx, MutableHandleValue rval)
|
|
{
|
|
if (!sandboxVal.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
RootedObject sandbox(cx, &sandboxVal.toObject());
|
|
sandbox = js::CheckedUnwrap(sandbox);
|
|
if (!sandbox || !xpc::IsSandbox(sandbox))
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
return xpc::GetSandboxAddonId(cx, sandbox, rval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal,
|
|
JSContext* cx, MutableHandleValue rval)
|
|
{
|
|
if (!sandboxVal.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
RootedObject sandbox(cx, &sandboxVal.toObject());
|
|
sandbox = js::CheckedUnwrap(sandbox);
|
|
if (!sandbox || !xpc::IsSandbox(sandbox))
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
return xpc::GetSandboxMetadata(cx, sandbox, rval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal,
|
|
HandleValue metadataVal,
|
|
JSContext* cx)
|
|
{
|
|
if (!sandboxVal.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
RootedObject sandbox(cx, &sandboxVal.toObject());
|
|
sandbox = js::CheckedUnwrap(sandbox);
|
|
if (!sandbox || !xpc::IsSandbox(sandbox))
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadataVal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::Import(const nsACString& registryLocation,
|
|
HandleValue targetObj,
|
|
JSContext* cx,
|
|
uint8_t optionalArgc,
|
|
MutableHandleValue retval)
|
|
{
|
|
nsCOMPtr<xpcIJSModuleLoader> moduleloader =
|
|
do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
|
|
if (!moduleloader)
|
|
return NS_ERROR_FAILURE;
|
|
return moduleloader->Import(registryLocation, targetObj, cx, optionalArgc, retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::IsModuleLoaded(const nsACString& registryLocation, bool* retval)
|
|
{
|
|
nsCOMPtr<xpcIJSModuleLoader> moduleloader =
|
|
do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
|
|
if (!moduleloader)
|
|
return NS_ERROR_FAILURE;
|
|
return moduleloader->IsModuleLoaded(registryLocation, retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::Unload(const nsACString & registryLocation)
|
|
{
|
|
nsCOMPtr<xpcIJSModuleLoader> moduleloader =
|
|
do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
|
|
if (!moduleloader)
|
|
return NS_ERROR_FAILURE;
|
|
return moduleloader->Unload(registryLocation);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
|
|
JSContext* cx)
|
|
{
|
|
RootedObject global(cx, CurrentGlobalOrNull(cx));
|
|
MOZ_ASSERT(global);
|
|
|
|
// Don't allow doing this if the global is a Window
|
|
nsGlobalWindow* win;
|
|
if (NS_SUCCEEDED(UNWRAP_OBJECT(Window, global, win))) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
GlobalProperties options;
|
|
NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
|
|
|
|
RootedObject propertyList(cx, &aPropertyList.toObject());
|
|
bool isArray;
|
|
if (NS_WARN_IF(!JS_IsArrayObject(cx, propertyList, &isArray))) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
if (NS_WARN_IF(!isArray)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
if (!options.Parse(cx, propertyList) ||
|
|
!options.Define(cx, global))
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext* cx,
|
|
xpcIJSWeakReference** _retval)
|
|
{
|
|
RefPtr<xpcJSWeakReference> ref = new xpcJSWeakReference();
|
|
nsresult rv = ref->Init(cx, object);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
ref.forget(_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ForceGC()
|
|
{
|
|
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
|
PrepareForFullGC(rt);
|
|
GCForReason(rt, GC_NORMAL, gcreason::COMPONENT_UTILS);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ForceCC(nsICycleCollectorListener* listener)
|
|
{
|
|
nsJSContext::CycleCollectNow(listener);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::FinishCC()
|
|
{
|
|
nsCycleCollector_finishAnyCurrentCollection();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::CcSlice(int64_t budget)
|
|
{
|
|
nsJSContext::RunCycleCollectorWorkSlice(budget);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetMaxCCSliceTimeSinceClear(int32_t* out)
|
|
{
|
|
*out = nsJSContext::GetMaxCCSliceTimeSinceClear();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ClearMaxCCTime()
|
|
{
|
|
nsJSContext::ClearMaxCCSliceTime();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ForceShrinkingGC()
|
|
{
|
|
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
|
PrepareForFullGC(rt);
|
|
GCForReason(rt, GC_SHRINK, gcreason::COMPONENT_UTILS);
|
|
return NS_OK;
|
|
}
|
|
|
|
class PreciseGCRunnable : public nsRunnable
|
|
{
|
|
public:
|
|
PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking)
|
|
: mCallback(aCallback), mShrinking(aShrinking) {}
|
|
|
|
NS_IMETHOD Run()
|
|
{
|
|
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
|
|
|
JSContext* cx;
|
|
JSContext* iter = nullptr;
|
|
while ((cx = JS_ContextIterator(rt, &iter)) != nullptr) {
|
|
if (JS_IsRunning(cx)) {
|
|
return NS_DispatchToMainThread(this);
|
|
}
|
|
}
|
|
|
|
nsJSContext::GarbageCollectNow(gcreason::COMPONENT_UTILS,
|
|
nsJSContext::NonIncrementalGC,
|
|
mShrinking ?
|
|
nsJSContext::ShrinkingGC :
|
|
nsJSContext::NonShrinkingGC);
|
|
|
|
mCallback->Callback();
|
|
return NS_OK;
|
|
}
|
|
|
|
private:
|
|
RefPtr<ScheduledGCCallback> mCallback;
|
|
bool mShrinking;
|
|
};
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback)
|
|
{
|
|
RefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, false);
|
|
return NS_DispatchToMainThread(event);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback)
|
|
{
|
|
RefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, true);
|
|
return NS_DispatchToMainThread(event);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::UnlinkGhostWindows()
|
|
{
|
|
#ifdef DEBUG
|
|
nsWindowMemoryReporter::UnlinkGhostWindows();
|
|
return NS_OK;
|
|
#else
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
#endif
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetJSTestingFunctions(JSContext* cx,
|
|
MutableHandleValue retval)
|
|
{
|
|
JSObject* obj = js::GetTestingFunctions(cx);
|
|
if (!obj)
|
|
return NS_ERROR_XPC_JAVASCRIPT_ERROR;
|
|
retval.setObject(*obj);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::CallFunctionWithAsyncStack(HandleValue function,
|
|
nsIStackFrame* stack,
|
|
const nsAString& asyncCause,
|
|
JSContext* cx,
|
|
MutableHandleValue retval)
|
|
{
|
|
nsresult rv;
|
|
|
|
if (!stack || asyncCause.IsEmpty()) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
JS::Rooted<JS::Value> asyncStack(cx);
|
|
rv = stack->GetNativeSavedFrame(&asyncStack);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (!asyncStack.isObject()) {
|
|
JS_ReportError(cx, "Must use a native JavaScript stack frame");
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
JS::Rooted<JSObject*> asyncStackObj(cx, &asyncStack.toObject());
|
|
JS::Rooted<JSString*> asyncCauseString(cx, JS_NewUCStringCopyN(cx, asyncCause.BeginReading(),
|
|
asyncCause.Length()));
|
|
if (!asyncCauseString)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
JS::AutoSetAsyncStackForNewCalls sas(cx, asyncStackObj, asyncCauseString,
|
|
JS::AutoSetAsyncStackForNewCalls::AsyncCallKind::EXPLICIT);
|
|
|
|
if (!JS_CallFunctionValue(cx, nullptr, function,
|
|
JS::HandleValueArray::empty(), retval))
|
|
{
|
|
return NS_ERROR_XPC_JAVASCRIPT_ERROR;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetGlobalForObject(HandleValue object,
|
|
JSContext* cx,
|
|
MutableHandleValue retval)
|
|
{
|
|
// First argument must be an object.
|
|
if (object.isPrimitive())
|
|
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
|
|
|
// Wrappers are parented to their the global in their home compartment. But
|
|
// when getting the global for a cross-compartment wrapper, we really want
|
|
// a wrapper for the foreign global. So we need to unwrap before getting the
|
|
// parent, enter the compartment for the duration of the call, and wrap the
|
|
// result.
|
|
Rooted<JSObject*> obj(cx, &object.toObject());
|
|
obj = js::UncheckedUnwrap(obj);
|
|
{
|
|
JSAutoCompartment ac(cx, obj);
|
|
obj = JS_GetGlobalForObject(cx, obj);
|
|
}
|
|
|
|
if (!JS_WrapObject(cx, &obj))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Get the WindowProxy if necessary.
|
|
obj = js::ToWindowProxyIfWindow(obj);
|
|
|
|
retval.setObject(*obj);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext* cx, bool* rval)
|
|
{
|
|
if (!vobj.isObject()) {
|
|
*rval = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
RootedObject obj(cx, &vobj.toObject());
|
|
obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
|
|
NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
|
|
|
|
*rval = js::IsScriptedProxy(obj);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ExportFunction(HandleValue vfunction, HandleValue vscope,
|
|
HandleValue voptions, JSContext* cx,
|
|
MutableHandleValue rval)
|
|
{
|
|
if (!xpc::ExportFunction(cx, vfunction, vscope, voptions, rval))
|
|
return NS_ERROR_FAILURE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::CreateObjectIn(HandleValue vobj, HandleValue voptions,
|
|
JSContext* cx, MutableHandleValue rval)
|
|
{
|
|
RootedObject optionsObject(cx, voptions.isObject() ? &voptions.toObject()
|
|
: nullptr);
|
|
CreateObjectInOptions options(cx, optionsObject);
|
|
if (voptions.isObject() &&
|
|
!options.Parse())
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (!xpc::CreateObjectIn(cx, vobj, options, rval))
|
|
return NS_ERROR_FAILURE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::MakeObjectPropsNormal(HandleValue vobj, JSContext* cx)
|
|
{
|
|
if (!cx)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// first argument must be an object
|
|
if (vobj.isPrimitive())
|
|
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
|
|
|
RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
|
|
JSAutoCompartment ac(cx, obj);
|
|
Rooted<IdVector> ida(cx, IdVector(cx));
|
|
if (!JS_Enumerate(cx, obj, &ida))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
RootedId id(cx);
|
|
RootedValue v(cx);
|
|
for (size_t i = 0; i < ida.length(); ++i) {
|
|
id = ida[i];
|
|
|
|
if (!JS_GetPropertyById(cx, obj, id, &v))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (v.isPrimitive())
|
|
continue;
|
|
|
|
RootedObject propobj(cx, &v.toObject());
|
|
// TODO Deal with non-functions.
|
|
if (!js::IsWrapper(propobj) || !JS::IsCallable(propobj))
|
|
continue;
|
|
|
|
FunctionForwarderOptions forwarderOptions;
|
|
if (!NewFunctionForwarder(cx, id, propobj, forwarderOptions, &v) ||
|
|
!JS_SetPropertyById(cx, obj, id, v))
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::IsDeadWrapper(HandleValue obj, bool* out)
|
|
{
|
|
*out = false;
|
|
if (obj.isPrimitive())
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
// Make sure to unwrap first. Once a proxy is nuked, it ceases to be a
|
|
// wrapper, meaning that, if passed to another compartment, we'll generate
|
|
// a CCW for it. Make sure that IsDeadWrapper sees through the confusion.
|
|
*out = JS_IsDeadWrapper(js::CheckedUnwrap(&obj.toObject()));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::IsCrossProcessWrapper(HandleValue obj, bool* out)
|
|
{
|
|
*out = false;
|
|
if (obj.isPrimitive())
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
*out = jsipc::IsWrappedCPOW(&obj.toObject());
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetCrossProcessWrapperTag(HandleValue obj, nsACString& out)
|
|
{
|
|
if (obj.isPrimitive() || !jsipc::IsWrappedCPOW(&obj.toObject()))
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
jsipc::GetWrappedCPOWTag(&obj.toObject(), out);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext* cx)
|
|
{
|
|
// Determine the compartment of the given object, if any.
|
|
JSCompartment* c = vobj.isObject()
|
|
? js::GetObjectCompartment(js::UncheckedUnwrap(&vobj.toObject()))
|
|
: nullptr;
|
|
|
|
// If no compartment was given, recompute all.
|
|
if (!c)
|
|
js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments());
|
|
// Otherwise, recompute wrappers for the given compartment.
|
|
else
|
|
js::RecomputeWrappers(cx, js::SingleCompartment(c), js::AllCompartments()) &&
|
|
js::RecomputeWrappers(cx, js::AllCompartments(), js::SingleCompartment(c));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::SetWantXrays(HandleValue vscope, JSContext* cx)
|
|
{
|
|
if (!vscope.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
|
|
JSCompartment* compartment = js::GetObjectCompartment(scopeObj);
|
|
CompartmentPrivate::Get(scopeObj)->wantXrays = true;
|
|
bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
|
|
js::AllCompartments());
|
|
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ForcePermissiveCOWs(JSContext* cx)
|
|
{
|
|
CrashIfNotInAutomation();
|
|
CompartmentPrivate::Get(CurrentGlobalOrNull(cx))->forcePermissiveCOWs = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::ForcePrivilegedComponentsForScope(HandleValue vscope,
|
|
JSContext* cx)
|
|
{
|
|
if (!vscope.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
CrashIfNotInAutomation();
|
|
JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
|
|
XPCWrappedNativeScope* scope = ObjectScope(scopeObj);
|
|
scope->ForcePrivilegedComponents();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext* cx,
|
|
MutableHandleValue rval)
|
|
{
|
|
if (!vscope.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
|
|
XPCWrappedNativeScope* scope = ObjectScope(scopeObj);
|
|
RootedObject components(cx);
|
|
if (!scope->GetComponentsJSObject(&components))
|
|
return NS_ERROR_FAILURE;
|
|
if (!JS_WrapObject(cx, &components))
|
|
return NS_ERROR_FAILURE;
|
|
rval.setObject(*components);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
|
|
JSContext* cx)
|
|
{
|
|
RootedValue runnable(cx, runnableArg);
|
|
// Enter the given compartment, if any, and rewrap runnable.
|
|
Maybe<JSAutoCompartment> ac;
|
|
if (scope.isObject()) {
|
|
JSObject* scopeObj = js::UncheckedUnwrap(&scope.toObject());
|
|
if (!scopeObj)
|
|
return NS_ERROR_FAILURE;
|
|
ac.emplace(cx, scopeObj);
|
|
if (!JS_WrapValue(cx, &runnable))
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// Get an XPCWrappedJS for |runnable|.
|
|
if (!runnable.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
nsCOMPtr<nsIRunnable> run;
|
|
nsresult rv = nsXPConnect::XPConnect()->WrapJS(cx, &runnable.toObject(),
|
|
NS_GET_IID(nsIRunnable),
|
|
getter_AddRefs(run));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
MOZ_ASSERT(run);
|
|
|
|
// Dispatch.
|
|
return NS_DispatchToMainThread(run);
|
|
}
|
|
|
|
#define GENERATE_JSCONTEXTOPTION_GETTER_SETTER(_attr, _getter, _setter) \
|
|
NS_IMETHODIMP \
|
|
nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
|
|
{ \
|
|
*aValue = ContextOptionsRef(cx)._getter(); \
|
|
return NS_OK; \
|
|
} \
|
|
NS_IMETHODIMP \
|
|
nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
|
|
{ \
|
|
ContextOptionsRef(cx)._setter(aValue); \
|
|
return NS_OK; \
|
|
}
|
|
|
|
#define GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(_attr, _getter, _setter) \
|
|
NS_IMETHODIMP \
|
|
nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
|
|
{ \
|
|
*aValue = RuntimeOptionsRef(cx)._getter(); \
|
|
return NS_OK; \
|
|
} \
|
|
NS_IMETHODIMP \
|
|
nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
|
|
{ \
|
|
RuntimeOptionsRef(cx)._setter(aValue); \
|
|
return NS_OK; \
|
|
}
|
|
|
|
GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
|
|
GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Werror, werror, setWerror)
|
|
GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
|
|
GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Ion, ion, setIon)
|
|
|
|
#undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
|
|
#undef GENERATE_JSRUNTIMEOPTION_GETTER_SETTER
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx)
|
|
{
|
|
#ifdef JS_GC_ZEAL
|
|
JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ);
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext* cx)
|
|
{
|
|
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::JS);
|
|
NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG);
|
|
JSObject* wrapper = &obj.toObject();
|
|
NS_ENSURE_TRUE(IsWrapper(wrapper), NS_ERROR_INVALID_ARG);
|
|
JSObject* sb = UncheckedUnwrap(wrapper);
|
|
NS_ENSURE_TRUE(IsSandbox(sb), NS_ERROR_INVALID_ARG);
|
|
NukeCrossCompartmentWrappers(cx, AllCompartments(),
|
|
SingleCompartment(GetObjectCompartment(sb)),
|
|
NukeWindowReferences);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
|
|
JSContext* cx)
|
|
{
|
|
NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
|
|
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
|
|
/* stopAtWindowProxy = */ false));
|
|
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
|
if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
|
|
JS_ReportError(cx, "Script may not be disabled for system globals");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
Scriptability::Get(global).Block();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
|
|
JSContext* cx)
|
|
{
|
|
NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
|
|
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
|
|
/* stopAtWindowProxy = */ false));
|
|
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
|
if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
|
|
JS_ReportError(cx, "Script may not be disabled for system globals");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
Scriptability::Get(global).Unblock();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::IsXrayWrapper(HandleValue obj, bool* aRetval)
|
|
{
|
|
*aRetval =
|
|
obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::WaiveXrays(HandleValue aVal, JSContext* aCx, MutableHandleValue aRetval)
|
|
{
|
|
RootedValue value(aCx, aVal);
|
|
if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value))
|
|
return NS_ERROR_FAILURE;
|
|
aRetval.set(value);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::UnwaiveXrays(HandleValue aVal, JSContext* aCx, MutableHandleValue aRetval)
|
|
{
|
|
if (!aVal.isObject()) {
|
|
aRetval.set(aVal);
|
|
return NS_OK;
|
|
}
|
|
|
|
RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject()));
|
|
if (!JS_WrapObject(aCx, &obj))
|
|
return NS_ERROR_FAILURE;
|
|
aRetval.setObject(*obj);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap, JSContext* aCx, char** aRv)
|
|
{
|
|
if (!aObj.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
RootedObject obj(aCx, &aObj.toObject());
|
|
if (aUnwrap)
|
|
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
|
|
*aRv = NS_strdup(js::GetObjectClass(obj)->name);
|
|
NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetDOMClassInfo(const nsAString& aClassName,
|
|
nsIClassInfo** aClassInfo)
|
|
{
|
|
*aClassInfo = nullptr;
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetIncumbentGlobal(HandleValue aCallback,
|
|
JSContext* aCx, MutableHandleValue aOut)
|
|
{
|
|
nsCOMPtr<nsIGlobalObject> global = mozilla::dom::GetIncumbentGlobal();
|
|
RootedValue globalVal(aCx);
|
|
|
|
if (!global) {
|
|
globalVal = NullValue();
|
|
} else {
|
|
// Note: We rely on the wrap call for outerization.
|
|
globalVal = ObjectValue(*global->GetGlobalJSObject());
|
|
if (!JS_WrapValue(aCx, &globalVal))
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// Invoke the callback, if passed.
|
|
if (aCallback.isObject()) {
|
|
RootedValue ignored(aCx);
|
|
if (!JS_CallFunctionValue(aCx, nullptr, aCallback, JS::HandleValueArray(globalVal), &ignored))
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
aOut.set(globalVal);
|
|
return NS_OK;
|
|
}
|
|
|
|
/*
|
|
* Below is a bunch of awkward junk to allow JS test code to trigger the
|
|
* creation of an XPCWrappedJS, such that it ends up in the map. We need to
|
|
* hand the caller some sort of reference to hold onto (to prevent the
|
|
* refcount from dropping to zero as soon as the function returns), but trying
|
|
* to return a bonafide XPCWrappedJS to script causes all sorts of trouble. So
|
|
* we create a benign holder class instead, which acts as an opaque reference
|
|
* that script can use to keep the XPCWrappedJS alive and in the map.
|
|
*/
|
|
|
|
class WrappedJSHolder : public nsISupports
|
|
{
|
|
NS_DECL_ISUPPORTS
|
|
WrappedJSHolder() {}
|
|
|
|
RefPtr<nsXPCWrappedJS> mWrappedJS;
|
|
|
|
private:
|
|
virtual ~WrappedJSHolder() {}
|
|
};
|
|
NS_IMPL_ISUPPORTS0(WrappedJSHolder);
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GenerateXPCWrappedJS(HandleValue aObj, HandleValue aScope,
|
|
JSContext* aCx, nsISupports** aOut)
|
|
{
|
|
if (!aObj.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
RootedObject obj(aCx, &aObj.toObject());
|
|
RootedObject scope(aCx, aScope.isObject() ? js::UncheckedUnwrap(&aScope.toObject())
|
|
: CurrentGlobalOrNull(aCx));
|
|
JSAutoCompartment ac(aCx, scope);
|
|
if (!JS_WrapObject(aCx, &obj))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
RefPtr<WrappedJSHolder> holder = new WrappedJSHolder();
|
|
nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports),
|
|
getter_AddRefs(holder->mWrappedJS));
|
|
holder.forget(aOut);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory, PRTime* aOut)
|
|
{
|
|
WatchdogTimestampCategory category;
|
|
if (aCategory.EqualsLiteral("RuntimeStateChange"))
|
|
category = TimestampRuntimeStateChange;
|
|
else if (aCategory.EqualsLiteral("WatchdogWakeup"))
|
|
category = TimestampWatchdogWakeup;
|
|
else if (aCategory.EqualsLiteral("WatchdogHibernateStart"))
|
|
category = TimestampWatchdogHibernateStart;
|
|
else if (aCategory.EqualsLiteral("WatchdogHibernateStop"))
|
|
category = TimestampWatchdogHibernateStop;
|
|
else
|
|
return NS_ERROR_INVALID_ARG;
|
|
*aOut = XPCJSRuntime::Get()->GetWatchdogTimestamp(category);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext* cx, MutableHandleValue rval)
|
|
{
|
|
RootedObject obj(cx, JS_NewPlainObject(cx));
|
|
if (!obj)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
|
|
|
|
size_t i = JS_SetProtoCalled(cx);
|
|
RootedValue v(cx, DoubleValue(i));
|
|
if (!JS_DefineProperty(cx, obj, "setProto", v, attrs))
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
i = JS_GetCustomIteratorCount(cx);
|
|
v.setDouble(i);
|
|
if (!JS_DefineProperty(cx, obj, "customIter", v, attrs))
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
rval.setObject(*obj);
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
xpc::CloneInto(JSContext* aCx, HandleValue aValue, HandleValue aScope,
|
|
HandleValue aOptions, MutableHandleValue aCloned)
|
|
{
|
|
if (!aScope.isObject())
|
|
return false;
|
|
|
|
RootedObject scope(aCx, &aScope.toObject());
|
|
scope = js::CheckedUnwrap(scope);
|
|
if(!scope) {
|
|
JS_ReportError(aCx, "Permission denied to clone object into scope");
|
|
return false;
|
|
}
|
|
|
|
if (!aOptions.isUndefined() && !aOptions.isObject()) {
|
|
JS_ReportError(aCx, "Invalid argument");
|
|
return false;
|
|
}
|
|
|
|
RootedObject optionsObject(aCx, aOptions.isObject() ? &aOptions.toObject()
|
|
: nullptr);
|
|
StackScopedCloneOptions options(aCx, optionsObject);
|
|
if (aOptions.isObject() && !options.Parse())
|
|
return false;
|
|
|
|
{
|
|
JSAutoCompartment ac(aCx, scope);
|
|
aCloned.set(aValue);
|
|
if (!StackScopedClone(aCx, options, aCloned))
|
|
return false;
|
|
}
|
|
|
|
return JS_WrapValue(aCx, aCloned);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope,
|
|
HandleValue aOptions, JSContext* aCx,
|
|
MutableHandleValue aCloned)
|
|
{
|
|
return xpc::CloneInto(aCx, aValue, aScope, aOptions, aCloned) ?
|
|
NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal** aResult)
|
|
{
|
|
// This API may only be when the Entry Settings Object corresponds to a
|
|
// JS-implemented WebIDL call. In all other cases, the value will be null,
|
|
// and we throw.
|
|
nsCOMPtr<nsIPrincipal> callerPrin = mozilla::dom::GetWebIDLCallerPrincipal();
|
|
if (!callerPrin)
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
callerPrin.forget(aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext* cx,
|
|
nsIPrincipal** result)
|
|
{
|
|
if (!val.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
RootedObject obj(cx, &val.toObject());
|
|
obj = js::CheckedUnwrap(obj);
|
|
MOZ_ASSERT(obj);
|
|
|
|
nsCOMPtr<nsIPrincipal> prin = nsContentUtils::ObjectPrincipal(obj);
|
|
prin.forget(result);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::GetCompartmentLocation(HandleValue val,
|
|
JSContext* cx,
|
|
nsACString& result)
|
|
{
|
|
if (!val.isObject())
|
|
return NS_ERROR_INVALID_ARG;
|
|
RootedObject obj(cx, &val.toObject());
|
|
obj = js::CheckedUnwrap(obj);
|
|
MOZ_ASSERT(obj);
|
|
|
|
result = xpc::CompartmentPrivate::Get(obj)->GetLocation();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::SetAddonInterposition(const nsACString& addonIdStr,
|
|
nsIAddonInterposition* interposition,
|
|
JSContext* cx)
|
|
{
|
|
JSAddonId* addonId = xpc::NewAddonId(cx, addonIdStr);
|
|
if (!addonId)
|
|
return NS_ERROR_FAILURE;
|
|
if (!XPCWrappedNativeScope::SetAddonInterposition(cx, addonId, interposition))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::SetAddonCallInterposition(HandleValue target,
|
|
JSContext* cx)
|
|
{
|
|
NS_ENSURE_TRUE(target.isObject(), NS_ERROR_INVALID_ARG);
|
|
RootedObject targetObj(cx, &target.toObject());
|
|
targetObj = js::CheckedUnwrap(targetObj);
|
|
NS_ENSURE_TRUE(targetObj, NS_ERROR_INVALID_ARG);
|
|
XPCWrappedNativeScope* xpcScope = ObjectScope(targetObj);
|
|
NS_ENSURE_TRUE(xpcScope, NS_ERROR_INVALID_ARG);
|
|
|
|
xpcScope->SetAddonCallInterposition();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents_Utils::Now(double* aRetval)
|
|
{
|
|
bool isInconsistent = false;
|
|
TimeStamp start = TimeStamp::ProcessCreation(isInconsistent);
|
|
*aRetval = (TimeStamp::Now() - start).ToMilliseconds();
|
|
return NS_OK;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
/***************************************************************************/
|
|
|
|
|
|
nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope)
|
|
: mScope(aScope)
|
|
{
|
|
MOZ_ASSERT(aScope, "aScope must not be null");
|
|
}
|
|
|
|
nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
|
|
: nsXPCComponentsBase(aScope)
|
|
{
|
|
}
|
|
|
|
nsXPCComponentsBase::~nsXPCComponentsBase()
|
|
{
|
|
}
|
|
|
|
nsXPCComponents::~nsXPCComponents()
|
|
{
|
|
}
|
|
|
|
void
|
|
nsXPCComponentsBase::ClearMembers()
|
|
{
|
|
mInterfaces = nullptr;
|
|
mInterfacesByID = nullptr;
|
|
mResults = nullptr;
|
|
}
|
|
|
|
void
|
|
nsXPCComponents::ClearMembers()
|
|
{
|
|
mClasses = nullptr;
|
|
mClassesByID = nullptr;
|
|
mID = nullptr;
|
|
mException = nullptr;
|
|
mConstructor = nullptr;
|
|
mUtils = nullptr;
|
|
|
|
nsXPCComponentsBase::ClearMembers();
|
|
}
|
|
|
|
/*******************************************/
|
|
#define XPC_IMPL_GET_OBJ_METHOD(_class, _n) \
|
|
NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n * *a##_n) { \
|
|
NS_ENSURE_ARG_POINTER(a##_n); \
|
|
if (!m##_n) \
|
|
m##_n = new nsXPCComponents_##_n(); \
|
|
RefPtr<nsXPCComponents_##_n> ret = m##_n; \
|
|
ret.forget(a##_n); \
|
|
return NS_OK; \
|
|
}
|
|
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Interfaces)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, InterfacesByID)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ClassesByID)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Results)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor)
|
|
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils)
|
|
|
|
#undef XPC_IMPL_GET_OBJ_METHOD
|
|
/*******************************************/
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponentsBase::IsSuccessCode(nsresult result, bool* out)
|
|
{
|
|
*out = NS_SUCCEEDED(result);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents::GetStack(nsIStackFrame * *aStack)
|
|
{
|
|
nsresult rv;
|
|
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
|
rv = xpc->GetCurrentJSStack(aStack);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents::GetManager(nsIComponentManager * *aManager)
|
|
{
|
|
MOZ_ASSERT(aManager, "bad param");
|
|
return NS_GetComponentManager(aManager);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents::GetLastResult(JSContext* aCx, MutableHandleValue aOut)
|
|
{
|
|
XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
|
|
if (!xpcc)
|
|
return NS_ERROR_FAILURE;
|
|
nsresult res = xpcc->GetLastResult();
|
|
aOut.setNumber(static_cast<uint32_t>(res));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents::GetReturnCode(JSContext* aCx, MutableHandleValue aOut)
|
|
{
|
|
XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
|
|
if (!xpcc)
|
|
return NS_ERROR_FAILURE;
|
|
nsresult res = xpcc->GetPendingResult();
|
|
aOut.setNumber(static_cast<uint32_t>(res));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsXPCComponents::SetReturnCode(JSContext* aCx, HandleValue aCode)
|
|
{
|
|
XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
|
|
if (!xpcc)
|
|
return NS_ERROR_FAILURE;
|
|
nsresult rv;
|
|
if (!ToUint32(aCx, aCode, (uint32_t*)&rv))
|
|
return NS_ERROR_FAILURE;
|
|
xpcc->SetPendingResult(rv);
|
|
xpcc->SetLastResult(rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
// static
|
|
NS_IMETHODIMP nsXPCComponents::ReportError(HandleValue error, JSContext* cx)
|
|
{
|
|
NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
|
|
|
|
nsCOMPtr<nsIXPCComponents_Utils> utils;
|
|
nsresult rv = GetUtils(getter_AddRefs(utils));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
return utils->ReportError(error, cx);
|
|
}
|
|
|
|
/**********************************************/
|
|
|
|
class ComponentsSH : public nsIXPCScriptable
|
|
{
|
|
public:
|
|
explicit ComponentsSH(unsigned dummy)
|
|
{
|
|
}
|
|
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIXPCSCRIPTABLE
|
|
// The NS_IMETHODIMP isn't really accurate here, but NS_CALLBACK requires
|
|
// the referent to be declared __stdcall on Windows, and this is the only
|
|
// macro that does that.
|
|
static NS_IMETHODIMP Get(nsIXPCScriptable** helper)
|
|
{
|
|
*helper = &singleton;
|
|
return NS_OK;
|
|
}
|
|
|
|
private:
|
|
static ComponentsSH singleton;
|
|
};
|
|
|
|
ComponentsSH ComponentsSH::singleton(0);
|
|
|
|
// Singleton refcounting.
|
|
NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::AddRef(void) { return 1; }
|
|
NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::Release(void) { return 1; }
|
|
|
|
NS_INTERFACE_MAP_BEGIN(ComponentsSH)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
#define NSXPCCOMPONENTSBASE_CID \
|
|
{ 0xc62998e5, 0x95f1, 0x4058, \
|
|
{ 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 } }
|
|
|
|
#define NSXPCCOMPONENTS_CID \
|
|
{ 0x3649f405, 0xf0ec, 0x4c28, \
|
|
{ 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 } }
|
|
|
|
NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID)
|
|
NS_IMPL_ISUPPORTS_CI(nsXPCComponentsBase, nsIXPCComponentsBase)
|
|
|
|
NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTS_CID)
|
|
// Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like
|
|
// if it existed.
|
|
NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase)
|
|
NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase)
|
|
NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
|
|
NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
|
|
NS_IMPL_QUERY_CLASSINFO(nsXPCComponents)
|
|
NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase)
|
|
NS_IMPL_CI_INTERFACE_GETTER(nsXPCComponents, nsIXPCComponents)
|
|
|
|
// The nsIXPCScriptable map declaration that will generate stubs for us
|
|
#define XPC_MAP_CLASSNAME ComponentsSH
|
|
#define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents"
|
|
#define XPC_MAP_WANT_PRECREATE
|
|
#include "xpc_map_end.h" /* This will #undef the above */
|
|
|
|
NS_IMETHODIMP
|
|
ComponentsSH::PreCreate(nsISupports* nativeObj, JSContext* cx, JSObject* globalObj, JSObject** parentObj)
|
|
{
|
|
nsXPCComponentsBase* self = static_cast<nsXPCComponentsBase*>(nativeObj);
|
|
// this should never happen
|
|
if (!self->GetScope()) {
|
|
NS_WARNING("mScope must not be null when nsXPCComponents::PreCreate is called");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
*parentObj = self->GetScope()->GetGlobalJSObject();
|
|
return NS_OK;
|
|
}
|