js/xpconnect/src/XPCComponents.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/xpconnect/src/XPCComponents.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3849 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=99: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* The "Components" xpcom objects for JavaScript. */
    1.11 +
    1.12 +#include "xpcprivate.h"
    1.13 +#include "xpcIJSModuleLoader.h"
    1.14 +#include "XPCJSWeakReference.h"
    1.15 +#include "WrapperFactory.h"
    1.16 +#include "nsJSUtils.h"
    1.17 +#include "mozJSComponentLoader.h"
    1.18 +#include "nsContentUtils.h"
    1.19 +#include "jsfriendapi.h"
    1.20 +#include "js/StructuredClone.h"
    1.21 +#include "mozilla/Attributes.h"
    1.22 +#include "nsJSEnvironment.h"
    1.23 +#include "mozilla/XPTInterfaceInfoManager.h"
    1.24 +#include "mozilla/dom/DOMException.h"
    1.25 +#include "mozilla/dom/DOMExceptionBinding.h"
    1.26 +#include "mozilla/dom/BindingUtils.h"
    1.27 +#include "mozilla/dom/StructuredCloneTags.h"
    1.28 +#include "nsZipArchive.h"
    1.29 +#include "nsIDOMFile.h"
    1.30 +#include "nsIDOMFileList.h"
    1.31 +#include "nsWindowMemoryReporter.h"
    1.32 +
    1.33 +using namespace mozilla;
    1.34 +using namespace JS;
    1.35 +using namespace js;
    1.36 +using namespace xpc;
    1.37 +using mozilla::dom::Exception;
    1.38 +
    1.39 +/***************************************************************************/
    1.40 +// stuff used by all
    1.41 +
    1.42 +nsresult
    1.43 +xpc::ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval)
    1.44 +{
    1.45 +    XPCThrower::Throw(errNum, cx);
    1.46 +    *retval = false;
    1.47 +    return NS_OK;
    1.48 +}
    1.49 +
    1.50 +static bool
    1.51 +JSValIsInterfaceOfType(JSContext *cx, HandleValue v, REFNSIID iid)
    1.52 +{
    1.53 +
    1.54 +    nsCOMPtr<nsIXPConnectWrappedNative> wn;
    1.55 +    nsCOMPtr<nsISupports> sup;
    1.56 +    nsISupports* iface;
    1.57 +
    1.58 +    if (v.isPrimitive())
    1.59 +        return false;
    1.60 +
    1.61 +    nsXPConnect* xpc = nsXPConnect::XPConnect();
    1.62 +    RootedObject obj(cx, &v.toObject());
    1.63 +    if (NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) && wn &&
    1.64 +        NS_SUCCEEDED(wn->Native()->QueryInterface(iid, (void**)&iface)) && iface)
    1.65 +    {
    1.66 +        NS_RELEASE(iface);
    1.67 +        return true;
    1.68 +    }
    1.69 +    return false;
    1.70 +}
    1.71 +
    1.72 +char *
    1.73 +xpc::CloneAllAccess()
    1.74 +{
    1.75 +    static const char allAccess[] = "AllAccess";
    1.76 +    return (char*)nsMemory::Clone(allAccess, sizeof(allAccess));
    1.77 +}
    1.78 +
    1.79 +char *
    1.80 +xpc::CheckAccessList(const char16_t *wideName, const char *const list[])
    1.81 +{
    1.82 +    nsAutoCString asciiName;
    1.83 +    CopyUTF16toUTF8(nsDependentString(wideName), asciiName);
    1.84 +
    1.85 +    for (const char* const* p = list; *p; p++)
    1.86 +        if (!strcmp(*p, asciiName.get()))
    1.87 +            return CloneAllAccess();
    1.88 +
    1.89 +    return nullptr;
    1.90 +}
    1.91 +
    1.92 +/***************************************************************************/
    1.93 +/***************************************************************************/
    1.94 +/***************************************************************************/
    1.95 +
    1.96 +
    1.97 +class nsXPCComponents_Interfaces :
    1.98 +            public nsIXPCComponents_Interfaces,
    1.99 +            public nsIXPCScriptable,
   1.100 +            public nsIClassInfo
   1.101 +{
   1.102 +public:
   1.103 +    // all the interface method declarations...
   1.104 +    NS_DECL_ISUPPORTS
   1.105 +    NS_DECL_NSIXPCCOMPONENTS_INTERFACES
   1.106 +    NS_DECL_NSIXPCSCRIPTABLE
   1.107 +    NS_DECL_NSICLASSINFO
   1.108 +
   1.109 +public:
   1.110 +    nsXPCComponents_Interfaces();
   1.111 +    virtual ~nsXPCComponents_Interfaces();
   1.112 +
   1.113 +private:
   1.114 +    nsCOMArray<nsIInterfaceInfo> mInterfaces;
   1.115 +};
   1.116 +
   1.117 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   1.118 +                       out nsIIDPtr array); */
   1.119 +NS_IMETHODIMP
   1.120 +nsXPCComponents_Interfaces::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   1.121 +{
   1.122 +    const uint32_t count = 2;
   1.123 +    *aCount = count;
   1.124 +    nsIID **array;
   1.125 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   1.126 +    if (!array)
   1.127 +        return NS_ERROR_OUT_OF_MEMORY;
   1.128 +
   1.129 +    uint32_t index = 0;
   1.130 +    nsIID* clone;
   1.131 +#define PUSH_IID(id)                                                          \
   1.132 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   1.133 +                                                 sizeof(nsIID)));             \
   1.134 +    if (!clone)                                                               \
   1.135 +        goto oom;                                                             \
   1.136 +    array[index++] = clone;
   1.137 +
   1.138 +    PUSH_IID(nsIXPCComponents_Interfaces)
   1.139 +    PUSH_IID(nsIXPCScriptable)
   1.140 +#undef PUSH_IID
   1.141 +
   1.142 +    return NS_OK;
   1.143 +oom:
   1.144 +    while (index)
   1.145 +        nsMemory::Free(array[--index]);
   1.146 +    nsMemory::Free(array);
   1.147 +    *aArray = nullptr;
   1.148 +    return NS_ERROR_OUT_OF_MEMORY;
   1.149 +}
   1.150 +
   1.151 +/* nsISupports getHelperForLanguage (in uint32_t language); */
   1.152 +NS_IMETHODIMP
   1.153 +nsXPCComponents_Interfaces::GetHelperForLanguage(uint32_t language,
   1.154 +                                                 nsISupports **retval)
   1.155 +{
   1.156 +    *retval = nullptr;
   1.157 +    return NS_OK;
   1.158 +}
   1.159 +
   1.160 +/* readonly attribute string contractID; */
   1.161 +NS_IMETHODIMP
   1.162 +nsXPCComponents_Interfaces::GetContractID(char * *aContractID)
   1.163 +{
   1.164 +    *aContractID = nullptr;
   1.165 +    return NS_ERROR_NOT_AVAILABLE;
   1.166 +}
   1.167 +
   1.168 +/* readonly attribute string classDescription; */
   1.169 +NS_IMETHODIMP
   1.170 +nsXPCComponents_Interfaces::GetClassDescription(char * *aClassDescription)
   1.171 +{
   1.172 +    static const char classDescription[] = "XPCComponents_Interfaces";
   1.173 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   1.174 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   1.175 +}
   1.176 +
   1.177 +/* readonly attribute nsCIDPtr classID; */
   1.178 +NS_IMETHODIMP
   1.179 +nsXPCComponents_Interfaces::GetClassID(nsCID * *aClassID)
   1.180 +{
   1.181 +    *aClassID = nullptr;
   1.182 +    return NS_OK;
   1.183 +}
   1.184 +
   1.185 +/* readonly attribute uint32_t implementationLanguage; */
   1.186 +NS_IMETHODIMP
   1.187 +nsXPCComponents_Interfaces::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   1.188 +{
   1.189 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   1.190 +    return NS_OK;
   1.191 +}
   1.192 +
   1.193 +/* readonly attribute uint32_t flags; */
   1.194 +NS_IMETHODIMP
   1.195 +nsXPCComponents_Interfaces::GetFlags(uint32_t *aFlags)
   1.196 +{
   1.197 +    // Mark ourselves as a DOM object so that instances may be created in
   1.198 +    // unprivileged scopes.
   1.199 +    *aFlags = nsIClassInfo::DOM_OBJECT;
   1.200 +    return NS_OK;
   1.201 +}
   1.202 +
   1.203 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   1.204 +NS_IMETHODIMP
   1.205 +nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   1.206 +{
   1.207 +    return NS_ERROR_NOT_AVAILABLE;
   1.208 +}
   1.209 +
   1.210 +nsXPCComponents_Interfaces::nsXPCComponents_Interfaces()
   1.211 +{
   1.212 +}
   1.213 +
   1.214 +nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces()
   1.215 +{
   1.216 +    // empty
   1.217 +}
   1.218 +
   1.219 +
   1.220 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces)
   1.221 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Interfaces)
   1.222 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   1.223 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   1.224 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Interfaces)
   1.225 +NS_INTERFACE_MAP_END
   1.226 +
   1.227 +NS_IMPL_ADDREF(nsXPCComponents_Interfaces)
   1.228 +NS_IMPL_RELEASE(nsXPCComponents_Interfaces)
   1.229 +
   1.230 +// The nsIXPCScriptable map declaration that will generate stubs for us...
   1.231 +#define XPC_MAP_CLASSNAME           nsXPCComponents_Interfaces
   1.232 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Interfaces"
   1.233 +#define                             XPC_MAP_WANT_NEWRESOLVE
   1.234 +#define                             XPC_MAP_WANT_NEWENUMERATE
   1.235 +#define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   1.236 +                                    nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   1.237 +#include "xpc_map_end.h" /* This will #undef the above */
   1.238 +
   1.239 +
   1.240 +/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   1.241 +NS_IMETHODIMP
   1.242 +nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   1.243 +                                         JSContext * cx, JSObject * obj,
   1.244 +                                         uint32_t enum_op, jsval * statep,
   1.245 +                                         jsid * idp, bool *_retval)
   1.246 +{
   1.247 +    switch (enum_op) {
   1.248 +        case JSENUMERATE_INIT:
   1.249 +        case JSENUMERATE_INIT_ALL:
   1.250 +        {
   1.251 +            // Lazily init the list of interfaces when someone tries to
   1.252 +            // enumerate them.
   1.253 +            if (mInterfaces.IsEmpty()) {
   1.254 +                XPTInterfaceInfoManager::GetSingleton()->
   1.255 +                    GetScriptableInterfaces(mInterfaces);
   1.256 +            }
   1.257 +
   1.258 +            *statep = JSVAL_ZERO;
   1.259 +            if (idp)
   1.260 +                *idp = INT_TO_JSID(mInterfaces.Length());
   1.261 +            return NS_OK;
   1.262 +        }
   1.263 +        case JSENUMERATE_NEXT:
   1.264 +        {
   1.265 +            uint32_t idx = JSVAL_TO_INT(*statep);
   1.266 +            nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
   1.267 +            *statep = UINT_TO_JSVAL(idx + 1);
   1.268 +
   1.269 +            if (interface) {
   1.270 +                const char* name;
   1.271 +
   1.272 +                RootedId id(cx);
   1.273 +                if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) {
   1.274 +                    RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
   1.275 +                    if (idstr && JS_StringToId(cx, idstr, &id)) {
   1.276 +                        *idp = id;
   1.277 +                        return NS_OK;
   1.278 +                    }
   1.279 +                }
   1.280 +            }
   1.281 +            // fall through
   1.282 +        }
   1.283 +
   1.284 +        case JSENUMERATE_DESTROY:
   1.285 +        default:
   1.286 +            *statep = JSVAL_NULL;
   1.287 +            return NS_OK;
   1.288 +    }
   1.289 +}
   1.290 +
   1.291 +/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
   1.292 +NS_IMETHODIMP
   1.293 +nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper,
   1.294 +                                       JSContext *cx, JSObject *objArg,
   1.295 +                                       jsid idArg, JSObject **objp,
   1.296 +                                       bool *_retval)
   1.297 +{
   1.298 +    RootedObject obj(cx, objArg);
   1.299 +    RootedId id(cx, idArg);
   1.300 +
   1.301 +    if (!JSID_IS_STRING(id))
   1.302 +        return NS_OK;
   1.303 +
   1.304 +    JSAutoByteString name;
   1.305 +    RootedString str(cx, JSID_TO_STRING(id));
   1.306 +
   1.307 +    // we only allow interfaces by name here
   1.308 +    if (name.encodeLatin1(cx, str) && name.ptr()[0] != '{') {
   1.309 +        nsCOMPtr<nsIInterfaceInfo> info;
   1.310 +        XPTInterfaceInfoManager::GetSingleton()->
   1.311 +            GetInfoForName(name.ptr(), getter_AddRefs(info));
   1.312 +        if (!info)
   1.313 +            return NS_OK;
   1.314 +
   1.315 +        nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
   1.316 +
   1.317 +        if (nsid) {
   1.318 +            nsXPConnect* xpc = nsXPConnect::XPConnect();
   1.319 +            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   1.320 +            if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
   1.321 +                                             static_cast<nsIJSIID*>(nsid),
   1.322 +                                             NS_GET_IID(nsIJSIID),
   1.323 +                                             getter_AddRefs(holder)))) {
   1.324 +                RootedObject idobj(cx);
   1.325 +                if (holder &&
   1.326 +                    // Assign, not compare
   1.327 +                    (idobj = holder->GetJSObject())) {
   1.328 +                    *objp = obj;
   1.329 +                    *_retval = JS_DefinePropertyById(cx, obj, id,
   1.330 +                                                     OBJECT_TO_JSVAL(idobj),
   1.331 +                                                     nullptr, nullptr,
   1.332 +                                                     JSPROP_ENUMERATE |
   1.333 +                                                     JSPROP_READONLY |
   1.334 +                                                     JSPROP_PERMANENT);
   1.335 +                }
   1.336 +            }
   1.337 +        }
   1.338 +    }
   1.339 +    return NS_OK;
   1.340 +}
   1.341 +
   1.342 +/***************************************************************************/
   1.343 +/***************************************************************************/
   1.344 +/***************************************************************************/
   1.345 +
   1.346 +class nsXPCComponents_InterfacesByID :
   1.347 +            public nsIXPCComponents_InterfacesByID,
   1.348 +            public nsIXPCScriptable,
   1.349 +            public nsIClassInfo
   1.350 +{
   1.351 +public:
   1.352 +    // all the interface method declarations...
   1.353 +    NS_DECL_ISUPPORTS
   1.354 +    NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID
   1.355 +    NS_DECL_NSIXPCSCRIPTABLE
   1.356 +    NS_DECL_NSICLASSINFO
   1.357 +
   1.358 +public:
   1.359 +    nsXPCComponents_InterfacesByID();
   1.360 +    virtual ~nsXPCComponents_InterfacesByID();
   1.361 +
   1.362 +private:
   1.363 +    nsCOMArray<nsIInterfaceInfo> mInterfaces;
   1.364 +};
   1.365 +
   1.366 +/***************************************************************************/
   1.367 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   1.368 +                       out nsIIDPtr array); */
   1.369 +NS_IMETHODIMP
   1.370 +nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   1.371 +{
   1.372 +    const uint32_t count = 2;
   1.373 +    *aCount = count;
   1.374 +    nsIID **array;
   1.375 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   1.376 +    if (!array)
   1.377 +        return NS_ERROR_OUT_OF_MEMORY;
   1.378 +
   1.379 +    uint32_t index = 0;
   1.380 +    nsIID* clone;
   1.381 +#define PUSH_IID(id)                                                          \
   1.382 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   1.383 +                                                 sizeof(nsIID)));             \
   1.384 +    if (!clone)                                                               \
   1.385 +        goto oom;                                                             \
   1.386 +    array[index++] = clone;
   1.387 +
   1.388 +    PUSH_IID(nsIXPCComponents_InterfacesByID)
   1.389 +    PUSH_IID(nsIXPCScriptable)
   1.390 +#undef PUSH_IID
   1.391 +
   1.392 +    return NS_OK;
   1.393 +oom:
   1.394 +    while (index)
   1.395 +        nsMemory::Free(array[--index]);
   1.396 +    nsMemory::Free(array);
   1.397 +    *aArray = nullptr;
   1.398 +    return NS_ERROR_OUT_OF_MEMORY;
   1.399 +}
   1.400 +
   1.401 +/* nsISupports getHelperForLanguage (in uint32_t language); */
   1.402 +NS_IMETHODIMP
   1.403 +nsXPCComponents_InterfacesByID::GetHelperForLanguage(uint32_t language,
   1.404 +                                                     nsISupports **retval)
   1.405 +{
   1.406 +    *retval = nullptr;
   1.407 +    return NS_OK;
   1.408 +}
   1.409 +
   1.410 +/* readonly attribute string contractID; */
   1.411 +NS_IMETHODIMP
   1.412 +nsXPCComponents_InterfacesByID::GetContractID(char * *aContractID)
   1.413 +{
   1.414 +    *aContractID = nullptr;
   1.415 +    return NS_ERROR_NOT_AVAILABLE;
   1.416 +}
   1.417 +
   1.418 +/* readonly attribute string classDescription; */
   1.419 +NS_IMETHODIMP
   1.420 +nsXPCComponents_InterfacesByID::GetClassDescription(char * *aClassDescription)
   1.421 +{
   1.422 +    static const char classDescription[] = "XPCComponents_InterfacesByID";
   1.423 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   1.424 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   1.425 +}
   1.426 +
   1.427 +/* readonly attribute nsCIDPtr classID; */
   1.428 +NS_IMETHODIMP
   1.429 +nsXPCComponents_InterfacesByID::GetClassID(nsCID * *aClassID)
   1.430 +{
   1.431 +    *aClassID = nullptr;
   1.432 +    return NS_OK;
   1.433 +}
   1.434 +
   1.435 +/* readonly attribute uint32_t implementationLanguage; */
   1.436 +NS_IMETHODIMP
   1.437 +nsXPCComponents_InterfacesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   1.438 +{
   1.439 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   1.440 +    return NS_OK;
   1.441 +}
   1.442 +
   1.443 +/* readonly attribute uint32_t flags; */
   1.444 +NS_IMETHODIMP
   1.445 +nsXPCComponents_InterfacesByID::GetFlags(uint32_t *aFlags)
   1.446 +{
   1.447 +    // Mark ourselves as a DOM object so that instances may be created in
   1.448 +    // unprivileged scopes.
   1.449 +    *aFlags = nsIClassInfo::DOM_OBJECT;
   1.450 +    return NS_OK;
   1.451 +}
   1.452 +
   1.453 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   1.454 +NS_IMETHODIMP
   1.455 +nsXPCComponents_InterfacesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   1.456 +{
   1.457 +    return NS_ERROR_NOT_AVAILABLE;
   1.458 +}
   1.459 +
   1.460 +nsXPCComponents_InterfacesByID::nsXPCComponents_InterfacesByID()
   1.461 +{
   1.462 +}
   1.463 +
   1.464 +nsXPCComponents_InterfacesByID::~nsXPCComponents_InterfacesByID()
   1.465 +{
   1.466 +    // empty
   1.467 +}
   1.468 +
   1.469 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID)
   1.470 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_InterfacesByID)
   1.471 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   1.472 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   1.473 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_InterfacesByID)
   1.474 +NS_INTERFACE_MAP_END
   1.475 +
   1.476 +NS_IMPL_ADDREF(nsXPCComponents_InterfacesByID)
   1.477 +NS_IMPL_RELEASE(nsXPCComponents_InterfacesByID)
   1.478 +
   1.479 +// The nsIXPCScriptable map declaration that will generate stubs for us...
   1.480 +#define XPC_MAP_CLASSNAME           nsXPCComponents_InterfacesByID
   1.481 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_InterfacesByID"
   1.482 +#define                             XPC_MAP_WANT_NEWRESOLVE
   1.483 +#define                             XPC_MAP_WANT_NEWENUMERATE
   1.484 +#define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   1.485 +                                    nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   1.486 +#include "xpc_map_end.h" /* This will #undef the above */
   1.487 +
   1.488 +/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   1.489 +NS_IMETHODIMP
   1.490 +nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   1.491 +                                             JSContext * cx, JSObject * obj,
   1.492 +                                             uint32_t enum_op, jsval * statep,
   1.493 +                                             jsid * idp, bool *_retval)
   1.494 +{
   1.495 +    switch (enum_op) {
   1.496 +        case JSENUMERATE_INIT:
   1.497 +        case JSENUMERATE_INIT_ALL:
   1.498 +        {
   1.499 +            // Lazily init the list of interfaces when someone tries to
   1.500 +            // enumerate them.
   1.501 +            if (mInterfaces.IsEmpty()) {
   1.502 +                XPTInterfaceInfoManager::GetSingleton()->
   1.503 +                    GetScriptableInterfaces(mInterfaces);
   1.504 +            }
   1.505 +
   1.506 +            *statep = JSVAL_ZERO;
   1.507 +            if (idp)
   1.508 +                *idp = INT_TO_JSID(mInterfaces.Length());
   1.509 +            return NS_OK;
   1.510 +        }
   1.511 +        case JSENUMERATE_NEXT:
   1.512 +        {
   1.513 +            uint32_t idx = JSVAL_TO_INT(*statep);
   1.514 +            nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
   1.515 +            *statep = UINT_TO_JSVAL(idx + 1);
   1.516 +            if (interface) {
   1.517 +                nsIID const *iid;
   1.518 +                char idstr[NSID_LENGTH];
   1.519 +
   1.520 +                if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
   1.521 +                    iid->ToProvidedString(idstr);
   1.522 +                    RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr));
   1.523 +                    RootedId id(cx);
   1.524 +                    if (jsstr && JS_StringToId(cx, jsstr, &id)) {
   1.525 +                        *idp = id;
   1.526 +                        return NS_OK;
   1.527 +                    }
   1.528 +                }
   1.529 +            }
   1.530 +            // FALL THROUGH
   1.531 +        }
   1.532 +
   1.533 +        case JSENUMERATE_DESTROY:
   1.534 +        default:
   1.535 +            *statep = JSVAL_NULL;
   1.536 +            return NS_OK;
   1.537 +    }
   1.538 +}
   1.539 +
   1.540 +/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
   1.541 +NS_IMETHODIMP
   1.542 +nsXPCComponents_InterfacesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
   1.543 +                                           JSContext *cx, JSObject *objArg,
   1.544 +                                           jsid idArg, JSObject **objp,
   1.545 +                                           bool *_retval)
   1.546 +{
   1.547 +    RootedObject obj(cx, objArg);
   1.548 +    RootedId id(cx, idArg);
   1.549 +
   1.550 +    if (!JSID_IS_STRING(id))
   1.551 +        return NS_OK;
   1.552 +
   1.553 +    RootedString str(cx, JSID_TO_STRING(id));
   1.554 +    if (38 != JS_GetStringLength(str))
   1.555 +        return NS_OK;
   1.556 +
   1.557 +    if (const jschar *name = JS_GetInternedStringChars(str)) {
   1.558 +        nsID iid;
   1.559 +        if (!iid.Parse(NS_ConvertUTF16toUTF8(name).get()))
   1.560 +            return NS_OK;
   1.561 +
   1.562 +        nsCOMPtr<nsIInterfaceInfo> info;
   1.563 +        XPTInterfaceInfoManager::GetSingleton()->
   1.564 +            GetInfoForIID(&iid, getter_AddRefs(info));
   1.565 +        if (!info)
   1.566 +            return NS_OK;
   1.567 +
   1.568 +        nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
   1.569 +
   1.570 +        if (!nsid)
   1.571 +            return NS_ERROR_OUT_OF_MEMORY;
   1.572 +
   1.573 +        nsXPConnect* xpc = nsXPConnect::XPConnect();
   1.574 +        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   1.575 +        if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
   1.576 +                                         static_cast<nsIJSIID*>(nsid),
   1.577 +                                            NS_GET_IID(nsIJSIID),
   1.578 +                                            getter_AddRefs(holder)))) {
   1.579 +            RootedObject idobj(cx);
   1.580 +            if (holder &&
   1.581 +                // Assign, not compare
   1.582 +                (idobj = holder->GetJSObject())) {
   1.583 +                *objp = obj;
   1.584 +                *_retval =
   1.585 +                    JS_DefinePropertyById(cx, obj, id,
   1.586 +                                          OBJECT_TO_JSVAL(idobj),
   1.587 +                                          nullptr, nullptr,
   1.588 +                                          JSPROP_ENUMERATE |
   1.589 +                                          JSPROP_READONLY |
   1.590 +                                          JSPROP_PERMANENT);
   1.591 +            }
   1.592 +        }
   1.593 +    }
   1.594 +    return NS_OK;
   1.595 +}
   1.596 +
   1.597 +/***************************************************************************/
   1.598 +/***************************************************************************/
   1.599 +/***************************************************************************/
   1.600 +
   1.601 +
   1.602 +
   1.603 +class nsXPCComponents_Classes :
   1.604 +  public nsIXPCComponents_Classes,
   1.605 +  public nsIXPCScriptable,
   1.606 +  public nsIClassInfo
   1.607 +{
   1.608 +public:
   1.609 +    // all the interface method declarations...
   1.610 +    NS_DECL_ISUPPORTS
   1.611 +    NS_DECL_NSIXPCCOMPONENTS_CLASSES
   1.612 +    NS_DECL_NSIXPCSCRIPTABLE
   1.613 +    NS_DECL_NSICLASSINFO
   1.614 +
   1.615 +public:
   1.616 +    nsXPCComponents_Classes();
   1.617 +    virtual ~nsXPCComponents_Classes();
   1.618 +};
   1.619 +
   1.620 +/***************************************************************************/
   1.621 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   1.622 +                       out nsIIDPtr array); */
   1.623 +NS_IMETHODIMP
   1.624 +nsXPCComponents_Classes::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   1.625 +{
   1.626 +    const uint32_t count = 2;
   1.627 +    *aCount = count;
   1.628 +    nsIID **array;
   1.629 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   1.630 +    if (!array)
   1.631 +        return NS_ERROR_OUT_OF_MEMORY;
   1.632 +
   1.633 +    uint32_t index = 0;
   1.634 +    nsIID* clone;
   1.635 +#define PUSH_IID(id)                                                          \
   1.636 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   1.637 +                                                 sizeof(nsIID)));             \
   1.638 +    if (!clone)                                                               \
   1.639 +        goto oom;                                                             \
   1.640 +    array[index++] = clone;
   1.641 +
   1.642 +    PUSH_IID(nsIXPCComponents_Classes)
   1.643 +    PUSH_IID(nsIXPCScriptable)
   1.644 +#undef PUSH_IID
   1.645 +
   1.646 +    return NS_OK;
   1.647 +oom:
   1.648 +    while (index)
   1.649 +        nsMemory::Free(array[--index]);
   1.650 +    nsMemory::Free(array);
   1.651 +    *aArray = nullptr;
   1.652 +    return NS_ERROR_OUT_OF_MEMORY;
   1.653 +}
   1.654 +
   1.655 +/* nsISupports getHelperForLanguage (in uint32_t language); */
   1.656 +NS_IMETHODIMP
   1.657 +nsXPCComponents_Classes::GetHelperForLanguage(uint32_t language,
   1.658 +                                              nsISupports **retval)
   1.659 +{
   1.660 +    *retval = nullptr;
   1.661 +    return NS_OK;
   1.662 +}
   1.663 +
   1.664 +/* readonly attribute string contractID; */
   1.665 +NS_IMETHODIMP
   1.666 +nsXPCComponents_Classes::GetContractID(char * *aContractID)
   1.667 +{
   1.668 +    *aContractID = nullptr;
   1.669 +    return NS_ERROR_NOT_AVAILABLE;
   1.670 +}
   1.671 +
   1.672 +/* readonly attribute string classDescription; */
   1.673 +NS_IMETHODIMP
   1.674 +nsXPCComponents_Classes::GetClassDescription(char * *aClassDescription)
   1.675 +{
   1.676 +    static const char classDescription[] = "XPCComponents_Classes";
   1.677 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   1.678 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   1.679 +}
   1.680 +
   1.681 +/* readonly attribute nsCIDPtr classID; */
   1.682 +NS_IMETHODIMP
   1.683 +nsXPCComponents_Classes::GetClassID(nsCID * *aClassID)
   1.684 +{
   1.685 +    *aClassID = nullptr;
   1.686 +    return NS_OK;
   1.687 +}
   1.688 +
   1.689 +/* readonly attribute uint32_t implementationLanguage; */
   1.690 +NS_IMETHODIMP
   1.691 +nsXPCComponents_Classes::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   1.692 +{
   1.693 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   1.694 +    return NS_OK;
   1.695 +}
   1.696 +
   1.697 +/* readonly attribute uint32_t flags; */
   1.698 +NS_IMETHODIMP
   1.699 +nsXPCComponents_Classes::GetFlags(uint32_t *aFlags)
   1.700 +{
   1.701 +    *aFlags = 0;
   1.702 +    return NS_OK;
   1.703 +}
   1.704 +
   1.705 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   1.706 +NS_IMETHODIMP
   1.707 +nsXPCComponents_Classes::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   1.708 +{
   1.709 +    return NS_ERROR_NOT_AVAILABLE;
   1.710 +}
   1.711 +
   1.712 +nsXPCComponents_Classes::nsXPCComponents_Classes()
   1.713 +{
   1.714 +}
   1.715 +
   1.716 +nsXPCComponents_Classes::~nsXPCComponents_Classes()
   1.717 +{
   1.718 +    // empty
   1.719 +}
   1.720 +
   1.721 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Classes)
   1.722 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Classes)
   1.723 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   1.724 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   1.725 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Classes)
   1.726 +NS_INTERFACE_MAP_END
   1.727 +
   1.728 +NS_IMPL_ADDREF(nsXPCComponents_Classes)
   1.729 +NS_IMPL_RELEASE(nsXPCComponents_Classes)
   1.730 +
   1.731 +// The nsIXPCScriptable map declaration that will generate stubs for us...
   1.732 +#define XPC_MAP_CLASSNAME           nsXPCComponents_Classes
   1.733 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Classes"
   1.734 +#define                             XPC_MAP_WANT_NEWRESOLVE
   1.735 +#define                             XPC_MAP_WANT_NEWENUMERATE
   1.736 +#define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   1.737 +                                    nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   1.738 +#include "xpc_map_end.h" /* This will #undef the above */
   1.739 +
   1.740 +
   1.741 +/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   1.742 +NS_IMETHODIMP
   1.743 +nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   1.744 +                                      JSContext * cx, JSObject * obj,
   1.745 +                                      uint32_t enum_op, jsval * statep,
   1.746 +                                      jsid * idp, bool *_retval)
   1.747 +{
   1.748 +    nsISimpleEnumerator* e;
   1.749 +
   1.750 +    switch (enum_op) {
   1.751 +        case JSENUMERATE_INIT:
   1.752 +        case JSENUMERATE_INIT_ALL:
   1.753 +        {
   1.754 +            nsCOMPtr<nsIComponentRegistrar> compMgr;
   1.755 +            if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
   1.756 +                NS_FAILED(compMgr->EnumerateContractIDs(&e)) || !e ) {
   1.757 +                *statep = JSVAL_NULL;
   1.758 +                return NS_ERROR_UNEXPECTED;
   1.759 +            }
   1.760 +
   1.761 +            *statep = PRIVATE_TO_JSVAL(e);
   1.762 +            if (idp)
   1.763 +                *idp = INT_TO_JSID(0); // indicate that we don't know the count
   1.764 +            return NS_OK;
   1.765 +        }
   1.766 +        case JSENUMERATE_NEXT:
   1.767 +        {
   1.768 +            nsCOMPtr<nsISupports> isup;
   1.769 +            bool hasMore;
   1.770 +            e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
   1.771 +
   1.772 +            if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
   1.773 +                NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
   1.774 +                nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
   1.775 +                if (holder) {
   1.776 +                    nsAutoCString name;
   1.777 +                    if (NS_SUCCEEDED(holder->GetData(name))) {
   1.778 +                        RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
   1.779 +                        RootedId id(cx);
   1.780 +                        if (idstr && JS_StringToId(cx, idstr, &id)) {
   1.781 +                            *idp = id;
   1.782 +                            return NS_OK;
   1.783 +                        }
   1.784 +                    }
   1.785 +                }
   1.786 +            }
   1.787 +            // else... FALL THROUGH
   1.788 +        }
   1.789 +
   1.790 +        case JSENUMERATE_DESTROY:
   1.791 +        default:
   1.792 +            e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
   1.793 +            NS_IF_RELEASE(e);
   1.794 +            *statep = JSVAL_NULL;
   1.795 +            return NS_OK;
   1.796 +    }
   1.797 +}
   1.798 +
   1.799 +/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
   1.800 +NS_IMETHODIMP
   1.801 +nsXPCComponents_Classes::NewResolve(nsIXPConnectWrappedNative *wrapper,
   1.802 +                                    JSContext *cx, JSObject *objArg,
   1.803 +                                    jsid idArg, JSObject **objp,
   1.804 +                                    bool *_retval)
   1.805 +
   1.806 +{
   1.807 +    RootedId id(cx, idArg);
   1.808 +    RootedObject obj(cx, objArg);
   1.809 +
   1.810 +    JSAutoByteString name;
   1.811 +    if (JSID_IS_STRING(id) &&
   1.812 +        name.encodeLatin1(cx, JSID_TO_STRING(id)) &&
   1.813 +        name.ptr()[0] != '{') { // we only allow contractids here
   1.814 +        nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
   1.815 +        if (nsid) {
   1.816 +            nsXPConnect* xpc = nsXPConnect::XPConnect();
   1.817 +            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   1.818 +            if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
   1.819 +                                             static_cast<nsIJSCID*>(nsid),
   1.820 +                                             NS_GET_IID(nsIJSCID),
   1.821 +                                             getter_AddRefs(holder)))) {
   1.822 +                RootedObject idobj(cx);
   1.823 +                if (holder &&
   1.824 +                    // Assign, not compare
   1.825 +                        (idobj = holder->GetJSObject())) {
   1.826 +                    *objp = obj;
   1.827 +                    *_retval = JS_DefinePropertyById(cx, obj, id,
   1.828 +                                                     OBJECT_TO_JSVAL(idobj),
   1.829 +                                                     nullptr, nullptr,
   1.830 +                                                     JSPROP_ENUMERATE |
   1.831 +                                                     JSPROP_READONLY |
   1.832 +                                                     JSPROP_PERMANENT);
   1.833 +                }
   1.834 +            }
   1.835 +        }
   1.836 +    }
   1.837 +    return NS_OK;
   1.838 +}
   1.839 +
   1.840 +/***************************************************************************/
   1.841 +/***************************************************************************/
   1.842 +/***************************************************************************/
   1.843 +
   1.844 +class nsXPCComponents_ClassesByID :
   1.845 +  public nsIXPCComponents_ClassesByID,
   1.846 +  public nsIXPCScriptable,
   1.847 +  public nsIClassInfo
   1.848 +{
   1.849 +public:
   1.850 +    // all the interface method declarations...
   1.851 +    NS_DECL_ISUPPORTS
   1.852 +    NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID
   1.853 +    NS_DECL_NSIXPCSCRIPTABLE
   1.854 +    NS_DECL_NSICLASSINFO
   1.855 +
   1.856 +public:
   1.857 +    nsXPCComponents_ClassesByID();
   1.858 +    virtual ~nsXPCComponents_ClassesByID();
   1.859 +};
   1.860 +
   1.861 +/***************************************************************************/
   1.862 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   1.863 +                       out nsIIDPtr array); */
   1.864 +NS_IMETHODIMP
   1.865 +nsXPCComponents_ClassesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   1.866 +{
   1.867 +    const uint32_t count = 2;
   1.868 +    *aCount = count;
   1.869 +    nsIID **array;
   1.870 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   1.871 +    if (!array)
   1.872 +        return NS_ERROR_OUT_OF_MEMORY;
   1.873 +
   1.874 +    uint32_t index = 0;
   1.875 +    nsIID* clone;
   1.876 +#define PUSH_IID(id)                                                          \
   1.877 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   1.878 +                                                 sizeof(nsIID)));             \
   1.879 +    if (!clone)                                                               \
   1.880 +        goto oom;                                                             \
   1.881 +    array[index++] = clone;
   1.882 +
   1.883 +    PUSH_IID(nsIXPCComponents_ClassesByID)
   1.884 +    PUSH_IID(nsIXPCScriptable)
   1.885 +#undef PUSH_IID
   1.886 +
   1.887 +    return NS_OK;
   1.888 +oom:
   1.889 +    while (index)
   1.890 +        nsMemory::Free(array[--index]);
   1.891 +    nsMemory::Free(array);
   1.892 +    *aArray = nullptr;
   1.893 +    return NS_ERROR_OUT_OF_MEMORY;
   1.894 +}
   1.895 +
   1.896 +/* nsISupports getHelperForLanguage (in uint32_t language); */
   1.897 +NS_IMETHODIMP
   1.898 +nsXPCComponents_ClassesByID::GetHelperForLanguage(uint32_t language,
   1.899 +                                                  nsISupports **retval)
   1.900 +{
   1.901 +    *retval = nullptr;
   1.902 +    return NS_OK;
   1.903 +}
   1.904 +
   1.905 +/* readonly attribute string contractID; */
   1.906 +NS_IMETHODIMP
   1.907 +nsXPCComponents_ClassesByID::GetContractID(char * *aContractID)
   1.908 +{
   1.909 +    *aContractID = nullptr;
   1.910 +    return NS_ERROR_NOT_AVAILABLE;
   1.911 +}
   1.912 +
   1.913 +/* readonly attribute string classDescription; */
   1.914 +NS_IMETHODIMP
   1.915 +nsXPCComponents_ClassesByID::GetClassDescription(char * *aClassDescription)
   1.916 +{
   1.917 +    static const char classDescription[] = "XPCComponents_ClassesByID";
   1.918 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   1.919 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   1.920 +}
   1.921 +
   1.922 +/* readonly attribute nsCIDPtr classID; */
   1.923 +NS_IMETHODIMP
   1.924 +nsXPCComponents_ClassesByID::GetClassID(nsCID * *aClassID)
   1.925 +{
   1.926 +    *aClassID = nullptr;
   1.927 +    return NS_OK;
   1.928 +}
   1.929 +
   1.930 +/* readonly attribute uint32_t implementationLanguage; */
   1.931 +NS_IMETHODIMP
   1.932 +nsXPCComponents_ClassesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   1.933 +{
   1.934 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   1.935 +    return NS_OK;
   1.936 +}
   1.937 +
   1.938 +/* readonly attribute uint32_t flags; */
   1.939 +NS_IMETHODIMP
   1.940 +nsXPCComponents_ClassesByID::GetFlags(uint32_t *aFlags)
   1.941 +{
   1.942 +    *aFlags = 0;
   1.943 +    return NS_OK;
   1.944 +}
   1.945 +
   1.946 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   1.947 +NS_IMETHODIMP
   1.948 +nsXPCComponents_ClassesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   1.949 +{
   1.950 +    return NS_ERROR_NOT_AVAILABLE;
   1.951 +}
   1.952 +
   1.953 +nsXPCComponents_ClassesByID::nsXPCComponents_ClassesByID()
   1.954 +{
   1.955 +}
   1.956 +
   1.957 +nsXPCComponents_ClassesByID::~nsXPCComponents_ClassesByID()
   1.958 +{
   1.959 +    // empty
   1.960 +}
   1.961 +
   1.962 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ClassesByID)
   1.963 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ClassesByID)
   1.964 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   1.965 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   1.966 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ClassesByID)
   1.967 +NS_INTERFACE_MAP_END
   1.968 +
   1.969 +NS_IMPL_ADDREF(nsXPCComponents_ClassesByID)
   1.970 +NS_IMPL_RELEASE(nsXPCComponents_ClassesByID)
   1.971 +
   1.972 +// The nsIXPCScriptable map declaration that will generate stubs for us...
   1.973 +#define XPC_MAP_CLASSNAME           nsXPCComponents_ClassesByID
   1.974 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ClassesByID"
   1.975 +#define                             XPC_MAP_WANT_NEWRESOLVE
   1.976 +#define                             XPC_MAP_WANT_NEWENUMERATE
   1.977 +#define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   1.978 +                                    nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   1.979 +#include "xpc_map_end.h" /* This will #undef the above */
   1.980 +
   1.981 +/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   1.982 +NS_IMETHODIMP
   1.983 +nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   1.984 +                                          JSContext * cx, JSObject * obj,
   1.985 +                                          uint32_t enum_op, jsval * statep,
   1.986 +                                          jsid * idp, bool *_retval)
   1.987 +{
   1.988 +    nsISimpleEnumerator* e;
   1.989 +
   1.990 +    switch (enum_op) {
   1.991 +        case JSENUMERATE_INIT:
   1.992 +        case JSENUMERATE_INIT_ALL:
   1.993 +        {
   1.994 +            nsCOMPtr<nsIComponentRegistrar> compMgr;
   1.995 +            if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
   1.996 +                NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e ) {
   1.997 +                *statep = JSVAL_NULL;
   1.998 +                return NS_ERROR_UNEXPECTED;
   1.999 +            }
  1.1000 +
  1.1001 +            *statep = PRIVATE_TO_JSVAL(e);
  1.1002 +            if (idp)
  1.1003 +                *idp = INT_TO_JSID(0); // indicate that we don't know the count
  1.1004 +            return NS_OK;
  1.1005 +        }
  1.1006 +        case JSENUMERATE_NEXT:
  1.1007 +        {
  1.1008 +            nsCOMPtr<nsISupports> isup;
  1.1009 +            bool hasMore;
  1.1010 +            e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
  1.1011 +
  1.1012 +            if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
  1.1013 +                NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
  1.1014 +                nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
  1.1015 +                if (holder) {
  1.1016 +                    char* name;
  1.1017 +                    if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
  1.1018 +                        RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
  1.1019 +                        nsMemory::Free(name);
  1.1020 +                        RootedId id(cx);
  1.1021 +                        if (idstr && JS_StringToId(cx, idstr, &id)) {
  1.1022 +                            *idp = id;
  1.1023 +                            return NS_OK;
  1.1024 +                        }
  1.1025 +                    }
  1.1026 +                }
  1.1027 +            }
  1.1028 +            // else... FALL THROUGH
  1.1029 +        }
  1.1030 +
  1.1031 +        case JSENUMERATE_DESTROY:
  1.1032 +        default:
  1.1033 +            e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
  1.1034 +            NS_IF_RELEASE(e);
  1.1035 +            *statep = JSVAL_NULL;
  1.1036 +            return NS_OK;
  1.1037 +    }
  1.1038 +}
  1.1039 +
  1.1040 +static bool
  1.1041 +IsRegisteredCLSID(const char* str)
  1.1042 +{
  1.1043 +    bool registered;
  1.1044 +    nsID id;
  1.1045 +
  1.1046 +    if (!id.Parse(str))
  1.1047 +        return false;
  1.1048 +
  1.1049 +    nsCOMPtr<nsIComponentRegistrar> compMgr;
  1.1050 +    if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
  1.1051 +        NS_FAILED(compMgr->IsCIDRegistered(id, &registered)))
  1.1052 +        return false;
  1.1053 +
  1.1054 +    return registered;
  1.1055 +}
  1.1056 +
  1.1057 +/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
  1.1058 +NS_IMETHODIMP
  1.1059 +nsXPCComponents_ClassesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
  1.1060 +                                        JSContext *cx, JSObject *objArg,
  1.1061 +                                        jsid idArg, JSObject **objp,
  1.1062 +                                        bool *_retval)
  1.1063 +{
  1.1064 +    RootedObject obj(cx, objArg);
  1.1065 +    RootedId id(cx, idArg);
  1.1066 +
  1.1067 +    if (!JSID_IS_STRING(id))
  1.1068 +        return NS_OK;
  1.1069 +
  1.1070 +    JSAutoByteString name;
  1.1071 +    RootedString str(cx, JSID_TO_STRING(id));
  1.1072 +    if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' &&
  1.1073 +        IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
  1.1074 +    {
  1.1075 +        nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
  1.1076 +        if (nsid) {
  1.1077 +            nsXPConnect* xpc = nsXPConnect::XPConnect();
  1.1078 +            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  1.1079 +            if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
  1.1080 +                                             static_cast<nsIJSCID*>(nsid),
  1.1081 +                                             NS_GET_IID(nsIJSCID),
  1.1082 +                                             getter_AddRefs(holder)))) {
  1.1083 +                RootedObject idobj(cx);
  1.1084 +                if (holder &&
  1.1085 +                    // Assign, not compare
  1.1086 +                    (idobj = holder->GetJSObject())) {
  1.1087 +                    *objp = obj;
  1.1088 +                    *_retval = JS_DefinePropertyById(cx, obj, id,
  1.1089 +                                                     ObjectValue(*idobj),
  1.1090 +                                                     nullptr, nullptr,
  1.1091 +                                                     JSPROP_ENUMERATE |
  1.1092 +                                                     JSPROP_READONLY |
  1.1093 +                                                     JSPROP_PERMANENT);
  1.1094 +                }
  1.1095 +            }
  1.1096 +        }
  1.1097 +    }
  1.1098 +    return NS_OK;
  1.1099 +}
  1.1100 +
  1.1101 +
  1.1102 +/***************************************************************************/
  1.1103 +
  1.1104 +// Currently the possible results do not change at runtime, so they are only
  1.1105 +// cached once (unlike ContractIDs, CLSIDs, and IIDs)
  1.1106 +
  1.1107 +class nsXPCComponents_Results :
  1.1108 +  public nsIXPCComponents_Results,
  1.1109 +  public nsIXPCScriptable,
  1.1110 +  public nsIClassInfo
  1.1111 +{
  1.1112 +public:
  1.1113 +    // all the interface method declarations...
  1.1114 +    NS_DECL_ISUPPORTS
  1.1115 +    NS_DECL_NSIXPCCOMPONENTS_RESULTS
  1.1116 +    NS_DECL_NSIXPCSCRIPTABLE
  1.1117 +    NS_DECL_NSICLASSINFO
  1.1118 +
  1.1119 +public:
  1.1120 +    nsXPCComponents_Results();
  1.1121 +    virtual ~nsXPCComponents_Results();
  1.1122 +};
  1.1123 +
  1.1124 +/***************************************************************************/
  1.1125 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1.1126 +                       out nsIIDPtr array); */
  1.1127 +NS_IMETHODIMP
  1.1128 +nsXPCComponents_Results::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1.1129 +{
  1.1130 +    const uint32_t count = 2;
  1.1131 +    *aCount = count;
  1.1132 +    nsIID **array;
  1.1133 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1.1134 +    if (!array)
  1.1135 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1136 +
  1.1137 +    uint32_t index = 0;
  1.1138 +    nsIID* clone;
  1.1139 +#define PUSH_IID(id)                                                          \
  1.1140 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1.1141 +                                                 sizeof(nsIID)));             \
  1.1142 +    if (!clone)                                                               \
  1.1143 +        goto oom;                                                             \
  1.1144 +    array[index++] = clone;
  1.1145 +
  1.1146 +    PUSH_IID(nsIXPCComponents_Results)
  1.1147 +    PUSH_IID(nsIXPCScriptable)
  1.1148 +#undef PUSH_IID
  1.1149 +
  1.1150 +    return NS_OK;
  1.1151 +oom:
  1.1152 +    while (index)
  1.1153 +        nsMemory::Free(array[--index]);
  1.1154 +    nsMemory::Free(array);
  1.1155 +    *aArray = nullptr;
  1.1156 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1157 +}
  1.1158 +
  1.1159 +/* nsISupports getHelperForLanguage (in uint32_t language); */
  1.1160 +NS_IMETHODIMP
  1.1161 +nsXPCComponents_Results::GetHelperForLanguage(uint32_t language,
  1.1162 +                                              nsISupports **retval)
  1.1163 +{
  1.1164 +    *retval = nullptr;
  1.1165 +    return NS_OK;
  1.1166 +}
  1.1167 +
  1.1168 +/* readonly attribute string contractID; */
  1.1169 +NS_IMETHODIMP
  1.1170 +nsXPCComponents_Results::GetContractID(char * *aContractID)
  1.1171 +{
  1.1172 +    *aContractID = nullptr;
  1.1173 +    return NS_ERROR_NOT_AVAILABLE;
  1.1174 +}
  1.1175 +
  1.1176 +/* readonly attribute string classDescription; */
  1.1177 +NS_IMETHODIMP
  1.1178 +nsXPCComponents_Results::GetClassDescription(char * *aClassDescription)
  1.1179 +{
  1.1180 +    static const char classDescription[] = "XPCComponents_Results";
  1.1181 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1.1182 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1.1183 +}
  1.1184 +
  1.1185 +/* readonly attribute nsCIDPtr classID; */
  1.1186 +NS_IMETHODIMP
  1.1187 +nsXPCComponents_Results::GetClassID(nsCID * *aClassID)
  1.1188 +{
  1.1189 +    *aClassID = nullptr;
  1.1190 +    return NS_OK;
  1.1191 +}
  1.1192 +
  1.1193 +/* readonly attribute uint32_t implementationLanguage; */
  1.1194 +NS_IMETHODIMP
  1.1195 +nsXPCComponents_Results::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1.1196 +{
  1.1197 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1.1198 +    return NS_OK;
  1.1199 +}
  1.1200 +
  1.1201 +/* readonly attribute uint32_t flags; */
  1.1202 +NS_IMETHODIMP
  1.1203 +nsXPCComponents_Results::GetFlags(uint32_t *aFlags)
  1.1204 +{
  1.1205 +    // Mark ourselves as a DOM object so that instances may be created in
  1.1206 +    // unprivileged scopes.
  1.1207 +    *aFlags = nsIClassInfo::DOM_OBJECT;
  1.1208 +    return NS_OK;
  1.1209 +}
  1.1210 +
  1.1211 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1.1212 +NS_IMETHODIMP
  1.1213 +nsXPCComponents_Results::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1.1214 +{
  1.1215 +    return NS_ERROR_NOT_AVAILABLE;
  1.1216 +}
  1.1217 +
  1.1218 +nsXPCComponents_Results::nsXPCComponents_Results()
  1.1219 +{
  1.1220 +}
  1.1221 +
  1.1222 +nsXPCComponents_Results::~nsXPCComponents_Results()
  1.1223 +{
  1.1224 +    // empty
  1.1225 +}
  1.1226 +
  1.1227 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Results)
  1.1228 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Results)
  1.1229 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1.1230 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1.1231 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Results)
  1.1232 +NS_INTERFACE_MAP_END
  1.1233 +
  1.1234 +NS_IMPL_ADDREF(nsXPCComponents_Results)
  1.1235 +NS_IMPL_RELEASE(nsXPCComponents_Results)
  1.1236 +
  1.1237 +// The nsIXPCScriptable map declaration that will generate stubs for us...
  1.1238 +#define XPC_MAP_CLASSNAME           nsXPCComponents_Results
  1.1239 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Results"
  1.1240 +#define                             XPC_MAP_WANT_NEWRESOLVE
  1.1241 +#define                             XPC_MAP_WANT_NEWENUMERATE
  1.1242 +#define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
  1.1243 +                                    nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1.1244 +#include "xpc_map_end.h" /* This will #undef the above */
  1.1245 +
  1.1246 +/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
  1.1247 +NS_IMETHODIMP
  1.1248 +nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
  1.1249 +                                      JSContext * cx, JSObject * obj,
  1.1250 +                                      uint32_t enum_op, jsval * statep,
  1.1251 +                                      jsid * idp, bool *_retval)
  1.1252 +{
  1.1253 +    const void** iter;
  1.1254 +
  1.1255 +    switch (enum_op) {
  1.1256 +        case JSENUMERATE_INIT:
  1.1257 +        case JSENUMERATE_INIT_ALL:
  1.1258 +        {
  1.1259 +            if (idp)
  1.1260 +                *idp = INT_TO_JSID(nsXPCException::GetNSResultCount());
  1.1261 +
  1.1262 +            void** space = (void**) new char[sizeof(void*)];
  1.1263 +            *space = nullptr;
  1.1264 +            *statep = PRIVATE_TO_JSVAL(space);
  1.1265 +            return NS_OK;
  1.1266 +        }
  1.1267 +        case JSENUMERATE_NEXT:
  1.1268 +        {
  1.1269 +            const char* name;
  1.1270 +            iter = (const void**) JSVAL_TO_PRIVATE(*statep);
  1.1271 +            if (nsXPCException::IterateNSResults(nullptr, &name, nullptr, iter)) {
  1.1272 +                RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
  1.1273 +                JS::RootedId id(cx);
  1.1274 +                if (idstr && JS_StringToId(cx, idstr, &id)) {
  1.1275 +                    *idp = id;
  1.1276 +                    return NS_OK;
  1.1277 +                }
  1.1278 +            }
  1.1279 +            // else... FALL THROUGH
  1.1280 +        }
  1.1281 +
  1.1282 +        case JSENUMERATE_DESTROY:
  1.1283 +        default:
  1.1284 +            iter = (const void**) JSVAL_TO_PRIVATE(*statep);
  1.1285 +            delete [] (char*) iter;
  1.1286 +            *statep = JSVAL_NULL;
  1.1287 +            return NS_OK;
  1.1288 +    }
  1.1289 +}
  1.1290 +
  1.1291 +
  1.1292 +/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
  1.1293 +NS_IMETHODIMP
  1.1294 +nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper,
  1.1295 +                                    JSContext *cx, JSObject *objArg,
  1.1296 +                                    jsid idArg, JSObject * *objp,
  1.1297 +                                    bool *_retval)
  1.1298 +{
  1.1299 +    RootedObject obj(cx, objArg);
  1.1300 +    RootedId id(cx, idArg);
  1.1301 +    JSAutoByteString name;
  1.1302 +
  1.1303 +    if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) {
  1.1304 +        const char* rv_name;
  1.1305 +        const void* iter = nullptr;
  1.1306 +        nsresult rv;
  1.1307 +        while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) {
  1.1308 +            if (!strcmp(name.ptr(), rv_name)) {
  1.1309 +                jsval val = JS_NumberValue((double)rv);
  1.1310 +
  1.1311 +                *objp = obj;
  1.1312 +                if (!JS_DefinePropertyById(cx, obj, id, val,
  1.1313 +                                           nullptr, nullptr,
  1.1314 +                                           JSPROP_ENUMERATE |
  1.1315 +                                           JSPROP_READONLY |
  1.1316 +                                           JSPROP_PERMANENT)) {
  1.1317 +                    return NS_ERROR_UNEXPECTED;
  1.1318 +                }
  1.1319 +            }
  1.1320 +        }
  1.1321 +    }
  1.1322 +    return NS_OK;
  1.1323 +}
  1.1324 +
  1.1325 +/***************************************************************************/
  1.1326 +// JavaScript Constructor for nsIJSID objects (Components.ID)
  1.1327 +
  1.1328 +class nsXPCComponents_ID :
  1.1329 +  public nsIXPCComponents_ID,
  1.1330 +  public nsIXPCScriptable,
  1.1331 +  public nsIClassInfo
  1.1332 +{
  1.1333 +public:
  1.1334 +    // all the interface method declarations...
  1.1335 +    NS_DECL_ISUPPORTS
  1.1336 +    NS_DECL_NSIXPCCOMPONENTS_ID
  1.1337 +    NS_DECL_NSIXPCSCRIPTABLE
  1.1338 +    NS_DECL_NSICLASSINFO
  1.1339 +
  1.1340 +
  1.1341 +public:
  1.1342 +    nsXPCComponents_ID();
  1.1343 +    virtual ~nsXPCComponents_ID();
  1.1344 +
  1.1345 +private:
  1.1346 +    static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1.1347 +                                    JSContext *cx, HandleObject obj,
  1.1348 +                                    const CallArgs &args, bool *_retval);
  1.1349 +};
  1.1350 +
  1.1351 +/***************************************************************************/
  1.1352 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1.1353 +                       out nsIIDPtr array); */
  1.1354 +NS_IMETHODIMP
  1.1355 +nsXPCComponents_ID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1.1356 +{
  1.1357 +    const uint32_t count = 2;
  1.1358 +    *aCount = count;
  1.1359 +    nsIID **array;
  1.1360 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1.1361 +    if (!array)
  1.1362 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1363 +
  1.1364 +    uint32_t index = 0;
  1.1365 +    nsIID* clone;
  1.1366 +#define PUSH_IID(id)                                                          \
  1.1367 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1.1368 +                                                 sizeof(nsIID)));             \
  1.1369 +    if (!clone)                                                               \
  1.1370 +        goto oom;                                                             \
  1.1371 +    array[index++] = clone;
  1.1372 +
  1.1373 +    PUSH_IID(nsIXPCComponents_ID)
  1.1374 +    PUSH_IID(nsIXPCScriptable)
  1.1375 +#undef PUSH_IID
  1.1376 +
  1.1377 +    return NS_OK;
  1.1378 +oom:
  1.1379 +    while (index)
  1.1380 +        nsMemory::Free(array[--index]);
  1.1381 +    nsMemory::Free(array);
  1.1382 +    *aArray = nullptr;
  1.1383 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1384 +}
  1.1385 +
  1.1386 +/* nsISupports getHelperForLanguage (in uint32_t language); */
  1.1387 +NS_IMETHODIMP
  1.1388 +nsXPCComponents_ID::GetHelperForLanguage(uint32_t language,
  1.1389 +                                         nsISupports **retval)
  1.1390 +{
  1.1391 +    *retval = nullptr;
  1.1392 +    return NS_OK;
  1.1393 +}
  1.1394 +
  1.1395 +/* readonly attribute string contractID; */
  1.1396 +NS_IMETHODIMP
  1.1397 +nsXPCComponents_ID::GetContractID(char * *aContractID)
  1.1398 +{
  1.1399 +    *aContractID = nullptr;
  1.1400 +    return NS_ERROR_NOT_AVAILABLE;
  1.1401 +}
  1.1402 +
  1.1403 +/* readonly attribute string classDescription; */
  1.1404 +NS_IMETHODIMP
  1.1405 +nsXPCComponents_ID::GetClassDescription(char * *aClassDescription)
  1.1406 +{
  1.1407 +    static const char classDescription[] = "XPCComponents_ID";
  1.1408 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1.1409 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1.1410 +}
  1.1411 +
  1.1412 +/* readonly attribute nsCIDPtr classID; */
  1.1413 +NS_IMETHODIMP
  1.1414 +nsXPCComponents_ID::GetClassID(nsCID * *aClassID)
  1.1415 +{
  1.1416 +    *aClassID = nullptr;
  1.1417 +    return NS_OK;
  1.1418 +}
  1.1419 +
  1.1420 +/* readonly attribute uint32_t implementationLanguage; */
  1.1421 +NS_IMETHODIMP
  1.1422 +nsXPCComponents_ID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1.1423 +{
  1.1424 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1.1425 +    return NS_OK;
  1.1426 +}
  1.1427 +
  1.1428 +/* readonly attribute uint32_t flags; */
  1.1429 +NS_IMETHODIMP
  1.1430 +nsXPCComponents_ID::GetFlags(uint32_t *aFlags)
  1.1431 +{
  1.1432 +    *aFlags = 0;
  1.1433 +    return NS_OK;
  1.1434 +}
  1.1435 +
  1.1436 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1.1437 +NS_IMETHODIMP
  1.1438 +nsXPCComponents_ID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1.1439 +{
  1.1440 +    return NS_ERROR_NOT_AVAILABLE;
  1.1441 +}
  1.1442 +
  1.1443 +nsXPCComponents_ID::nsXPCComponents_ID()
  1.1444 +{
  1.1445 +}
  1.1446 +
  1.1447 +nsXPCComponents_ID::~nsXPCComponents_ID()
  1.1448 +{
  1.1449 +    // empty
  1.1450 +}
  1.1451 +
  1.1452 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ID)
  1.1453 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ID)
  1.1454 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1.1455 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1.1456 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ID)
  1.1457 +NS_INTERFACE_MAP_END
  1.1458 +
  1.1459 +NS_IMPL_ADDREF(nsXPCComponents_ID)
  1.1460 +NS_IMPL_RELEASE(nsXPCComponents_ID)
  1.1461 +
  1.1462 +// The nsIXPCScriptable map declaration that will generate stubs for us...
  1.1463 +#define XPC_MAP_CLASSNAME           nsXPCComponents_ID
  1.1464 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ID"
  1.1465 +#define                             XPC_MAP_WANT_CALL
  1.1466 +#define                             XPC_MAP_WANT_CONSTRUCT
  1.1467 +#define                             XPC_MAP_WANT_HASINSTANCE
  1.1468 +#define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1.1469 +#include "xpc_map_end.h" /* This will #undef the above */
  1.1470 +
  1.1471 +
  1.1472 +/* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.1473 +NS_IMETHODIMP
  1.1474 +nsXPCComponents_ID::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1.1475 +                         const CallArgs &args, bool *_retval)
  1.1476 +{
  1.1477 +    RootedObject obj(cx, objArg);
  1.1478 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.1479 +}
  1.1480 +
  1.1481 +/* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.1482 +NS_IMETHODIMP
  1.1483 +nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1.1484 +                              const CallArgs &args, bool *_retval)
  1.1485 +{
  1.1486 +    RootedObject obj(cx, objArg);
  1.1487 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.1488 +}
  1.1489 +
  1.1490 +// static
  1.1491 +nsresult
  1.1492 +nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1.1493 +                                    JSContext *cx, HandleObject obj,
  1.1494 +                                    const CallArgs &args, bool *_retval)
  1.1495 +{
  1.1496 +    // make sure we have at least one arg
  1.1497 +
  1.1498 +    if (args.length() < 1)
  1.1499 +        return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
  1.1500 +
  1.1501 +    // Do the security check if necessary
  1.1502 +
  1.1503 +    nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager();
  1.1504 +    if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsJSID::GetCID()))) {
  1.1505 +        // the security manager vetoed. It should have set an exception.
  1.1506 +        *_retval = false;
  1.1507 +        return NS_OK;
  1.1508 +    }
  1.1509 +
  1.1510 +    // convert the first argument into a string and see if it looks like an id
  1.1511 +
  1.1512 +    JSString* jsstr;
  1.1513 +    JSAutoByteString bytes;
  1.1514 +    nsID id;
  1.1515 +
  1.1516 +    if (!(jsstr = ToString(cx, args[0])) ||
  1.1517 +        !bytes.encodeLatin1(cx, jsstr) ||
  1.1518 +        !id.Parse(bytes.ptr())) {
  1.1519 +        return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
  1.1520 +    }
  1.1521 +
  1.1522 +    // make the new object and return it.
  1.1523 +
  1.1524 +    JSObject* newobj = xpc_NewIDObject(cx, obj, id);
  1.1525 +    if (!newobj)
  1.1526 +        return NS_ERROR_UNEXPECTED;
  1.1527 +
  1.1528 +    args.rval().setObject(*newobj);
  1.1529 +    return NS_OK;
  1.1530 +}
  1.1531 +
  1.1532 +/* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
  1.1533 +NS_IMETHODIMP
  1.1534 +nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative *wrapper,
  1.1535 +                                JSContext *cx, JSObject *obj,
  1.1536 +                                HandleValue val, bool *bp, bool *_retval)
  1.1537 +{
  1.1538 +    if (bp)
  1.1539 +        *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIJSID));
  1.1540 +    return NS_OK;
  1.1541 +}
  1.1542 +
  1.1543 +/***************************************************************************/
  1.1544 +// JavaScript Constructor for nsIXPCException objects (Components.Exception)
  1.1545 +
  1.1546 +class nsXPCComponents_Exception :
  1.1547 +  public nsIXPCComponents_Exception,
  1.1548 +  public nsIXPCScriptable,
  1.1549 +  public nsIClassInfo
  1.1550 +{
  1.1551 +public:
  1.1552 +    // all the interface method declarations...
  1.1553 +    NS_DECL_ISUPPORTS
  1.1554 +    NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
  1.1555 +    NS_DECL_NSIXPCSCRIPTABLE
  1.1556 +    NS_DECL_NSICLASSINFO
  1.1557 +
  1.1558 +
  1.1559 +public:
  1.1560 +    nsXPCComponents_Exception();
  1.1561 +    virtual ~nsXPCComponents_Exception();
  1.1562 +
  1.1563 +private:
  1.1564 +    static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1.1565 +                                    JSContext *cx, HandleObject obj,
  1.1566 +                                    const CallArgs &args, bool *_retval);
  1.1567 +};
  1.1568 +
  1.1569 +/***************************************************************************/
  1.1570 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1.1571 +                       out nsIIDPtr array); */
  1.1572 +NS_IMETHODIMP
  1.1573 +nsXPCComponents_Exception::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1.1574 +{
  1.1575 +    const uint32_t count = 2;
  1.1576 +    *aCount = count;
  1.1577 +    nsIID **array;
  1.1578 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1.1579 +    if (!array)
  1.1580 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1581 +
  1.1582 +    uint32_t index = 0;
  1.1583 +    nsIID* clone;
  1.1584 +#define PUSH_IID(id)                                                          \
  1.1585 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1.1586 +                                                 sizeof(nsIID)));             \
  1.1587 +    if (!clone)                                                               \
  1.1588 +        goto oom;                                                             \
  1.1589 +    array[index++] = clone;
  1.1590 +
  1.1591 +    PUSH_IID(nsIXPCComponents_Exception)
  1.1592 +    PUSH_IID(nsIXPCScriptable)
  1.1593 +#undef PUSH_IID
  1.1594 +
  1.1595 +    return NS_OK;
  1.1596 +oom:
  1.1597 +    while (index)
  1.1598 +        nsMemory::Free(array[--index]);
  1.1599 +    nsMemory::Free(array);
  1.1600 +    *aArray = nullptr;
  1.1601 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1602 +}
  1.1603 +
  1.1604 +/* nsISupports getHelperForLanguage (in uint32_t language); */
  1.1605 +NS_IMETHODIMP
  1.1606 +nsXPCComponents_Exception::GetHelperForLanguage(uint32_t language,
  1.1607 +                                                nsISupports **retval)
  1.1608 +{
  1.1609 +    *retval = nullptr;
  1.1610 +    return NS_OK;
  1.1611 +}
  1.1612 +
  1.1613 +/* readonly attribute string contractID; */
  1.1614 +NS_IMETHODIMP
  1.1615 +nsXPCComponents_Exception::GetContractID(char * *aContractID)
  1.1616 +{
  1.1617 +    *aContractID = nullptr;
  1.1618 +    return NS_ERROR_NOT_AVAILABLE;
  1.1619 +}
  1.1620 +
  1.1621 +/* readonly attribute string classDescription; */
  1.1622 +NS_IMETHODIMP
  1.1623 +nsXPCComponents_Exception::GetClassDescription(char * *aClassDescription)
  1.1624 +{
  1.1625 +    static const char classDescription[] = "XPCComponents_Exception";
  1.1626 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1.1627 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1.1628 +}
  1.1629 +
  1.1630 +/* readonly attribute nsCIDPtr classID; */
  1.1631 +NS_IMETHODIMP
  1.1632 +nsXPCComponents_Exception::GetClassID(nsCID * *aClassID)
  1.1633 +{
  1.1634 +    *aClassID = nullptr;
  1.1635 +    return NS_OK;
  1.1636 +}
  1.1637 +
  1.1638 +/* readonly attribute uint32_t implementationLanguage; */
  1.1639 +NS_IMETHODIMP
  1.1640 +nsXPCComponents_Exception::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1.1641 +{
  1.1642 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1.1643 +    return NS_OK;
  1.1644 +}
  1.1645 +
  1.1646 +/* readonly attribute uint32_t flags; */
  1.1647 +NS_IMETHODIMP
  1.1648 +nsXPCComponents_Exception::GetFlags(uint32_t *aFlags)
  1.1649 +{
  1.1650 +    *aFlags = 0;
  1.1651 +    return NS_OK;
  1.1652 +}
  1.1653 +
  1.1654 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1.1655 +NS_IMETHODIMP
  1.1656 +nsXPCComponents_Exception::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1.1657 +{
  1.1658 +    return NS_ERROR_NOT_AVAILABLE;
  1.1659 +}
  1.1660 +
  1.1661 +nsXPCComponents_Exception::nsXPCComponents_Exception()
  1.1662 +{
  1.1663 +}
  1.1664 +
  1.1665 +nsXPCComponents_Exception::~nsXPCComponents_Exception()
  1.1666 +{
  1.1667 +    // empty
  1.1668 +}
  1.1669 +
  1.1670 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Exception)
  1.1671 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Exception)
  1.1672 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1.1673 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1.1674 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Exception)
  1.1675 +NS_INTERFACE_MAP_END
  1.1676 +
  1.1677 +NS_IMPL_ADDREF(nsXPCComponents_Exception)
  1.1678 +NS_IMPL_RELEASE(nsXPCComponents_Exception)
  1.1679 +
  1.1680 +// The nsIXPCScriptable map declaration that will generate stubs for us...
  1.1681 +#define XPC_MAP_CLASSNAME           nsXPCComponents_Exception
  1.1682 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Exception"
  1.1683 +#define                             XPC_MAP_WANT_CALL
  1.1684 +#define                             XPC_MAP_WANT_CONSTRUCT
  1.1685 +#define                             XPC_MAP_WANT_HASINSTANCE
  1.1686 +#define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1.1687 +#include "xpc_map_end.h" /* This will #undef the above */
  1.1688 +
  1.1689 +
  1.1690 +/* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.1691 +NS_IMETHODIMP
  1.1692 +nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1.1693 +                                const CallArgs &args, bool *_retval)
  1.1694 +{
  1.1695 +    RootedObject obj(cx, objArg);
  1.1696 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.1697 +}
  1.1698 +
  1.1699 +/* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.1700 +NS_IMETHODIMP
  1.1701 +nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1.1702 +                                     JSObject *objArg, const CallArgs &args, bool *_retval)
  1.1703 +{
  1.1704 +    RootedObject obj(cx, objArg);
  1.1705 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.1706 +}
  1.1707 +
  1.1708 +struct MOZ_STACK_CLASS ExceptionArgParser
  1.1709 +{
  1.1710 +    ExceptionArgParser(JSContext *context,
  1.1711 +                       nsXPConnect *xpconnect)
  1.1712 +        : eMsg("exception")
  1.1713 +        , eResult(NS_ERROR_FAILURE)
  1.1714 +        , cx(context)
  1.1715 +        , xpc(xpconnect)
  1.1716 +    {}
  1.1717 +
  1.1718 +    // Public exception parameter values. During construction, these are
  1.1719 +    // initialized to the appropriate defaults.
  1.1720 +    const char*             eMsg;
  1.1721 +    nsresult                eResult;
  1.1722 +    nsCOMPtr<nsIStackFrame> eStack;
  1.1723 +    nsCOMPtr<nsISupports>   eData;
  1.1724 +
  1.1725 +    // Parse the constructor arguments into the above |eFoo| parameter values.
  1.1726 +    bool parse(const CallArgs &args) {
  1.1727 +        /*
  1.1728 +         * The Components.Exception takes a series of arguments, all of them
  1.1729 +         * optional:
  1.1730 +         *
  1.1731 +         * Argument 0: Exception message (defaults to 'exception').
  1.1732 +         * Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options
  1.1733 +         *             object (see below).
  1.1734 +         * Argument 2: Stack (defaults to the current stack, which we trigger
  1.1735 +         *                    by leaving this nullptr in the parser).
  1.1736 +         * Argument 3: Optional user data (defaults to nullptr).
  1.1737 +         *
  1.1738 +         * To dig our way out of this clunky API, we now support passing an
  1.1739 +         * options object as the second parameter (as opposed to a result code).
  1.1740 +         * If this is the case, all subsequent arguments are ignored, and the
  1.1741 +         * following properties are parsed out of the object (using the
  1.1742 +         * associated default if the property does not exist):
  1.1743 +         *
  1.1744 +         *   result:    Result code (see argument 1).
  1.1745 +         *   stack:     Call stack (see argument 2).
  1.1746 +         *   data:      User data (see argument 3).
  1.1747 +         */
  1.1748 +        if (args.length() > 0 && !parseMessage(args[0]))
  1.1749 +            return false;
  1.1750 +        if (args.length() > 1) {
  1.1751 +            if (args[1].isObject()) {
  1.1752 +                RootedObject obj(cx, &args[1].toObject());
  1.1753 +                return parseOptionsObject(obj);
  1.1754 +            }
  1.1755 +            if (!parseResult(args[1]))
  1.1756 +                return false;
  1.1757 +        }
  1.1758 +        if (args.length() > 2) {
  1.1759 +            if (!parseStack(args[2]))
  1.1760 +                return false;
  1.1761 +        }
  1.1762 +        if (args.length() > 3) {
  1.1763 +            if (!parseData(args[3]))
  1.1764 +                return false;
  1.1765 +        }
  1.1766 +        return true;
  1.1767 +    }
  1.1768 +
  1.1769 +  protected:
  1.1770 +
  1.1771 +    /*
  1.1772 +     * Parsing helpers.
  1.1773 +     */
  1.1774 +
  1.1775 +    bool parseMessage(HandleValue v) {
  1.1776 +        JSString *str = ToString(cx, v);
  1.1777 +        if (!str)
  1.1778 +           return false;
  1.1779 +        eMsg = messageBytes.encodeLatin1(cx, str);
  1.1780 +        return !!eMsg;
  1.1781 +    }
  1.1782 +
  1.1783 +    bool parseResult(HandleValue v) {
  1.1784 +        return JS::ToUint32(cx, v, (uint32_t*) &eResult);
  1.1785 +    }
  1.1786 +
  1.1787 +    bool parseStack(HandleValue v) {
  1.1788 +        if (!v.isObject()) {
  1.1789 +            // eStack has already been initialized to null, which is what we want
  1.1790 +            // for any non-object values (including null).
  1.1791 +            return true;
  1.1792 +        }
  1.1793 +
  1.1794 +        return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
  1.1795 +                                        NS_GET_IID(nsIStackFrame),
  1.1796 +                                        getter_AddRefs(eStack)));
  1.1797 +    }
  1.1798 +
  1.1799 +    bool parseData(HandleValue v) {
  1.1800 +        if (!v.isObject()) {
  1.1801 +            // eData has already been initialized to null, which is what we want
  1.1802 +            // for any non-object values (including null).
  1.1803 +            return true;
  1.1804 +        }
  1.1805 +
  1.1806 +        return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
  1.1807 +                                        NS_GET_IID(nsISupports),
  1.1808 +                                        getter_AddRefs(eData)));
  1.1809 +    }
  1.1810 +
  1.1811 +    bool parseOptionsObject(HandleObject obj) {
  1.1812 +        RootedValue v(cx);
  1.1813 +
  1.1814 +        if (!getOption(obj, "result", &v) ||
  1.1815 +            (!v.isUndefined() && !parseResult(v)))
  1.1816 +            return false;
  1.1817 +
  1.1818 +        if (!getOption(obj, "stack", &v) ||
  1.1819 +            (!v.isUndefined() && !parseStack(v)))
  1.1820 +            return false;
  1.1821 +
  1.1822 +        if (!getOption(obj, "data", &v) ||
  1.1823 +            (!v.isUndefined() && !parseData(v)))
  1.1824 +            return false;
  1.1825 +
  1.1826 +        return true;
  1.1827 +    }
  1.1828 +
  1.1829 +    bool getOption(HandleObject obj, const char *name, MutableHandleValue rv) {
  1.1830 +        // Look for the property.
  1.1831 +        bool found;
  1.1832 +        if (!JS_HasProperty(cx, obj, name, &found))
  1.1833 +            return false;
  1.1834 +
  1.1835 +        // If it wasn't found, indicate with undefined.
  1.1836 +        if (!found) {
  1.1837 +            rv.setUndefined();
  1.1838 +            return true;
  1.1839 +        }
  1.1840 +
  1.1841 +        // Get the property.
  1.1842 +        return JS_GetProperty(cx, obj, name, rv);
  1.1843 +    }
  1.1844 +
  1.1845 +    /*
  1.1846 +     * Internal data members.
  1.1847 +     */
  1.1848 +
  1.1849 +    // If there's a non-default exception string, hold onto the allocated bytes.
  1.1850 +    JSAutoByteString messageBytes;
  1.1851 +
  1.1852 +    // Various bits and pieces that are helpful to have around.
  1.1853 +    JSContext *cx;
  1.1854 +    nsXPConnect *xpc;
  1.1855 +};
  1.1856 +
  1.1857 +// static
  1.1858 +nsresult
  1.1859 +nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1.1860 +                                           JSContext *cx, HandleObject obj,
  1.1861 +                                           const CallArgs &args, bool *_retval)
  1.1862 +{
  1.1863 +    nsXPConnect* xpc = nsXPConnect::XPConnect();
  1.1864 +
  1.1865 +    // Do the security check if necessary
  1.1866 +
  1.1867 +    nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
  1.1868 +    if (sm && NS_FAILED(sm->CanCreateInstance(cx, Exception::GetCID()))) {
  1.1869 +        // the security manager vetoed. It should have set an exception.
  1.1870 +        *_retval = false;
  1.1871 +        return NS_OK;
  1.1872 +    }
  1.1873 +
  1.1874 +    // Parse the arguments to the Exception constructor.
  1.1875 +    ExceptionArgParser parser(cx, xpc);
  1.1876 +    if (!parser.parse(args))
  1.1877 +        return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  1.1878 +
  1.1879 +    nsCOMPtr<nsIException> e = new Exception(nsCString(parser.eMsg),
  1.1880 +                                             parser.eResult,
  1.1881 +                                             EmptyCString(),
  1.1882 +                                             parser.eStack,
  1.1883 +                                             parser.eData);
  1.1884 +
  1.1885 +    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  1.1886 +    RootedObject newObj(cx);
  1.1887 +
  1.1888 +    if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
  1.1889 +                                  getter_AddRefs(holder))) || !holder ||
  1.1890 +        // Assign, not compare
  1.1891 +        !(newObj = holder->GetJSObject())) {
  1.1892 +        return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
  1.1893 +    }
  1.1894 +
  1.1895 +    args.rval().setObject(*newObj);
  1.1896 +    return NS_OK;
  1.1897 +}
  1.1898 +
  1.1899 +/* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
  1.1900 +NS_IMETHODIMP
  1.1901 +nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper,
  1.1902 +                                       JSContext * cx, JSObject * obj,
  1.1903 +                                       HandleValue val, bool *bp,
  1.1904 +                                       bool *_retval)
  1.1905 +{
  1.1906 +    using namespace mozilla::dom;
  1.1907 +
  1.1908 +    RootedValue v(cx, val);
  1.1909 +    if (bp) {
  1.1910 +        Exception* e;
  1.1911 +        *bp = NS_SUCCEEDED(UNWRAP_OBJECT(Exception, v.toObjectOrNull(), e)) ||
  1.1912 +              JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException));
  1.1913 +    }
  1.1914 +    return NS_OK;
  1.1915 +}
  1.1916 +
  1.1917 +/***************************************************************************/
  1.1918 +// This class is for the thing returned by "new Component.Constructor".
  1.1919 +
  1.1920 +// XXXjband we use this CID for security check, but security system can't see
  1.1921 +// it since it has no registed factory. Security really kicks in when we try
  1.1922 +// to build a wrapper around an instance.
  1.1923 +
  1.1924 +// {B4A95150-E25A-11d3-8F61-0010A4E73D9A}
  1.1925 +#define NS_XPCCONSTRUCTOR_CID                                                 \
  1.1926 +{ 0xb4a95150, 0xe25a, 0x11d3,                                                 \
  1.1927 +    { 0x8f, 0x61, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
  1.1928 +
  1.1929 +class nsXPCConstructor :
  1.1930 +  public nsIXPCConstructor,
  1.1931 +  public nsIXPCScriptable,
  1.1932 +  public nsIClassInfo
  1.1933 +{
  1.1934 +public:
  1.1935 +    NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID)
  1.1936 +public:
  1.1937 +    // all the interface method declarations...
  1.1938 +    NS_DECL_ISUPPORTS
  1.1939 +    NS_DECL_NSIXPCCONSTRUCTOR
  1.1940 +    NS_DECL_NSIXPCSCRIPTABLE
  1.1941 +    NS_DECL_NSICLASSINFO
  1.1942 +
  1.1943 +public:
  1.1944 +    nsXPCConstructor(); // not implemented
  1.1945 +    nsXPCConstructor(nsIJSCID* aClassID,
  1.1946 +                     nsIJSIID* aInterfaceID,
  1.1947 +                     const char* aInitializer);
  1.1948 +    virtual ~nsXPCConstructor();
  1.1949 +
  1.1950 +private:
  1.1951 +    nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1.1952 +                             JSContext *cx, HandleObject obj,
  1.1953 +                             const CallArgs &args, bool *_retval);
  1.1954 +private:
  1.1955 +    nsRefPtr<nsIJSCID> mClassID;
  1.1956 +    nsRefPtr<nsIJSIID> mInterfaceID;
  1.1957 +    char*              mInitializer;
  1.1958 +};
  1.1959 +
  1.1960 +/***************************************************************************/
  1.1961 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1.1962 +                       out nsIIDPtr array); */
  1.1963 +NS_IMETHODIMP
  1.1964 +nsXPCConstructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1.1965 +{
  1.1966 +    const uint32_t count = 2;
  1.1967 +    *aCount = count;
  1.1968 +    nsIID **array;
  1.1969 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1.1970 +    if (!array)
  1.1971 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1972 +
  1.1973 +    uint32_t index = 0;
  1.1974 +    nsIID* clone;
  1.1975 +#define PUSH_IID(id)                                                          \
  1.1976 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1.1977 +                                                 sizeof(nsIID)));             \
  1.1978 +    if (!clone)                                                               \
  1.1979 +        goto oom;                                                             \
  1.1980 +    array[index++] = clone;
  1.1981 +
  1.1982 +    PUSH_IID(nsIXPCConstructor)
  1.1983 +    PUSH_IID(nsIXPCScriptable)
  1.1984 +#undef PUSH_IID
  1.1985 +
  1.1986 +    return NS_OK;
  1.1987 +oom:
  1.1988 +    while (index)
  1.1989 +        nsMemory::Free(array[--index]);
  1.1990 +    nsMemory::Free(array);
  1.1991 +    *aArray = nullptr;
  1.1992 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1993 +}
  1.1994 +
  1.1995 +/* nsISupports getHelperForLanguage (in uint32_t language); */
  1.1996 +NS_IMETHODIMP
  1.1997 +nsXPCConstructor::GetHelperForLanguage(uint32_t language,
  1.1998 +                                       nsISupports **retval)
  1.1999 +{
  1.2000 +    *retval = nullptr;
  1.2001 +    return NS_OK;
  1.2002 +}
  1.2003 +
  1.2004 +/* readonly attribute string contractID; */
  1.2005 +NS_IMETHODIMP
  1.2006 +nsXPCConstructor::GetContractID(char * *aContractID)
  1.2007 +{
  1.2008 +    *aContractID = nullptr;
  1.2009 +    return NS_ERROR_NOT_AVAILABLE;
  1.2010 +}
  1.2011 +
  1.2012 +/* readonly attribute string classDescription; */
  1.2013 +NS_IMETHODIMP
  1.2014 +nsXPCConstructor::GetClassDescription(char * *aClassDescription)
  1.2015 +{
  1.2016 +    static const char classDescription[] = "XPCConstructor";
  1.2017 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1.2018 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1.2019 +}
  1.2020 +
  1.2021 +/* readonly attribute nsCIDPtr classID; */
  1.2022 +NS_IMETHODIMP
  1.2023 +nsXPCConstructor::GetClassID(nsCID * *aClassID)
  1.2024 +{
  1.2025 +    *aClassID = nullptr;
  1.2026 +    return NS_OK;
  1.2027 +}
  1.2028 +
  1.2029 +/* readonly attribute uint32_t implementationLanguage; */
  1.2030 +NS_IMETHODIMP
  1.2031 +nsXPCConstructor::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1.2032 +{
  1.2033 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1.2034 +    return NS_OK;
  1.2035 +}
  1.2036 +
  1.2037 +/* readonly attribute uint32_t flags; */
  1.2038 +NS_IMETHODIMP
  1.2039 +nsXPCConstructor::GetFlags(uint32_t *aFlags)
  1.2040 +{
  1.2041 +    *aFlags = 0;
  1.2042 +    return NS_OK;
  1.2043 +}
  1.2044 +
  1.2045 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1.2046 +NS_IMETHODIMP
  1.2047 +nsXPCConstructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1.2048 +{
  1.2049 +    return NS_ERROR_NOT_AVAILABLE;
  1.2050 +}
  1.2051 +
  1.2052 +nsXPCConstructor::nsXPCConstructor(nsIJSCID* aClassID,
  1.2053 +                                   nsIJSIID* aInterfaceID,
  1.2054 +                                   const char* aInitializer)
  1.2055 +    : mClassID(aClassID),
  1.2056 +      mInterfaceID(aInterfaceID)
  1.2057 +{
  1.2058 +    mInitializer = aInitializer ?
  1.2059 +        (char*) nsMemory::Clone(aInitializer, strlen(aInitializer)+1) :
  1.2060 +        nullptr;
  1.2061 +}
  1.2062 +
  1.2063 +nsXPCConstructor::~nsXPCConstructor()
  1.2064 +{
  1.2065 +    if (mInitializer)
  1.2066 +        nsMemory::Free(mInitializer);
  1.2067 +}
  1.2068 +
  1.2069 +/* readonly attribute nsIJSCID classID; */
  1.2070 +NS_IMETHODIMP
  1.2071 +nsXPCConstructor::GetClassID(nsIJSCID * *aClassID)
  1.2072 +{
  1.2073 +    nsRefPtr<nsIJSCID> rval = mClassID;
  1.2074 +    rval.forget(aClassID);
  1.2075 +    return NS_OK;
  1.2076 +}
  1.2077 +
  1.2078 +/* readonly attribute nsIJSIID interfaceID; */
  1.2079 +NS_IMETHODIMP
  1.2080 +nsXPCConstructor::GetInterfaceID(nsIJSIID * *aInterfaceID)
  1.2081 +{
  1.2082 +    nsRefPtr<nsIJSIID> rval = mInterfaceID;
  1.2083 +    rval.forget(aInterfaceID);
  1.2084 +    return NS_OK;
  1.2085 +}
  1.2086 +
  1.2087 +/* readonly attribute string initializer; */
  1.2088 +NS_IMETHODIMP
  1.2089 +nsXPCConstructor::GetInitializer(char * *aInitializer)
  1.2090 +{
  1.2091 +    XPC_STRING_GETTER_BODY(aInitializer, mInitializer);
  1.2092 +}
  1.2093 +
  1.2094 +NS_INTERFACE_MAP_BEGIN(nsXPCConstructor)
  1.2095 +  NS_INTERFACE_MAP_ENTRY(nsIXPCConstructor)
  1.2096 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1.2097 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1.2098 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCConstructor)
  1.2099 +NS_INTERFACE_MAP_END
  1.2100 +
  1.2101 +NS_IMPL_ADDREF(nsXPCConstructor)
  1.2102 +NS_IMPL_RELEASE(nsXPCConstructor)
  1.2103 +
  1.2104 +// The nsIXPCScriptable map declaration that will generate stubs for us...
  1.2105 +#define XPC_MAP_CLASSNAME           nsXPCConstructor
  1.2106 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCConstructor"
  1.2107 +#define                             XPC_MAP_WANT_CALL
  1.2108 +#define                             XPC_MAP_WANT_CONSTRUCT
  1.2109 +#define XPC_MAP_FLAGS               0
  1.2110 +#include "xpc_map_end.h" /* This will #undef the above */
  1.2111 +
  1.2112 +
  1.2113 +/* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.2114 +NS_IMETHODIMP
  1.2115 +nsXPCConstructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1.2116 +                       const CallArgs &args, bool *_retval)
  1.2117 +{
  1.2118 +    RootedObject obj(cx, objArg);
  1.2119 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.2120 +
  1.2121 +}
  1.2122 +
  1.2123 +/* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.2124 +NS_IMETHODIMP
  1.2125 +nsXPCConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1.2126 +                            const CallArgs &args, bool *_retval)
  1.2127 +{
  1.2128 +    RootedObject obj(cx, objArg);
  1.2129 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.2130 +}
  1.2131 +
  1.2132 +// static
  1.2133 +nsresult
  1.2134 +nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,JSContext *cx,
  1.2135 +                                  HandleObject obj, const CallArgs &args, bool *_retval)
  1.2136 +{
  1.2137 +    nsXPConnect* xpc = nsXPConnect::XPConnect();
  1.2138 +
  1.2139 +    // security check not required because we are going to call through the
  1.2140 +    // code which is reflected into JS which will do that for us later.
  1.2141 +
  1.2142 +    nsCOMPtr<nsIXPConnectJSObjectHolder> cidHolder;
  1.2143 +    nsCOMPtr<nsIXPConnectJSObjectHolder> iidHolder;
  1.2144 +    RootedObject cidObj(cx);
  1.2145 +    RootedObject iidObj(cx);
  1.2146 +
  1.2147 +    if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID),
  1.2148 +                                  getter_AddRefs(cidHolder))) || !cidHolder ||
  1.2149 +        // Assign, not compare
  1.2150 +        !(cidObj = cidHolder->GetJSObject()) ||
  1.2151 +        NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID),
  1.2152 +                                  getter_AddRefs(iidHolder))) || !iidHolder ||
  1.2153 +        // Assign, not compare
  1.2154 +        !(iidObj = iidHolder->GetJSObject())) {
  1.2155 +        return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
  1.2156 +    }
  1.2157 +
  1.2158 +    JS::Rooted<JS::Value> arg(cx, ObjectValue(*iidObj));
  1.2159 +    RootedValue rval(cx);
  1.2160 +    if (!JS_CallFunctionName(cx, cidObj, "createInstance", arg, &rval) ||
  1.2161 +        rval.isPrimitive()) {
  1.2162 +        // createInstance will have thrown an exception
  1.2163 +        *_retval = false;
  1.2164 +        return NS_OK;
  1.2165 +    }
  1.2166 +
  1.2167 +    args.rval().set(rval);
  1.2168 +
  1.2169 +    // call initializer method if supplied
  1.2170 +    if (mInitializer) {
  1.2171 +        RootedObject newObj(cx, &rval.toObject());
  1.2172 +        // first check existence of function property for better error reporting
  1.2173 +        RootedValue fun(cx);
  1.2174 +        if (!JS_GetProperty(cx, newObj, mInitializer, &fun) ||
  1.2175 +            fun.isPrimitive()) {
  1.2176 +            return ThrowAndFail(NS_ERROR_XPC_BAD_INITIALIZER_NAME, cx, _retval);
  1.2177 +        }
  1.2178 +
  1.2179 +        RootedValue dummy(cx);
  1.2180 +        if (!JS_CallFunctionValue(cx, newObj, fun, args, &dummy)) {
  1.2181 +            // function should have thrown an exception
  1.2182 +            *_retval = false;
  1.2183 +            return NS_OK;
  1.2184 +        }
  1.2185 +    }
  1.2186 +
  1.2187 +    return NS_OK;
  1.2188 +}
  1.2189 +
  1.2190 +/*******************************************************/
  1.2191 +// JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
  1.2192 +
  1.2193 +class nsXPCComponents_Constructor :
  1.2194 +  public nsIXPCComponents_Constructor,
  1.2195 +  public nsIXPCScriptable,
  1.2196 +  public nsIClassInfo
  1.2197 +{
  1.2198 +public:
  1.2199 +    // all the interface method declarations...
  1.2200 +    NS_DECL_ISUPPORTS
  1.2201 +    NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
  1.2202 +    NS_DECL_NSIXPCSCRIPTABLE
  1.2203 +    NS_DECL_NSICLASSINFO
  1.2204 +
  1.2205 +public:
  1.2206 +    nsXPCComponents_Constructor();
  1.2207 +    virtual ~nsXPCComponents_Constructor();
  1.2208 +
  1.2209 +private:
  1.2210 +    static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1.2211 +                                    JSContext *cx, HandleObject obj,
  1.2212 +                                    const CallArgs &args, bool *_retval);
  1.2213 +};
  1.2214 +
  1.2215 +/***************************************************************************/
  1.2216 +/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1.2217 +                       out nsIIDPtr array); */
  1.2218 +NS_IMETHODIMP
  1.2219 +nsXPCComponents_Constructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1.2220 +{
  1.2221 +    const uint32_t count = 2;
  1.2222 +    *aCount = count;
  1.2223 +    nsIID **array;
  1.2224 +    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1.2225 +    if (!array)
  1.2226 +        return NS_ERROR_OUT_OF_MEMORY;
  1.2227 +
  1.2228 +    uint32_t index = 0;
  1.2229 +    nsIID* clone;
  1.2230 +#define PUSH_IID(id)                                                          \
  1.2231 +    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1.2232 +                                                 sizeof(nsIID)));             \
  1.2233 +    if (!clone)                                                               \
  1.2234 +        goto oom;                                                             \
  1.2235 +    array[index++] = clone;
  1.2236 +
  1.2237 +    PUSH_IID(nsIXPCComponents_Constructor)
  1.2238 +    PUSH_IID(nsIXPCScriptable)
  1.2239 +#undef PUSH_IID
  1.2240 +
  1.2241 +    return NS_OK;
  1.2242 +oom:
  1.2243 +    while (index)
  1.2244 +        nsMemory::Free(array[--index]);
  1.2245 +    nsMemory::Free(array);
  1.2246 +    *aArray = nullptr;
  1.2247 +    return NS_ERROR_OUT_OF_MEMORY;
  1.2248 +}
  1.2249 +
  1.2250 +/* nsISupports getHelperForLanguage (in uint32_t language); */
  1.2251 +NS_IMETHODIMP
  1.2252 +nsXPCComponents_Constructor::GetHelperForLanguage(uint32_t language,
  1.2253 +                                                  nsISupports **retval)
  1.2254 +{
  1.2255 +    *retval = nullptr;
  1.2256 +    return NS_OK;
  1.2257 +}
  1.2258 +
  1.2259 +/* readonly attribute string contractID; */
  1.2260 +NS_IMETHODIMP
  1.2261 +nsXPCComponents_Constructor::GetContractID(char * *aContractID)
  1.2262 +{
  1.2263 +    *aContractID = nullptr;
  1.2264 +    return NS_ERROR_NOT_AVAILABLE;
  1.2265 +}
  1.2266 +
  1.2267 +/* readonly attribute string classDescription; */
  1.2268 +NS_IMETHODIMP
  1.2269 +nsXPCComponents_Constructor::GetClassDescription(char * *aClassDescription)
  1.2270 +{
  1.2271 +    static const char classDescription[] = "XPCComponents_Constructor";
  1.2272 +    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1.2273 +    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1.2274 +}
  1.2275 +
  1.2276 +/* readonly attribute nsCIDPtr classID; */
  1.2277 +NS_IMETHODIMP
  1.2278 +nsXPCComponents_Constructor::GetClassID(nsCID * *aClassID)
  1.2279 +{
  1.2280 +    *aClassID = nullptr;
  1.2281 +    return NS_OK;
  1.2282 +}
  1.2283 +
  1.2284 +/* readonly attribute uint32_t implementationLanguage; */
  1.2285 +NS_IMETHODIMP
  1.2286 +nsXPCComponents_Constructor::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1.2287 +{
  1.2288 +    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1.2289 +    return NS_OK;
  1.2290 +}
  1.2291 +
  1.2292 +/* readonly attribute uint32_t flags; */
  1.2293 +NS_IMETHODIMP
  1.2294 +nsXPCComponents_Constructor::GetFlags(uint32_t *aFlags)
  1.2295 +{
  1.2296 +    *aFlags = 0;
  1.2297 +    return NS_OK;
  1.2298 +}
  1.2299 +
  1.2300 +/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1.2301 +NS_IMETHODIMP
  1.2302 +nsXPCComponents_Constructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1.2303 +{
  1.2304 +    return NS_ERROR_NOT_AVAILABLE;
  1.2305 +}
  1.2306 +
  1.2307 +nsXPCComponents_Constructor::nsXPCComponents_Constructor()
  1.2308 +{
  1.2309 +}
  1.2310 +
  1.2311 +nsXPCComponents_Constructor::~nsXPCComponents_Constructor()
  1.2312 +{
  1.2313 +    // empty
  1.2314 +}
  1.2315 +
  1.2316 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Constructor)
  1.2317 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Constructor)
  1.2318 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1.2319 +  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1.2320 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Constructor)
  1.2321 +NS_INTERFACE_MAP_END
  1.2322 +
  1.2323 +NS_IMPL_ADDREF(nsXPCComponents_Constructor)
  1.2324 +NS_IMPL_RELEASE(nsXPCComponents_Constructor)
  1.2325 +
  1.2326 +// The nsIXPCScriptable map declaration that will generate stubs for us...
  1.2327 +#define XPC_MAP_CLASSNAME           nsXPCComponents_Constructor
  1.2328 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Constructor"
  1.2329 +#define                             XPC_MAP_WANT_CALL
  1.2330 +#define                             XPC_MAP_WANT_CONSTRUCT
  1.2331 +#define                             XPC_MAP_WANT_HASINSTANCE
  1.2332 +#define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1.2333 +#include "xpc_map_end.h" /* This will #undef the above */
  1.2334 +
  1.2335 +
  1.2336 +/* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.2337 +NS_IMETHODIMP
  1.2338 +nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1.2339 +                                  JSObject *objArg, const CallArgs &args, bool *_retval)
  1.2340 +{
  1.2341 +    RootedObject obj(cx, objArg);
  1.2342 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.2343 +}
  1.2344 +
  1.2345 +/* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1.2346 +NS_IMETHODIMP
  1.2347 +nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1.2348 +                                       JSObject *objArg, const CallArgs &args, bool *_retval)
  1.2349 +{
  1.2350 +    RootedObject obj(cx, objArg);
  1.2351 +    return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1.2352 +}
  1.2353 +
  1.2354 +// static
  1.2355 +nsresult
  1.2356 +nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1.2357 +                                             JSContext *cx, HandleObject obj,
  1.2358 +                                             const CallArgs &args, bool *_retval)
  1.2359 +{
  1.2360 +    // make sure we have at least one arg
  1.2361 +
  1.2362 +    if (args.length() < 1)
  1.2363 +        return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
  1.2364 +
  1.2365 +    // get the various other object pointers we need
  1.2366 +
  1.2367 +    nsXPConnect* xpc = nsXPConnect::XPConnect();
  1.2368 +    XPCWrappedNativeScope* scope = GetObjectScope(obj);
  1.2369 +    nsCOMPtr<nsIXPCComponents> comp;
  1.2370 +
  1.2371 +    if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents())))
  1.2372 +        return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  1.2373 +
  1.2374 +    // Do the security check if necessary
  1.2375 +
  1.2376 +    nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
  1.2377 +    if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCConstructor::GetCID()))) {
  1.2378 +        // the security manager vetoed. It should have set an exception.
  1.2379 +        *_retval = false;
  1.2380 +        return NS_OK;
  1.2381 +    }
  1.2382 +
  1.2383 +    // initialization params for the Constructor object we will create
  1.2384 +    nsCOMPtr<nsIJSCID> cClassID;
  1.2385 +    nsCOMPtr<nsIJSIID> cInterfaceID;
  1.2386 +    const char*        cInitializer = nullptr;
  1.2387 +    JSAutoByteString  cInitializerBytes;
  1.2388 +
  1.2389 +    if (args.length() >= 3) {
  1.2390 +        // args[2] is an initializer function or property name
  1.2391 +        RootedString str(cx, ToString(cx, args[2]));
  1.2392 +        if (!str || !(cInitializer = cInitializerBytes.encodeLatin1(cx, str)))
  1.2393 +            return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  1.2394 +    }
  1.2395 +
  1.2396 +    if (args.length() >= 2) {
  1.2397 +        // args[1] is an iid name string
  1.2398 +        // XXXjband support passing "Components.interfaces.foo"?
  1.2399 +
  1.2400 +        nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
  1.2401 +        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  1.2402 +        RootedObject ifacesObj(cx);
  1.2403 +
  1.2404 +        // we do the lookup by asking the Components.interfaces object
  1.2405 +        // for the property with this name - i.e. we let its caching of these
  1.2406 +        // nsIJSIID objects work for us.
  1.2407 +
  1.2408 +        if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
  1.2409 +            NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
  1.2410 +                                      NS_GET_IID(nsIXPCComponents_Interfaces),
  1.2411 +                                      getter_AddRefs(holder))) || !holder ||
  1.2412 +            // Assign, not compare
  1.2413 +            !(ifacesObj = holder->GetJSObject())) {
  1.2414 +            return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  1.2415 +        }
  1.2416 +
  1.2417 +        RootedString str(cx, ToString(cx, args[1]));
  1.2418 +        RootedId id(cx);
  1.2419 +        if (!str || !JS_StringToId(cx, str, &id))
  1.2420 +            return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  1.2421 +
  1.2422 +        RootedValue val(cx);
  1.2423 +        if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive())
  1.2424 +            return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
  1.2425 +
  1.2426 +        nsCOMPtr<nsIXPConnectWrappedNative> wn;
  1.2427 +        if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(),
  1.2428 +                                                      getter_AddRefs(wn))) || !wn ||
  1.2429 +            !(cInterfaceID = do_QueryWrappedNative(wn))) {
  1.2430 +            return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  1.2431 +        }
  1.2432 +    } else {
  1.2433 +        nsCOMPtr<nsIInterfaceInfo> info;
  1.2434 +        xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info));
  1.2435 +
  1.2436 +        if (info) {
  1.2437 +            cInterfaceID = nsJSIID::NewID(info);
  1.2438 +        }
  1.2439 +        if (!cInterfaceID)
  1.2440 +            return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  1.2441 +    }
  1.2442 +
  1.2443 +    // a new scope to avoid warnings about shadowed names
  1.2444 +    {
  1.2445 +        // argv[0] is a contractid name string
  1.2446 +        // XXXjband support passing "Components.classes.foo"?
  1.2447 +
  1.2448 +        // we do the lookup by asking the Components.classes object
  1.2449 +        // for the property with this name - i.e. we let its caching of these
  1.2450 +        // nsIJSCID objects work for us.
  1.2451 +
  1.2452 +        nsCOMPtr<nsIXPCComponents_Classes> classes;
  1.2453 +        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  1.2454 +        RootedObject classesObj(cx);
  1.2455 +
  1.2456 +        if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
  1.2457 +            NS_FAILED(xpc->WrapNative(cx, obj, classes,
  1.2458 +                                      NS_GET_IID(nsIXPCComponents_Classes),
  1.2459 +                                      getter_AddRefs(holder))) || !holder ||
  1.2460 +            // Assign, not compare
  1.2461 +            !(classesObj = holder->GetJSObject())) {
  1.2462 +            return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  1.2463 +        }
  1.2464 +
  1.2465 +        RootedString str(cx, ToString(cx, args[0]));
  1.2466 +        RootedId id(cx);
  1.2467 +        if (!str || !JS_StringToId(cx, str, &id))
  1.2468 +            return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  1.2469 +
  1.2470 +        RootedValue val(cx);
  1.2471 +        if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive())
  1.2472 +            return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
  1.2473 +
  1.2474 +        nsCOMPtr<nsIXPConnectWrappedNative> wn;
  1.2475 +        if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val),
  1.2476 +                                                      getter_AddRefs(wn))) || !wn ||
  1.2477 +            !(cClassID = do_QueryWrappedNative(wn))) {
  1.2478 +            return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  1.2479 +        }
  1.2480 +    }
  1.2481 +
  1.2482 +    nsCOMPtr<nsIXPCConstructor> ctor = new nsXPCConstructor(cClassID, cInterfaceID, cInitializer);
  1.2483 +    nsCOMPtr<nsIXPConnectJSObjectHolder> holder2;
  1.2484 +    RootedObject newObj(cx);
  1.2485 +
  1.2486 +    if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor),
  1.2487 +                                  getter_AddRefs(holder2))) || !holder2 ||
  1.2488 +        // Assign, not compare
  1.2489 +        !(newObj = holder2->GetJSObject())) {
  1.2490 +        return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
  1.2491 +    }
  1.2492 +
  1.2493 +    args.rval().setObject(*newObj);
  1.2494 +    return NS_OK;
  1.2495 +}
  1.2496 +
  1.2497 +/* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
  1.2498 +NS_IMETHODIMP
  1.2499 +nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
  1.2500 +                                         JSContext * cx, JSObject * obj,
  1.2501 +                                         HandleValue val, bool *bp,
  1.2502 +                                         bool *_retval)
  1.2503 +{
  1.2504 +    if (bp)
  1.2505 +        *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIXPCConstructor));
  1.2506 +    return NS_OK;
  1.2507 +}
  1.2508 +
  1.2509 +class nsXPCComponents_Utils :
  1.2510 +            public nsIXPCComponents_Utils,
  1.2511 +            public nsIXPCScriptable
  1.2512 +{
  1.2513 +public:
  1.2514 +    // all the interface method declarations...
  1.2515 +    NS_DECL_ISUPPORTS
  1.2516 +    NS_DECL_NSIXPCSCRIPTABLE
  1.2517 +    NS_DECL_NSIXPCCOMPONENTS_UTILS
  1.2518 +
  1.2519 +public:
  1.2520 +    nsXPCComponents_Utils() { }
  1.2521 +    virtual ~nsXPCComponents_Utils() { }
  1.2522 +
  1.2523 +private:
  1.2524 +    nsCOMPtr<nsIXPCComponents_utils_Sandbox> mSandbox;
  1.2525 +};
  1.2526 +
  1.2527 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils)
  1.2528 +  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils)
  1.2529 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1.2530 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils)
  1.2531 +NS_INTERFACE_MAP_END
  1.2532 +
  1.2533 +NS_IMPL_ADDREF(nsXPCComponents_Utils)
  1.2534 +NS_IMPL_RELEASE(nsXPCComponents_Utils)
  1.2535 +
  1.2536 +// The nsIXPCScriptable map declaration that will generate stubs for us...
  1.2537 +#define XPC_MAP_CLASSNAME           nsXPCComponents_Utils
  1.2538 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Utils"
  1.2539 +#define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1.2540 +#include "xpc_map_end.h" /* This will #undef the above */
  1.2541 +
  1.2542 +NS_IMETHODIMP
  1.2543 +nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox **aSandbox)
  1.2544 +{
  1.2545 +    NS_ENSURE_ARG_POINTER(aSandbox);
  1.2546 +    if (!mSandbox)
  1.2547 +        mSandbox = NewSandboxConstructor();
  1.2548 +
  1.2549 +    nsCOMPtr<nsIXPCComponents_utils_Sandbox> rval = mSandbox;
  1.2550 +    rval.forget(aSandbox);
  1.2551 +    return NS_OK;
  1.2552 +}
  1.2553 +
  1.2554 +/* void reportError (); */
  1.2555 +NS_IMETHODIMP
  1.2556 +nsXPCComponents_Utils::ReportError(HandleValue error, JSContext *cx)
  1.2557 +{
  1.2558 +    // This function shall never fail! Silently eat any failure conditions.
  1.2559 +
  1.2560 +    nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  1.2561 +
  1.2562 +    nsCOMPtr<nsIScriptError> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
  1.2563 +
  1.2564 +    if (!scripterr || !console)
  1.2565 +        return NS_OK;
  1.2566 +
  1.2567 +    const uint64_t innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
  1.2568 +
  1.2569 +    RootedObject errorObj(cx, error.isObject() ? &error.toObject() : nullptr);
  1.2570 +    JSErrorReport *err = errorObj ? JS_ErrorFromException(cx, errorObj) : nullptr;
  1.2571 +    if (err) {
  1.2572 +        // It's a proper JS Error
  1.2573 +        nsAutoString fileUni;
  1.2574 +        CopyUTF8toUTF16(err->filename, fileUni);
  1.2575 +
  1.2576 +        uint32_t column = err->uctokenptr - err->uclinebuf;
  1.2577 +
  1.2578 +        const char16_t* ucmessage =
  1.2579 +            static_cast<const char16_t*>(err->ucmessage);
  1.2580 +        const char16_t* uclinebuf =
  1.2581 +            static_cast<const char16_t*>(err->uclinebuf);
  1.2582 +
  1.2583 +        nsresult rv = scripterr->InitWithWindowID(
  1.2584 +                ucmessage ? nsDependentString(ucmessage) : EmptyString(),
  1.2585 +                fileUni,
  1.2586 +                uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
  1.2587 +                err->lineno,
  1.2588 +                column, err->flags, "XPConnect JavaScript", innerWindowID);
  1.2589 +        NS_ENSURE_SUCCESS(rv, NS_OK);
  1.2590 +
  1.2591 +        console->LogMessage(scripterr);
  1.2592 +        return NS_OK;
  1.2593 +    }
  1.2594 +
  1.2595 +    // It's not a JS Error object, so we synthesize as best we're able.
  1.2596 +    RootedString msgstr(cx, ToString(cx, error));
  1.2597 +    if (!msgstr)
  1.2598 +        return NS_OK;
  1.2599 +
  1.2600 +    nsCOMPtr<nsIStackFrame> frame;
  1.2601 +    nsXPConnect *xpc = nsXPConnect::XPConnect();
  1.2602 +    xpc->GetCurrentJSStack(getter_AddRefs(frame));
  1.2603 +
  1.2604 +    nsString fileName;
  1.2605 +    int32_t lineNo = 0;
  1.2606 +    if (frame) {
  1.2607 +        frame->GetFilename(fileName);
  1.2608 +        frame->GetLineNumber(&lineNo);
  1.2609 +    }
  1.2610 +
  1.2611 +    const jschar *msgchars = JS_GetStringCharsZ(cx, msgstr);
  1.2612 +    if (!msgchars)
  1.2613 +        return NS_OK;
  1.2614 +
  1.2615 +    nsresult rv = scripterr->InitWithWindowID(
  1.2616 +            nsDependentString(static_cast<const char16_t *>(msgchars)),
  1.2617 +            fileName, EmptyString(), lineNo, 0, 0,
  1.2618 +            "XPConnect JavaScript", innerWindowID);
  1.2619 +    NS_ENSURE_SUCCESS(rv, NS_OK);
  1.2620 +
  1.2621 +    console->LogMessage(scripterr);
  1.2622 +    return NS_OK;
  1.2623 +}
  1.2624 +
  1.2625 +/* void evalInSandbox(in AString source, in nativeobj sandbox); */
  1.2626 +NS_IMETHODIMP
  1.2627 +nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
  1.2628 +                                     HandleValue sandboxVal,
  1.2629 +                                     HandleValue version,
  1.2630 +                                     const nsACString& filenameArg,
  1.2631 +                                     int32_t lineNumber,
  1.2632 +                                     JSContext *cx,
  1.2633 +                                     uint8_t optionalArgc,
  1.2634 +                                     MutableHandleValue retval)
  1.2635 +{
  1.2636 +    RootedObject sandbox(cx);
  1.2637 +    if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox)
  1.2638 +        return NS_ERROR_INVALID_ARG;
  1.2639 +
  1.2640 +    // Optional third argument: JS version, as a string.
  1.2641 +    JSVersion jsVersion = JSVERSION_DEFAULT;
  1.2642 +    if (optionalArgc >= 1) {
  1.2643 +        JSString *jsVersionStr = ToString(cx, version);
  1.2644 +        if (!jsVersionStr)
  1.2645 +            return NS_ERROR_INVALID_ARG;
  1.2646 +
  1.2647 +        JSAutoByteString bytes(cx, jsVersionStr);
  1.2648 +        if (!bytes)
  1.2649 +            return NS_ERROR_INVALID_ARG;
  1.2650 +
  1.2651 +        jsVersion = JS_StringToVersion(bytes.ptr());
  1.2652 +        // Explicitly check for "latest", which we support for sandboxes but
  1.2653 +        // isn't in the set of web-exposed version strings.
  1.2654 +        if (jsVersion == JSVERSION_UNKNOWN &&
  1.2655 +            !strcmp(bytes.ptr(), "latest"))
  1.2656 +        {
  1.2657 +            jsVersion = JSVERSION_LATEST;
  1.2658 +        }
  1.2659 +        if (jsVersion == JSVERSION_UNKNOWN)
  1.2660 +            return NS_ERROR_INVALID_ARG;
  1.2661 +    }
  1.2662 +
  1.2663 +    // Optional fourth and fifth arguments: filename and line number.
  1.2664 +    int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1;
  1.2665 +    nsCString filename;
  1.2666 +    if (!filenameArg.IsVoid()) {
  1.2667 +        filename.Assign(filenameArg);
  1.2668 +    } else {
  1.2669 +        // Get the current source info from xpc.
  1.2670 +        nsresult rv;
  1.2671 +        nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
  1.2672 +        NS_ENSURE_SUCCESS(rv, rv);
  1.2673 +
  1.2674 +        nsCOMPtr<nsIStackFrame> frame;
  1.2675 +        xpc->GetCurrentJSStack(getter_AddRefs(frame));
  1.2676 +        if (frame) {
  1.2677 +            nsString frameFile;
  1.2678 +            frame->GetFilename(frameFile);
  1.2679 +            CopyUTF16toUTF8(frameFile, filename);
  1.2680 +            frame->GetLineNumber(&lineNo);
  1.2681 +        }
  1.2682 +    }
  1.2683 +
  1.2684 +    return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo,
  1.2685 +                              jsVersion, false, retval);
  1.2686 +}
  1.2687 +
  1.2688 +NS_IMETHODIMP
  1.2689 +nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal,
  1.2690 +                                          JSContext *cx, MutableHandleValue rval)
  1.2691 +{
  1.2692 +    if (!sandboxVal.isObject())
  1.2693 +        return NS_ERROR_INVALID_ARG;
  1.2694 +
  1.2695 +    RootedObject sandbox(cx, &sandboxVal.toObject());
  1.2696 +    sandbox = js::CheckedUnwrap(sandbox);
  1.2697 +    if (!sandbox || !xpc::IsSandbox(sandbox))
  1.2698 +        return NS_ERROR_INVALID_ARG;
  1.2699 +
  1.2700 +    return xpc::GetSandboxMetadata(cx, sandbox, rval);
  1.2701 +}
  1.2702 +
  1.2703 +NS_IMETHODIMP
  1.2704 +nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal,
  1.2705 +                                          HandleValue metadataVal,
  1.2706 +                                          JSContext *cx)
  1.2707 +{
  1.2708 +    if (!sandboxVal.isObject())
  1.2709 +        return NS_ERROR_INVALID_ARG;
  1.2710 +
  1.2711 +    RootedObject sandbox(cx, &sandboxVal.toObject());
  1.2712 +    sandbox = js::CheckedUnwrap(sandbox);
  1.2713 +    if (!sandbox || !xpc::IsSandbox(sandbox))
  1.2714 +        return NS_ERROR_INVALID_ARG;
  1.2715 +
  1.2716 +    nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadataVal);
  1.2717 +    NS_ENSURE_SUCCESS(rv, rv);
  1.2718 +
  1.2719 +    return NS_OK;
  1.2720 +}
  1.2721 +
  1.2722 +/* JSObject import (in AUTF8String registryLocation,
  1.2723 + *                  [optional] in JSObject targetObj);
  1.2724 + */
  1.2725 +NS_IMETHODIMP
  1.2726 +nsXPCComponents_Utils::Import(const nsACString& registryLocation,
  1.2727 +                              HandleValue targetObj,
  1.2728 +                              JSContext* cx,
  1.2729 +                              uint8_t optionalArgc,
  1.2730 +                              MutableHandleValue retval)
  1.2731 +{
  1.2732 +    nsCOMPtr<xpcIJSModuleLoader> moduleloader =
  1.2733 +        do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
  1.2734 +    if (!moduleloader)
  1.2735 +        return NS_ERROR_FAILURE;
  1.2736 +    return moduleloader->Import(registryLocation, targetObj, cx, optionalArgc, retval);
  1.2737 +}
  1.2738 +
  1.2739 +/* unload (in AUTF8String registryLocation);
  1.2740 + */
  1.2741 +NS_IMETHODIMP
  1.2742 +nsXPCComponents_Utils::Unload(const nsACString & registryLocation)
  1.2743 +{
  1.2744 +    nsCOMPtr<xpcIJSModuleLoader> moduleloader =
  1.2745 +        do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
  1.2746 +    if (!moduleloader)
  1.2747 +        return NS_ERROR_FAILURE;
  1.2748 +    return moduleloader->Unload(registryLocation);
  1.2749 +}
  1.2750 +
  1.2751 +/*
  1.2752 + * JSObject importGlobalProperties (in jsval aPropertyList);
  1.2753 + */
  1.2754 +NS_IMETHODIMP
  1.2755 +nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
  1.2756 +                                              JSContext* cx)
  1.2757 +{
  1.2758 +    RootedObject global(cx, CurrentGlobalOrNull(cx));
  1.2759 +    MOZ_ASSERT(global);
  1.2760 +    GlobalProperties options(false);
  1.2761 +    NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
  1.2762 +    RootedObject propertyList(cx, &aPropertyList.toObject());
  1.2763 +    NS_ENSURE_TRUE(JS_IsArrayObject(cx, propertyList), NS_ERROR_INVALID_ARG);
  1.2764 +    if (!options.Parse(cx, propertyList) ||
  1.2765 +        !options.Define(cx, global))
  1.2766 +    {
  1.2767 +        return NS_ERROR_FAILURE;
  1.2768 +    }
  1.2769 +
  1.2770 +    return NS_OK;
  1.2771 +}
  1.2772 +
  1.2773 +/* xpcIJSWeakReference getWeakReference (); */
  1.2774 +NS_IMETHODIMP
  1.2775 +nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext *cx,
  1.2776 +                                        xpcIJSWeakReference **_retval)
  1.2777 +{
  1.2778 +    nsRefPtr<xpcJSWeakReference> ref = new xpcJSWeakReference();
  1.2779 +    nsresult rv = ref->Init(cx, object);
  1.2780 +    NS_ENSURE_SUCCESS(rv, rv);
  1.2781 +    ref.forget(_retval);
  1.2782 +    return NS_OK;
  1.2783 +}
  1.2784 +
  1.2785 +/* void forceGC (); */
  1.2786 +NS_IMETHODIMP
  1.2787 +nsXPCComponents_Utils::ForceGC()
  1.2788 +{
  1.2789 +    JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
  1.2790 +    PrepareForFullGC(rt);
  1.2791 +    GCForReason(rt, gcreason::COMPONENT_UTILS);
  1.2792 +    return NS_OK;
  1.2793 +}
  1.2794 +
  1.2795 +/* void forceCC (); */
  1.2796 +NS_IMETHODIMP
  1.2797 +nsXPCComponents_Utils::ForceCC()
  1.2798 +{
  1.2799 +    nsJSContext::CycleCollectNow();
  1.2800 +    return NS_OK;
  1.2801 +}
  1.2802 +
  1.2803 +/* void forceShrinkingGC (); */
  1.2804 +NS_IMETHODIMP
  1.2805 +nsXPCComponents_Utils::ForceShrinkingGC()
  1.2806 +{
  1.2807 +    JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
  1.2808 +    PrepareForFullGC(rt);
  1.2809 +    ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
  1.2810 +    return NS_OK;
  1.2811 +}
  1.2812 +
  1.2813 +class PreciseGCRunnable : public nsRunnable
  1.2814 +{
  1.2815 +  public:
  1.2816 +    PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking)
  1.2817 +    : mCallback(aCallback), mShrinking(aShrinking) {}
  1.2818 +
  1.2819 +    NS_IMETHOD Run()
  1.2820 +    {
  1.2821 +        JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
  1.2822 +
  1.2823 +        JSContext *cx;
  1.2824 +        JSContext *iter = nullptr;
  1.2825 +        while ((cx = JS_ContextIterator(rt, &iter)) != nullptr) {
  1.2826 +            if (JS_IsRunning(cx)) {
  1.2827 +                return NS_DispatchToMainThread(this);
  1.2828 +            }
  1.2829 +        }
  1.2830 +
  1.2831 +        PrepareForFullGC(rt);
  1.2832 +        if (mShrinking)
  1.2833 +            ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
  1.2834 +        else
  1.2835 +            GCForReason(rt, gcreason::COMPONENT_UTILS);
  1.2836 +
  1.2837 +        mCallback->Callback();
  1.2838 +        return NS_OK;
  1.2839 +    }
  1.2840 +
  1.2841 +  private:
  1.2842 +    nsRefPtr<ScheduledGCCallback> mCallback;
  1.2843 +    bool mShrinking;
  1.2844 +};
  1.2845 +
  1.2846 +/* void schedulePreciseGC(in ScheduledGCCallback callback); */
  1.2847 +NS_IMETHODIMP
  1.2848 +nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback)
  1.2849 +{
  1.2850 +    nsRefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, false);
  1.2851 +    return NS_DispatchToMainThread(event);
  1.2852 +}
  1.2853 +
  1.2854 +/* void schedulePreciseShrinkingGC(in ScheduledGCCallback callback); */
  1.2855 +NS_IMETHODIMP
  1.2856 +nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback)
  1.2857 +{
  1.2858 +    nsRefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, true);
  1.2859 +    return NS_DispatchToMainThread(event);
  1.2860 +}
  1.2861 +
  1.2862 +/* void unlinkGhostWindows(); */
  1.2863 +NS_IMETHODIMP
  1.2864 +nsXPCComponents_Utils::UnlinkGhostWindows()
  1.2865 +{
  1.2866 +#ifdef DEBUG
  1.2867 +    nsWindowMemoryReporter::UnlinkGhostWindows();
  1.2868 +    return NS_OK;
  1.2869 +#else
  1.2870 +    return NS_ERROR_NOT_IMPLEMENTED;
  1.2871 +#endif
  1.2872 +}
  1.2873 +
  1.2874 +/* [implicit_jscontext] jsval nondeterministicGetWeakMapKeys(in jsval aMap); */
  1.2875 +NS_IMETHODIMP
  1.2876 +nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(HandleValue aMap,
  1.2877 +                                                      JSContext *aCx,
  1.2878 +                                                      MutableHandleValue aKeys)
  1.2879 +{
  1.2880 +    if (!aMap.isObject()) {
  1.2881 +        aKeys.setUndefined();
  1.2882 +        return NS_OK;
  1.2883 +    }
  1.2884 +    RootedObject objRet(aCx);
  1.2885 +    RootedObject mapObj(aCx, &aMap.toObject());
  1.2886 +    if (!JS_NondeterministicGetWeakMapKeys(aCx, mapObj, &objRet))
  1.2887 +        return NS_ERROR_OUT_OF_MEMORY;
  1.2888 +     aKeys.set(objRet ? ObjectValue(*objRet) : UndefinedValue());
  1.2889 +    return NS_OK;
  1.2890 +}
  1.2891 +
  1.2892 +/* void getDebugObject(); */
  1.2893 +NS_IMETHODIMP
  1.2894 +nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx,
  1.2895 +                                             MutableHandleValue retval)
  1.2896 +{
  1.2897 +    JSObject *obj = js::GetTestingFunctions(cx);
  1.2898 +    if (!obj)
  1.2899 +        return NS_ERROR_XPC_JAVASCRIPT_ERROR;
  1.2900 +    retval.setObject(*obj);
  1.2901 +    return NS_OK;
  1.2902 +}
  1.2903 +
  1.2904 +/* void getGlobalForObject(); */
  1.2905 +NS_IMETHODIMP
  1.2906 +nsXPCComponents_Utils::GetGlobalForObject(HandleValue object,
  1.2907 +                                          JSContext *cx,
  1.2908 +                                          MutableHandleValue retval)
  1.2909 +{
  1.2910 +    // First argument must be an object.
  1.2911 +    if (object.isPrimitive())
  1.2912 +        return NS_ERROR_XPC_BAD_CONVERT_JS;
  1.2913 +
  1.2914 +    // Wrappers are parented to their the global in their home compartment. But
  1.2915 +    // when getting the global for a cross-compartment wrapper, we really want
  1.2916 +    // a wrapper for the foreign global. So we need to unwrap before getting the
  1.2917 +    // parent, enter the compartment for the duration of the call, and wrap the
  1.2918 +    // result.
  1.2919 +    Rooted<JSObject*> obj(cx, &object.toObject());
  1.2920 +    obj = js::UncheckedUnwrap(obj);
  1.2921 +    {
  1.2922 +        JSAutoCompartment ac(cx, obj);
  1.2923 +        obj = JS_GetGlobalForObject(cx, obj);
  1.2924 +    }
  1.2925 +
  1.2926 +    if (!JS_WrapObject(cx, &obj))
  1.2927 +        return NS_ERROR_FAILURE;
  1.2928 +
  1.2929 +    // Outerize if necessary.
  1.2930 +    if (JSObjectOp outerize = js::GetObjectClass(obj)->ext.outerObject)
  1.2931 +      obj = outerize(cx, obj);
  1.2932 +
  1.2933 +    retval.setObject(*obj);
  1.2934 +    return NS_OK;
  1.2935 +}
  1.2936 +
  1.2937 +/* jsval createObjectIn(in jsval vobj); */
  1.2938 +bool
  1.2939 +xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectInOptions &options,
  1.2940 +                    MutableHandleValue rval)
  1.2941 +{
  1.2942 +    if (!vobj.isObject()) {
  1.2943 +        JS_ReportError(cx, "Expected an object as the target scope");
  1.2944 +        return false;
  1.2945 +    }
  1.2946 +
  1.2947 +    RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject()));
  1.2948 +    if (!scope) {
  1.2949 +        JS_ReportError(cx, "Permission denied to create object in the target scope");
  1.2950 +        return false;
  1.2951 +    }
  1.2952 +
  1.2953 +    bool define = !JSID_IS_VOID(options.defineAs);
  1.2954 +
  1.2955 +    if (define && js::IsScriptedProxy(scope)) {
  1.2956 +        JS_ReportError(cx, "Defining property on proxy object is not allowed");
  1.2957 +        return false;
  1.2958 +    }
  1.2959 +
  1.2960 +    RootedObject obj(cx);
  1.2961 +    {
  1.2962 +        JSAutoCompartment ac(cx, scope);
  1.2963 +        obj = JS_NewObject(cx, nullptr, JS::NullPtr(), scope);
  1.2964 +        if (!obj)
  1.2965 +            return false;
  1.2966 +
  1.2967 +        if (define) {
  1.2968 +            if (!JS_DefinePropertyById(cx, scope, options.defineAs, ObjectValue(*obj),
  1.2969 +                                       JS_PropertyStub, JS_StrictPropertyStub,
  1.2970 +                                       JSPROP_ENUMERATE))
  1.2971 +                return false;
  1.2972 +        }
  1.2973 +    }
  1.2974 +
  1.2975 +    rval.setObject(*obj);
  1.2976 +    if (!WrapperFactory::WaiveXrayAndWrap(cx, rval))
  1.2977 +        return false;
  1.2978 +
  1.2979 +    return true;
  1.2980 +}
  1.2981 +
  1.2982 +/* boolean isProxy(in value vobj); */
  1.2983 +NS_IMETHODIMP
  1.2984 +nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext *cx, bool *rval)
  1.2985 +{
  1.2986 +    if (!vobj.isObject()) {
  1.2987 +        *rval = false;
  1.2988 +        return NS_OK;
  1.2989 +    }
  1.2990 +
  1.2991 +    RootedObject obj(cx, &vobj.toObject());
  1.2992 +    obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
  1.2993 +    NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
  1.2994 +
  1.2995 +    *rval = js::IsScriptedProxy(obj);
  1.2996 +    return NS_OK;
  1.2997 +}
  1.2998 +
  1.2999 +/* jsval evalInWindow(in string source, in jsval window); */
  1.3000 +NS_IMETHODIMP
  1.3001 +nsXPCComponents_Utils::EvalInWindow(const nsAString &source, HandleValue window,
  1.3002 +                                    JSContext *cx, MutableHandleValue rval)
  1.3003 +{
  1.3004 +    if (!window.isObject())
  1.3005 +        return NS_ERROR_INVALID_ARG;
  1.3006 +
  1.3007 +    RootedObject rwindow(cx, &window.toObject());
  1.3008 +    if (!xpc::EvalInWindow(cx, source, rwindow, rval))
  1.3009 +        return NS_ERROR_FAILURE;
  1.3010 +    return NS_OK;
  1.3011 +}
  1.3012 +
  1.3013 +/* jsval exportFunction(in jsval vfunction, in jsval vscope, in jsval voptions); */
  1.3014 +NS_IMETHODIMP
  1.3015 +nsXPCComponents_Utils::ExportFunction(HandleValue vfunction, HandleValue vscope,
  1.3016 +                                      HandleValue voptions, JSContext *cx,
  1.3017 +                                      MutableHandleValue rval)
  1.3018 +{
  1.3019 +    if (!xpc::ExportFunction(cx, vfunction, vscope, voptions, rval))
  1.3020 +        return NS_ERROR_FAILURE;
  1.3021 +    return NS_OK;
  1.3022 +}
  1.3023 +
  1.3024 +/* jsval createObjectIn(in jsval vobj, [optional] in jsval voptions); */
  1.3025 +NS_IMETHODIMP
  1.3026 +nsXPCComponents_Utils::CreateObjectIn(HandleValue vobj, HandleValue voptions,
  1.3027 +                                      JSContext *cx, MutableHandleValue rval)
  1.3028 +{
  1.3029 +    RootedObject optionsObject(cx, voptions.isObject() ? &voptions.toObject()
  1.3030 +                                                       : nullptr);
  1.3031 +    CreateObjectInOptions options(cx, optionsObject);
  1.3032 +    if (voptions.isObject() &&
  1.3033 +        !options.Parse())
  1.3034 +    {
  1.3035 +        return NS_ERROR_FAILURE;
  1.3036 +    }
  1.3037 +
  1.3038 +    if (!xpc::CreateObjectIn(cx, vobj, options, rval))
  1.3039 +        return NS_ERROR_FAILURE;
  1.3040 +    return NS_OK;
  1.3041 +}
  1.3042 +
  1.3043 +/* void makeObjectPropsNormal(jsval vobj); */
  1.3044 +NS_IMETHODIMP
  1.3045 +nsXPCComponents_Utils::MakeObjectPropsNormal(HandleValue vobj, JSContext *cx)
  1.3046 +{
  1.3047 +    if (!cx)
  1.3048 +        return NS_ERROR_FAILURE;
  1.3049 +
  1.3050 +    // first argument must be an object
  1.3051 +    if (vobj.isPrimitive())
  1.3052 +        return NS_ERROR_XPC_BAD_CONVERT_JS;
  1.3053 +
  1.3054 +    RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
  1.3055 +    JSAutoCompartment ac(cx, obj);
  1.3056 +    AutoIdArray ida(cx, JS_Enumerate(cx, obj));
  1.3057 +    if (!ida)
  1.3058 +        return NS_ERROR_FAILURE;
  1.3059 +
  1.3060 +    RootedId id(cx);
  1.3061 +    RootedValue v(cx);
  1.3062 +    for (size_t i = 0; i < ida.length(); ++i) {
  1.3063 +        id = ida[i];
  1.3064 +
  1.3065 +        if (!JS_GetPropertyById(cx, obj, id, &v))
  1.3066 +            return NS_ERROR_FAILURE;
  1.3067 +
  1.3068 +        if (v.isPrimitive())
  1.3069 +            continue;
  1.3070 +
  1.3071 +        RootedObject propobj(cx, &v.toObject());
  1.3072 +        // TODO Deal with non-functions.
  1.3073 +        if (!js::IsWrapper(propobj) || !JS_ObjectIsCallable(cx, propobj))
  1.3074 +            continue;
  1.3075 +
  1.3076 +        if (!NewFunctionForwarder(cx, id, propobj, /* doclone = */ false, &v) ||
  1.3077 +            !JS_SetPropertyById(cx, obj, id, v))
  1.3078 +            return NS_ERROR_FAILURE;
  1.3079 +    }
  1.3080 +
  1.3081 +    return NS_OK;
  1.3082 +}
  1.3083 +
  1.3084 +NS_IMETHODIMP
  1.3085 +nsXPCComponents_Utils::IsDeadWrapper(HandleValue obj, bool *out)
  1.3086 +{
  1.3087 +    *out = false;
  1.3088 +    if (obj.isPrimitive())
  1.3089 +        return NS_ERROR_INVALID_ARG;
  1.3090 +
  1.3091 +    // Make sure to unwrap first. Once a proxy is nuked, it ceases to be a
  1.3092 +    // wrapper, meaning that, if passed to another compartment, we'll generate
  1.3093 +    // a CCW for it. Make sure that IsDeadWrapper sees through the confusion.
  1.3094 +    *out = JS_IsDeadWrapper(js::CheckedUnwrap(&obj.toObject()));
  1.3095 +    return NS_OK;
  1.3096 +}
  1.3097 +
  1.3098 +/* void recomputerWrappers(jsval vobj); */
  1.3099 +NS_IMETHODIMP
  1.3100 +nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext *cx)
  1.3101 +{
  1.3102 +    // Determine the compartment of the given object, if any.
  1.3103 +    JSCompartment *c = vobj.isObject()
  1.3104 +                       ? js::GetObjectCompartment(js::UncheckedUnwrap(&vobj.toObject()))
  1.3105 +                       : nullptr;
  1.3106 +
  1.3107 +    // If no compartment was given, recompute all.
  1.3108 +    if (!c)
  1.3109 +        js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments());
  1.3110 +    // Otherwise, recompute wrappers for the given compartment.
  1.3111 +    else
  1.3112 +        js::RecomputeWrappers(cx, js::SingleCompartment(c), js::AllCompartments()) &&
  1.3113 +        js::RecomputeWrappers(cx, js::AllCompartments(), js::SingleCompartment(c));
  1.3114 +
  1.3115 +    return NS_OK;
  1.3116 +}
  1.3117 +
  1.3118 +/* jsval setWantXrays(jsval vscope); */
  1.3119 +NS_IMETHODIMP
  1.3120 +nsXPCComponents_Utils::SetWantXrays(HandleValue vscope, JSContext *cx)
  1.3121 +{
  1.3122 +    if (!vscope.isObject())
  1.3123 +        return NS_ERROR_INVALID_ARG;
  1.3124 +    JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
  1.3125 +    JSCompartment *compartment = js::GetObjectCompartment(scopeObj);
  1.3126 +    EnsureCompartmentPrivate(scopeObj)->wantXrays = true;
  1.3127 +    bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
  1.3128 +                                    js::AllCompartments());
  1.3129 +    NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
  1.3130 +    return NS_OK;
  1.3131 +}
  1.3132 +
  1.3133 +/* jsval forcePrivilegedComponentsForScope(jsval vscope); */
  1.3134 +NS_IMETHODIMP
  1.3135 +nsXPCComponents_Utils::ForcePrivilegedComponentsForScope(HandleValue vscope,
  1.3136 +                                                         JSContext *cx)
  1.3137 +{
  1.3138 +    if (!vscope.isObject())
  1.3139 +        return NS_ERROR_INVALID_ARG;
  1.3140 +    JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
  1.3141 +    XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
  1.3142 +    scope->ForcePrivilegedComponents();
  1.3143 +    return NS_OK;
  1.3144 +}
  1.3145 +
  1.3146 +/* jsval getComponentsForScope(jsval vscope); */
  1.3147 +NS_IMETHODIMP
  1.3148 +nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext *cx,
  1.3149 +                                             MutableHandleValue rval)
  1.3150 +{
  1.3151 +    if (!vscope.isObject())
  1.3152 +        return NS_ERROR_INVALID_ARG;
  1.3153 +    JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
  1.3154 +    XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
  1.3155 +    RootedObject components(cx);
  1.3156 +    if (!scope->GetComponentsJSObject(&components))
  1.3157 +        return NS_ERROR_FAILURE;
  1.3158 +    if (!JS_WrapObject(cx, &components))
  1.3159 +        return NS_ERROR_FAILURE;
  1.3160 +    rval.setObject(*components);
  1.3161 +    return NS_OK;
  1.3162 +}
  1.3163 +
  1.3164 +NS_IMETHODIMP
  1.3165 +nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
  1.3166 +                                JSContext *cx)
  1.3167 +{
  1.3168 +    RootedValue runnable(cx, runnableArg);
  1.3169 +    // Enter the given compartment, if any, and rewrap runnable.
  1.3170 +    Maybe<JSAutoCompartment> ac;
  1.3171 +    if (scope.isObject()) {
  1.3172 +        JSObject *scopeObj = js::UncheckedUnwrap(&scope.toObject());
  1.3173 +        if (!scopeObj)
  1.3174 +            return NS_ERROR_FAILURE;
  1.3175 +        ac.construct(cx, scopeObj);
  1.3176 +        if (!JS_WrapValue(cx, &runnable))
  1.3177 +            return NS_ERROR_FAILURE;
  1.3178 +    }
  1.3179 +
  1.3180 +    // Get an XPCWrappedJS for |runnable|.
  1.3181 +    if (!runnable.isObject())
  1.3182 +        return NS_ERROR_INVALID_ARG;
  1.3183 +
  1.3184 +    nsCOMPtr<nsIRunnable> run;
  1.3185 +    nsresult rv = nsXPConnect::XPConnect()->WrapJS(cx, &runnable.toObject(),
  1.3186 +                                                   NS_GET_IID(nsIRunnable),
  1.3187 +                                                   getter_AddRefs(run));
  1.3188 +    NS_ENSURE_SUCCESS(rv, rv);
  1.3189 +    MOZ_ASSERT(run);
  1.3190 +
  1.3191 +    // Dispatch.
  1.3192 +    return NS_DispatchToMainThread(run);
  1.3193 +}
  1.3194 +
  1.3195 +#define GENERATE_JSCONTEXTOPTION_GETTER_SETTER(_attr, _getter, _setter) \
  1.3196 +    NS_IMETHODIMP                                                       \
  1.3197 +    nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue)     \
  1.3198 +    {                                                                   \
  1.3199 +        *aValue = ContextOptionsRef(cx)._getter();                      \
  1.3200 +        return NS_OK;                                                   \
  1.3201 +    }                                                                   \
  1.3202 +    NS_IMETHODIMP                                                       \
  1.3203 +    nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue)      \
  1.3204 +    {                                                                   \
  1.3205 +        ContextOptionsRef(cx)._setter(aValue);                          \
  1.3206 +        return NS_OK;                                                   \
  1.3207 +    }
  1.3208 +
  1.3209 +#define GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(_attr, _getter, _setter) \
  1.3210 +    NS_IMETHODIMP                                                       \
  1.3211 +    nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue)     \
  1.3212 +    {                                                                   \
  1.3213 +        *aValue = RuntimeOptionsRef(cx)._getter();                      \
  1.3214 +        return NS_OK;                                                   \
  1.3215 +    }                                                                   \
  1.3216 +    NS_IMETHODIMP                                                       \
  1.3217 +    nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue)      \
  1.3218 +    {                                                                   \
  1.3219 +        RuntimeOptionsRef(cx)._setter(aValue);                          \
  1.3220 +        return NS_OK;                                                   \
  1.3221 +    }
  1.3222 +
  1.3223 +GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
  1.3224 +GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Werror, werror, setWerror)
  1.3225 +GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
  1.3226 +GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Ion, ion, setIon)
  1.3227 +
  1.3228 +#undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
  1.3229 +#undef GENERATE_JSRUNTIMEOPTION_GETTER_SETTER
  1.3230 +
  1.3231 +NS_IMETHODIMP
  1.3232 +nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx)
  1.3233 +{
  1.3234 +#ifdef JS_GC_ZEAL
  1.3235 +    JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ);
  1.3236 +#endif
  1.3237 +    return NS_OK;
  1.3238 +}
  1.3239 +
  1.3240 +NS_IMETHODIMP
  1.3241 +nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext *cx)
  1.3242 +{
  1.3243 +    NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG);
  1.3244 +    JSObject *wrapper = &obj.toObject();
  1.3245 +    NS_ENSURE_TRUE(IsWrapper(wrapper), NS_ERROR_INVALID_ARG);
  1.3246 +    JSObject *sb = UncheckedUnwrap(wrapper);
  1.3247 +    NS_ENSURE_TRUE(IsSandbox(sb), NS_ERROR_INVALID_ARG);
  1.3248 +    NukeCrossCompartmentWrappers(cx, AllCompartments(),
  1.3249 +                                 SingleCompartment(GetObjectCompartment(sb)),
  1.3250 +                                 NukeWindowReferences);
  1.3251 +    return NS_OK;
  1.3252 +}
  1.3253 +
  1.3254 +NS_IMETHODIMP
  1.3255 +nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
  1.3256 +                                            JSContext *cx)
  1.3257 +{
  1.3258 +    NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
  1.3259 +    RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
  1.3260 +                                            /* stopAtOuter = */ false));
  1.3261 +    NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
  1.3262 +    if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
  1.3263 +        JS_ReportError(cx, "Script may not be disabled for system globals");
  1.3264 +        return NS_ERROR_FAILURE;
  1.3265 +    }
  1.3266 +    Scriptability::Get(global).Block();
  1.3267 +    return NS_OK;
  1.3268 +}
  1.3269 +
  1.3270 +NS_IMETHODIMP
  1.3271 +nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
  1.3272 +                                              JSContext *cx)
  1.3273 +{
  1.3274 +    NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
  1.3275 +    RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
  1.3276 +                                            /* stopAtOuter = */ false));
  1.3277 +    NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
  1.3278 +    if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
  1.3279 +        JS_ReportError(cx, "Script may not be disabled for system globals");
  1.3280 +        return NS_ERROR_FAILURE;
  1.3281 +    }
  1.3282 +    Scriptability::Get(global).Unblock();
  1.3283 +    return NS_OK;
  1.3284 +}
  1.3285 +
  1.3286 +NS_IMETHODIMP
  1.3287 +nsXPCComponents_Utils::IsXrayWrapper(HandleValue obj, bool* aRetval)
  1.3288 +{
  1.3289 +    *aRetval =
  1.3290 +        obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
  1.3291 +    return NS_OK;
  1.3292 +}
  1.3293 +
  1.3294 +NS_IMETHODIMP
  1.3295 +nsXPCComponents_Utils::WaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval)
  1.3296 +{
  1.3297 +    RootedValue value(aCx, aVal);
  1.3298 +    if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value))
  1.3299 +        return NS_ERROR_FAILURE;
  1.3300 +    aRetval.set(value);
  1.3301 +    return NS_OK;
  1.3302 +}
  1.3303 +
  1.3304 +NS_IMETHODIMP
  1.3305 +nsXPCComponents_Utils::UnwaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval)
  1.3306 +{
  1.3307 +    if (!aVal.isObject()) {
  1.3308 +        aRetval.set(aVal);
  1.3309 +        return NS_OK;
  1.3310 +    }
  1.3311 +
  1.3312 +    RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject()));
  1.3313 +    if (!JS_WrapObject(aCx, &obj))
  1.3314 +        return NS_ERROR_FAILURE;
  1.3315 +    aRetval.setObject(*obj);
  1.3316 +    return NS_OK;
  1.3317 +}
  1.3318 +
  1.3319 +NS_IMETHODIMP
  1.3320 +nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap, JSContext *aCx, char **aRv)
  1.3321 +{
  1.3322 +    if (!aObj.isObject())
  1.3323 +        return NS_ERROR_INVALID_ARG;
  1.3324 +    RootedObject obj(aCx, &aObj.toObject());
  1.3325 +    if (aUnwrap)
  1.3326 +        obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
  1.3327 +    *aRv = NS_strdup(js::GetObjectClass(obj)->name);
  1.3328 +    NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY);
  1.3329 +    return NS_OK;
  1.3330 +}
  1.3331 +
  1.3332 +NS_IMETHODIMP
  1.3333 +nsXPCComponents_Utils::GetDOMClassInfo(const nsAString& aClassName,
  1.3334 +                                       nsIClassInfo** aClassInfo)
  1.3335 +{
  1.3336 +    *aClassInfo = nullptr;
  1.3337 +    return NS_ERROR_NOT_AVAILABLE;
  1.3338 +}
  1.3339 +
  1.3340 +NS_IMETHODIMP
  1.3341 +nsXPCComponents_Utils::GetIncumbentGlobal(HandleValue aCallback,
  1.3342 +                                          JSContext *aCx, MutableHandleValue aOut)
  1.3343 +{
  1.3344 +    nsCOMPtr<nsIGlobalObject> global = mozilla::dom::GetIncumbentGlobal();
  1.3345 +    RootedValue globalVal(aCx);
  1.3346 +
  1.3347 +    if (!global) {
  1.3348 +        globalVal = NullValue();
  1.3349 +    } else {
  1.3350 +        // Note: We rely on the wrap call for outerization.
  1.3351 +        globalVal = ObjectValue(*global->GetGlobalJSObject());
  1.3352 +        if (!JS_WrapValue(aCx, &globalVal))
  1.3353 +            return NS_ERROR_FAILURE;
  1.3354 +    }
  1.3355 +
  1.3356 +    // Invoke the callback, if passed.
  1.3357 +    if (aCallback.isObject()) {
  1.3358 +        RootedValue ignored(aCx);
  1.3359 +        if (!JS_CallFunctionValue(aCx, JS::NullPtr(), aCallback, globalVal, &ignored))
  1.3360 +            return NS_ERROR_FAILURE;
  1.3361 +    }
  1.3362 +
  1.3363 +    aOut.set(globalVal);
  1.3364 +    return NS_OK;
  1.3365 +}
  1.3366 +
  1.3367 +/*
  1.3368 + * Below is a bunch of awkward junk to allow JS test code to trigger the
  1.3369 + * creation of an XPCWrappedJS, such that it ends up in the map. We need to
  1.3370 + * hand the caller some sort of reference to hold onto (to prevent the
  1.3371 + * refcount from dropping to zero as soon as the function returns), but trying
  1.3372 + * to return a bonafide XPCWrappedJS to script causes all sorts of trouble. So
  1.3373 + * we create a benign holder class instead, which acts as an opaque reference
  1.3374 + * that script can use to keep the XPCWrappedJS alive and in the map.
  1.3375 + */
  1.3376 +
  1.3377 +class WrappedJSHolder : public nsISupports
  1.3378 +{
  1.3379 +    NS_DECL_ISUPPORTS
  1.3380 +    WrappedJSHolder() {}
  1.3381 +    virtual ~WrappedJSHolder() {}
  1.3382 +
  1.3383 +    nsRefPtr<nsXPCWrappedJS> mWrappedJS;
  1.3384 +};
  1.3385 +NS_IMPL_ISUPPORTS0(WrappedJSHolder);
  1.3386 +
  1.3387 +NS_IMETHODIMP
  1.3388 +nsXPCComponents_Utils::GenerateXPCWrappedJS(HandleValue aObj, HandleValue aScope,
  1.3389 +                                            JSContext *aCx, nsISupports **aOut)
  1.3390 +{
  1.3391 +    if (!aObj.isObject())
  1.3392 +        return NS_ERROR_INVALID_ARG;
  1.3393 +    RootedObject obj(aCx, &aObj.toObject());
  1.3394 +    RootedObject scope(aCx, aScope.isObject() ? js::UncheckedUnwrap(&aScope.toObject())
  1.3395 +                                              : CurrentGlobalOrNull(aCx));
  1.3396 +    JSAutoCompartment ac(aCx, scope);
  1.3397 +    if (!JS_WrapObject(aCx, &obj))
  1.3398 +        return NS_ERROR_FAILURE;
  1.3399 +
  1.3400 +    nsRefPtr<WrappedJSHolder> holder = new WrappedJSHolder();
  1.3401 +    nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports),
  1.3402 +                                               getter_AddRefs(holder->mWrappedJS));
  1.3403 +    holder.forget(aOut);
  1.3404 +    return rv;
  1.3405 +}
  1.3406 +
  1.3407 +NS_IMETHODIMP
  1.3408 +nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory, PRTime *aOut)
  1.3409 +{
  1.3410 +    WatchdogTimestampCategory category;
  1.3411 +    if (aCategory.EqualsLiteral("RuntimeStateChange"))
  1.3412 +        category = TimestampRuntimeStateChange;
  1.3413 +    else if (aCategory.EqualsLiteral("WatchdogWakeup"))
  1.3414 +        category = TimestampWatchdogWakeup;
  1.3415 +    else if (aCategory.EqualsLiteral("WatchdogHibernateStart"))
  1.3416 +        category = TimestampWatchdogHibernateStart;
  1.3417 +    else if (aCategory.EqualsLiteral("WatchdogHibernateStop"))
  1.3418 +        category = TimestampWatchdogHibernateStop;
  1.3419 +    else
  1.3420 +        return NS_ERROR_INVALID_ARG;
  1.3421 +    *aOut = XPCJSRuntime::Get()->GetWatchdogTimestamp(category);
  1.3422 +    return NS_OK;
  1.3423 +}
  1.3424 +
  1.3425 +NS_IMETHODIMP
  1.3426 +nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext *cx, MutableHandleValue rval)
  1.3427 +{
  1.3428 +    RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
  1.3429 +    if (!obj)
  1.3430 +        return NS_ERROR_OUT_OF_MEMORY;
  1.3431 +
  1.3432 +    unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
  1.3433 +
  1.3434 +    size_t i = JS_SetProtoCalled(cx);
  1.3435 +    RootedValue v(cx, DoubleValue(i));
  1.3436 +    if (!JS_DefineProperty(cx, obj, "setProto", v, attrs))
  1.3437 +        return NS_ERROR_OUT_OF_MEMORY;
  1.3438 +
  1.3439 +    i = JS_GetCustomIteratorCount(cx);
  1.3440 +    v.setDouble(i);
  1.3441 +    if (!JS_DefineProperty(cx, obj, "customIter", v, attrs))
  1.3442 +        return NS_ERROR_OUT_OF_MEMORY;
  1.3443 +
  1.3444 +    rval.setObject(*obj);
  1.3445 +    return NS_OK;
  1.3446 +}
  1.3447 +
  1.3448 +class MOZ_STACK_CLASS CloneIntoOptions : public OptionsBase
  1.3449 +{
  1.3450 +public:
  1.3451 +    CloneIntoOptions(JSContext *cx = xpc_GetSafeJSContext(),
  1.3452 +                     JSObject *options = nullptr)
  1.3453 +        : OptionsBase(cx, options)
  1.3454 +        , cloneFunctions(false)
  1.3455 +    {}
  1.3456 +
  1.3457 +    virtual bool Parse()
  1.3458 +    {
  1.3459 +        return ParseBoolean("cloneFunctions", &cloneFunctions);
  1.3460 +    }
  1.3461 +
  1.3462 +    bool cloneFunctions;
  1.3463 +};
  1.3464 +
  1.3465 +class MOZ_STACK_CLASS CloneIntoCallbacksData
  1.3466 +{
  1.3467 +public:
  1.3468 +    CloneIntoCallbacksData(JSContext *aCx, CloneIntoOptions *aOptions)
  1.3469 +        : mOptions(aOptions)
  1.3470 +        , mFunctions(aCx)
  1.3471 +    {}
  1.3472 +
  1.3473 +    CloneIntoOptions *mOptions;
  1.3474 +    AutoObjectVector mFunctions;
  1.3475 +};
  1.3476 +
  1.3477 +static JSObject*
  1.3478 +CloneIntoReadStructuredClone(JSContext *cx,
  1.3479 +                             JSStructuredCloneReader *reader,
  1.3480 +                             uint32_t tag,
  1.3481 +                             uint32_t value,
  1.3482 +                             void* closure)
  1.3483 +{
  1.3484 +    CloneIntoCallbacksData* data = static_cast<CloneIntoCallbacksData*>(closure);
  1.3485 +    MOZ_ASSERT(data);
  1.3486 +
  1.3487 +    if (tag == mozilla::dom::SCTAG_DOM_BLOB || tag == mozilla::dom::SCTAG_DOM_FILELIST) {
  1.3488 +        MOZ_ASSERT(!value, "Data should be empty");
  1.3489 +
  1.3490 +        nsISupports *supports;
  1.3491 +        if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
  1.3492 +            RootedValue val(cx);
  1.3493 +            if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val)))
  1.3494 +                return val.toObjectOrNull();
  1.3495 +        }
  1.3496 +    }
  1.3497 +
  1.3498 +    if (tag == mozilla::dom::SCTAG_DOM_FUNCTION) {
  1.3499 +      MOZ_ASSERT(value < data->mFunctions.length());
  1.3500 +
  1.3501 +      RootedValue functionValue(cx);
  1.3502 +      RootedObject obj(cx, data->mFunctions[value]);
  1.3503 +
  1.3504 +      if (!JS_WrapObject(cx, &obj))
  1.3505 +          return nullptr;
  1.3506 +
  1.3507 +      if (!xpc::NewFunctionForwarder(cx, obj, false, &functionValue))
  1.3508 +          return nullptr;
  1.3509 +
  1.3510 +      return &functionValue.toObject();
  1.3511 +    }
  1.3512 +
  1.3513 +    return nullptr;
  1.3514 +}
  1.3515 +
  1.3516 +static bool
  1.3517 +CloneIntoWriteStructuredClone(JSContext *cx,
  1.3518 +                              JSStructuredCloneWriter *writer,
  1.3519 +                              HandleObject obj,
  1.3520 +                              void *closure)
  1.3521 +{
  1.3522 +    CloneIntoCallbacksData* data = static_cast<CloneIntoCallbacksData*>(closure);
  1.3523 +    MOZ_ASSERT(data);
  1.3524 +
  1.3525 +    nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
  1.3526 +    nsContentUtils::XPConnect()->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
  1.3527 +    if (wrappedNative) {
  1.3528 +        uint32_t scTag = 0;
  1.3529 +        nsISupports *supports = wrappedNative->Native();
  1.3530 +
  1.3531 +        nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
  1.3532 +        if (blob)
  1.3533 +            scTag = mozilla::dom::SCTAG_DOM_BLOB;
  1.3534 +        else {
  1.3535 +            nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
  1.3536 +            if (list)
  1.3537 +                scTag = mozilla::dom::SCTAG_DOM_FILELIST;
  1.3538 +        }
  1.3539 +
  1.3540 +        if (scTag) {
  1.3541 +            return JS_WriteUint32Pair(writer, scTag, 0) &&
  1.3542 +                   JS_WriteBytes(writer, &supports, sizeof(supports));
  1.3543 +        }
  1.3544 +    }
  1.3545 +
  1.3546 +    if (data->mOptions->cloneFunctions && JS_ObjectIsCallable(cx, obj)) {
  1.3547 +        data->mFunctions.append(obj);
  1.3548 +        return JS_WriteUint32Pair(writer, mozilla::dom::SCTAG_DOM_FUNCTION,
  1.3549 +                                  data->mFunctions.length() - 1);
  1.3550 +    }
  1.3551 +
  1.3552 +    return false;
  1.3553 +}
  1.3554 +
  1.3555 +// These functions serialize raw XPCOM pointers in the data stream, and thus
  1.3556 +// should only be used when the read and write are done together
  1.3557 +// synchronously.
  1.3558 +static JSStructuredCloneCallbacks CloneIntoCallbacks = {
  1.3559 +    CloneIntoReadStructuredClone,
  1.3560 +    CloneIntoWriteStructuredClone,
  1.3561 +    nullptr
  1.3562 +};
  1.3563 +
  1.3564 +bool
  1.3565 +xpc::CloneInto(JSContext *aCx, HandleValue aValue, HandleValue aScope,
  1.3566 +               HandleValue aOptions, MutableHandleValue aCloned)
  1.3567 +{
  1.3568 +    if (!aScope.isObject())
  1.3569 +        return false;
  1.3570 +
  1.3571 +    RootedObject scope(aCx, &aScope.toObject());
  1.3572 +    scope = js::CheckedUnwrap(scope);
  1.3573 +    if(!scope) {
  1.3574 +        JS_ReportError(aCx, "Permission denied to clone object into scope");
  1.3575 +        return false;
  1.3576 +    }
  1.3577 +
  1.3578 +    if (!aOptions.isUndefined() && !aOptions.isObject()) {
  1.3579 +        JS_ReportError(aCx, "Invalid argument");
  1.3580 +        return false;
  1.3581 +    }
  1.3582 +
  1.3583 +    RootedObject optionsObject(aCx, aOptions.isObject() ? &aOptions.toObject()
  1.3584 +                                                        : nullptr);
  1.3585 +    CloneIntoOptions options(aCx, optionsObject);
  1.3586 +    if (aOptions.isObject() && !options.Parse())
  1.3587 +        return false;
  1.3588 +
  1.3589 +    {
  1.3590 +        CloneIntoCallbacksData data(aCx, &options);
  1.3591 +        JSAutoCompartment ac(aCx, scope);
  1.3592 +        if (!JS_StructuredClone(aCx, aValue, aCloned, &CloneIntoCallbacks, &data))
  1.3593 +            return false;
  1.3594 +    }
  1.3595 +
  1.3596 +    return JS_WrapValue(aCx, aCloned);
  1.3597 +}
  1.3598 +
  1.3599 +NS_IMETHODIMP
  1.3600 +nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope,
  1.3601 +                                 HandleValue aOptions, JSContext *aCx,
  1.3602 +                                 MutableHandleValue aCloned)
  1.3603 +{
  1.3604 +    return xpc::CloneInto(aCx, aValue, aScope, aOptions, aCloned) ?
  1.3605 +           NS_OK : NS_ERROR_FAILURE;
  1.3606 +}
  1.3607 +
  1.3608 +NS_IMETHODIMP
  1.3609 +nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal **aResult)
  1.3610 +{
  1.3611 +    // This API may only be when the Entry Settings Object corresponds to a
  1.3612 +    // JS-implemented WebIDL call. In all other cases, the value will be null,
  1.3613 +    // and we throw.
  1.3614 +    nsCOMPtr<nsIPrincipal> callerPrin = mozilla::dom::GetWebIDLCallerPrincipal();
  1.3615 +    if (!callerPrin)
  1.3616 +        return NS_ERROR_NOT_AVAILABLE;
  1.3617 +    callerPrin.forget(aResult);
  1.3618 +    return NS_OK;
  1.3619 +}
  1.3620 +
  1.3621 +NS_IMETHODIMP
  1.3622 +nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext *cx,
  1.3623 +                                          nsIPrincipal **result)
  1.3624 +{
  1.3625 +    if (!val.isObject())
  1.3626 +        return NS_ERROR_INVALID_ARG;
  1.3627 +    RootedObject obj(cx, &val.toObject());
  1.3628 +    obj = js::CheckedUnwrap(obj);
  1.3629 +    MOZ_ASSERT(obj);
  1.3630 +
  1.3631 +    nsCOMPtr<nsIPrincipal> prin = nsContentUtils::GetObjectPrincipal(obj);
  1.3632 +    prin.forget(result);
  1.3633 +    return NS_OK;
  1.3634 +}
  1.3635 +
  1.3636 +/***************************************************************************/
  1.3637 +/***************************************************************************/
  1.3638 +/***************************************************************************/
  1.3639 +
  1.3640 +
  1.3641 +nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope)
  1.3642 +    :   mScope(aScope)
  1.3643 +{
  1.3644 +    MOZ_ASSERT(aScope, "aScope must not be null");
  1.3645 +}
  1.3646 +
  1.3647 +nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
  1.3648 +    :   nsXPCComponentsBase(aScope)
  1.3649 +{
  1.3650 +}
  1.3651 +
  1.3652 +nsXPCComponentsBase::~nsXPCComponentsBase()
  1.3653 +{
  1.3654 +}
  1.3655 +
  1.3656 +nsXPCComponents::~nsXPCComponents()
  1.3657 +{
  1.3658 +}
  1.3659 +
  1.3660 +void
  1.3661 +nsXPCComponentsBase::ClearMembers()
  1.3662 +{
  1.3663 +    mInterfaces = nullptr;
  1.3664 +    mInterfacesByID = nullptr;
  1.3665 +    mResults = nullptr;
  1.3666 +}
  1.3667 +
  1.3668 +void
  1.3669 +nsXPCComponents::ClearMembers()
  1.3670 +{
  1.3671 +    mClasses = nullptr;
  1.3672 +    mClassesByID = nullptr;
  1.3673 +    mID = nullptr;
  1.3674 +    mException = nullptr;
  1.3675 +    mConstructor = nullptr;
  1.3676 +    mUtils = nullptr;
  1.3677 +
  1.3678 +    nsXPCComponentsBase::ClearMembers();
  1.3679 +}
  1.3680 +
  1.3681 +/*******************************************/
  1.3682 +#define XPC_IMPL_GET_OBJ_METHOD(_class, _n)                                   \
  1.3683 +NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n * *a##_n) {               \
  1.3684 +    NS_ENSURE_ARG_POINTER(a##_n);                                             \
  1.3685 +    if (!m##_n)                                                               \
  1.3686 +        m##_n = new nsXPCComponents_##_n();                                   \
  1.3687 +    nsRefPtr<nsXPCComponents_##_n> ret = m##_n;                               \
  1.3688 +    ret.forget(a##_n);                                                        \
  1.3689 +    return NS_OK;                                                             \
  1.3690 +}
  1.3691 +
  1.3692 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Interfaces)
  1.3693 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, InterfacesByID)
  1.3694 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes)
  1.3695 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ClassesByID)
  1.3696 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Results)
  1.3697 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID)
  1.3698 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception)
  1.3699 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor)
  1.3700 +XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils)
  1.3701 +
  1.3702 +#undef XPC_IMPL_GET_OBJ_METHOD
  1.3703 +/*******************************************/
  1.3704 +
  1.3705 +NS_IMETHODIMP
  1.3706 +nsXPCComponentsBase::IsSuccessCode(nsresult result, bool *out)
  1.3707 +{
  1.3708 +    *out = NS_SUCCEEDED(result);
  1.3709 +    return NS_OK;
  1.3710 +}
  1.3711 +
  1.3712 +NS_IMETHODIMP
  1.3713 +nsXPCComponents::GetStack(nsIStackFrame * *aStack)
  1.3714 +{
  1.3715 +    nsresult rv;
  1.3716 +    nsXPConnect* xpc = nsXPConnect::XPConnect();
  1.3717 +    rv = xpc->GetCurrentJSStack(aStack);
  1.3718 +    return rv;
  1.3719 +}
  1.3720 +
  1.3721 +NS_IMETHODIMP
  1.3722 +nsXPCComponents::GetManager(nsIComponentManager * *aManager)
  1.3723 +{
  1.3724 +    MOZ_ASSERT(aManager, "bad param");
  1.3725 +    return NS_GetComponentManager(aManager);
  1.3726 +}
  1.3727 +
  1.3728 +NS_IMETHODIMP
  1.3729 +nsXPCComponents::GetLastResult(JSContext *aCx, MutableHandleValue aOut)
  1.3730 +{
  1.3731 +    XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
  1.3732 +    if (!xpcc)
  1.3733 +        return NS_ERROR_FAILURE;
  1.3734 +    nsresult res = xpcc->GetLastResult();
  1.3735 +    aOut.setNumber(static_cast<uint32_t>(res));
  1.3736 +    return NS_OK;
  1.3737 +}
  1.3738 +
  1.3739 +NS_IMETHODIMP
  1.3740 +nsXPCComponents::GetReturnCode(JSContext *aCx, MutableHandleValue aOut)
  1.3741 +{
  1.3742 +    XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
  1.3743 +    if (!xpcc)
  1.3744 +        return NS_ERROR_FAILURE;
  1.3745 +    nsresult res = xpcc->GetPendingResult();
  1.3746 +    aOut.setNumber(static_cast<uint32_t>(res));
  1.3747 +    return NS_OK;
  1.3748 +}
  1.3749 +
  1.3750 +NS_IMETHODIMP
  1.3751 +nsXPCComponents::SetReturnCode(JSContext *aCx, HandleValue aCode)
  1.3752 +{
  1.3753 +    XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
  1.3754 +    if (!xpcc)
  1.3755 +        return NS_ERROR_FAILURE;
  1.3756 +    nsresult rv;
  1.3757 +    if (!ToUint32(aCx, aCode, (uint32_t*)&rv))
  1.3758 +        return NS_ERROR_FAILURE;
  1.3759 +    xpcc->SetPendingResult(rv);
  1.3760 +    xpcc->SetLastResult(rv);
  1.3761 +    return NS_OK;
  1.3762 +}
  1.3763 +
  1.3764 +// static
  1.3765 +/* void reportError (); */
  1.3766 +NS_IMETHODIMP nsXPCComponents::ReportError(HandleValue error, JSContext *cx)
  1.3767 +{
  1.3768 +    NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
  1.3769 +
  1.3770 +    nsCOMPtr<nsIXPCComponents_Utils> utils;
  1.3771 +    nsresult rv = GetUtils(getter_AddRefs(utils));
  1.3772 +    if (NS_FAILED(rv))
  1.3773 +        return rv;
  1.3774 +
  1.3775 +    return utils->ReportError(error, cx);
  1.3776 +}
  1.3777 +
  1.3778 +/**********************************************/
  1.3779 +
  1.3780 +class ComponentsSH : public nsIXPCScriptable
  1.3781 +{
  1.3782 +public:
  1.3783 +    ComponentsSH(unsigned dummy)
  1.3784 +    {
  1.3785 +    }
  1.3786 +
  1.3787 +    NS_DECL_ISUPPORTS
  1.3788 +    NS_DECL_NSIXPCSCRIPTABLE
  1.3789 +    // The NS_IMETHODIMP isn't really accurate here, but NS_CALLBACK requires
  1.3790 +    // the referent to be declared __stdcall on Windows, and this is the only
  1.3791 +    // macro that does that.
  1.3792 +    static NS_IMETHODIMP Get(uint32_t aLangId, nsISupports **helper)
  1.3793 +    {
  1.3794 +        *helper = &singleton;
  1.3795 +        return NS_OK;
  1.3796 +    }
  1.3797 +
  1.3798 +private:
  1.3799 +    static ComponentsSH singleton;
  1.3800 +};
  1.3801 +
  1.3802 +ComponentsSH ComponentsSH::singleton(0);
  1.3803 +
  1.3804 +// Singleton refcounting.
  1.3805 +NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::AddRef(void) { return 1; }
  1.3806 +NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::Release(void) { return 1; }
  1.3807 +
  1.3808 +NS_INTERFACE_MAP_BEGIN(ComponentsSH)
  1.3809 +  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1.3810 +  NS_INTERFACE_MAP_ENTRY(nsISupports)
  1.3811 +NS_INTERFACE_MAP_END
  1.3812 +
  1.3813 +#define NSXPCCOMPONENTSBASE_CID \
  1.3814 +{ 0xc62998e5, 0x95f1, 0x4058, \
  1.3815 +  { 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 } }
  1.3816 +
  1.3817 +#define NSXPCCOMPONENTS_CID \
  1.3818 +{ 0x3649f405, 0xf0ec, 0x4c28, \
  1.3819 +    { 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 } }
  1.3820 +
  1.3821 +NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID)
  1.3822 +NS_IMPL_ISUPPORTS_CI(nsXPCComponentsBase, nsIXPCComponentsBase)
  1.3823 +
  1.3824 +NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTS_CID)
  1.3825 +// Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like
  1.3826 +// if it existed.
  1.3827 +NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase)
  1.3828 +NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase)
  1.3829 +NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
  1.3830 +    NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
  1.3831 +    NS_IMPL_QUERY_CLASSINFO(nsXPCComponents)
  1.3832 +NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase)
  1.3833 +NS_IMPL_CI_INTERFACE_GETTER(nsXPCComponents, nsIXPCComponents)
  1.3834 +
  1.3835 +// The nsIXPCScriptable map declaration that will generate stubs for us
  1.3836 +#define XPC_MAP_CLASSNAME           ComponentsSH
  1.3837 +#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents"
  1.3838 +#define                             XPC_MAP_WANT_PRECREATE
  1.3839 +#include "xpc_map_end.h" /* This will #undef the above */
  1.3840 +
  1.3841 +NS_IMETHODIMP
  1.3842 +ComponentsSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj)
  1.3843 +{
  1.3844 +  nsXPCComponentsBase *self = static_cast<nsXPCComponentsBase*>(nativeObj);
  1.3845 +  // this should never happen
  1.3846 +  if (!self->GetScope()) {
  1.3847 +      NS_WARNING("mScope must not be null when nsXPCComponents::PreCreate is called");
  1.3848 +      return NS_ERROR_FAILURE;
  1.3849 +  }
  1.3850 +  *parentObj = self->GetScope()->GetGlobalJSObject();
  1.3851 +  return NS_OK;
  1.3852 +}

mercurial