js/xpconnect/src/XPCComponents.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* The "Components" xpcom objects for JavaScript. */
     9 #include "xpcprivate.h"
    10 #include "xpcIJSModuleLoader.h"
    11 #include "XPCJSWeakReference.h"
    12 #include "WrapperFactory.h"
    13 #include "nsJSUtils.h"
    14 #include "mozJSComponentLoader.h"
    15 #include "nsContentUtils.h"
    16 #include "jsfriendapi.h"
    17 #include "js/StructuredClone.h"
    18 #include "mozilla/Attributes.h"
    19 #include "nsJSEnvironment.h"
    20 #include "mozilla/XPTInterfaceInfoManager.h"
    21 #include "mozilla/dom/DOMException.h"
    22 #include "mozilla/dom/DOMExceptionBinding.h"
    23 #include "mozilla/dom/BindingUtils.h"
    24 #include "mozilla/dom/StructuredCloneTags.h"
    25 #include "nsZipArchive.h"
    26 #include "nsIDOMFile.h"
    27 #include "nsIDOMFileList.h"
    28 #include "nsWindowMemoryReporter.h"
    30 using namespace mozilla;
    31 using namespace JS;
    32 using namespace js;
    33 using namespace xpc;
    34 using mozilla::dom::Exception;
    36 /***************************************************************************/
    37 // stuff used by all
    39 nsresult
    40 xpc::ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval)
    41 {
    42     XPCThrower::Throw(errNum, cx);
    43     *retval = false;
    44     return NS_OK;
    45 }
    47 static bool
    48 JSValIsInterfaceOfType(JSContext *cx, HandleValue v, REFNSIID iid)
    49 {
    51     nsCOMPtr<nsIXPConnectWrappedNative> wn;
    52     nsCOMPtr<nsISupports> sup;
    53     nsISupports* iface;
    55     if (v.isPrimitive())
    56         return false;
    58     nsXPConnect* xpc = nsXPConnect::XPConnect();
    59     RootedObject obj(cx, &v.toObject());
    60     if (NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) && wn &&
    61         NS_SUCCEEDED(wn->Native()->QueryInterface(iid, (void**)&iface)) && iface)
    62     {
    63         NS_RELEASE(iface);
    64         return true;
    65     }
    66     return false;
    67 }
    69 char *
    70 xpc::CloneAllAccess()
    71 {
    72     static const char allAccess[] = "AllAccess";
    73     return (char*)nsMemory::Clone(allAccess, sizeof(allAccess));
    74 }
    76 char *
    77 xpc::CheckAccessList(const char16_t *wideName, const char *const list[])
    78 {
    79     nsAutoCString asciiName;
    80     CopyUTF16toUTF8(nsDependentString(wideName), asciiName);
    82     for (const char* const* p = list; *p; p++)
    83         if (!strcmp(*p, asciiName.get()))
    84             return CloneAllAccess();
    86     return nullptr;
    87 }
    89 /***************************************************************************/
    90 /***************************************************************************/
    91 /***************************************************************************/
    94 class nsXPCComponents_Interfaces :
    95             public nsIXPCComponents_Interfaces,
    96             public nsIXPCScriptable,
    97             public nsIClassInfo
    98 {
    99 public:
   100     // all the interface method declarations...
   101     NS_DECL_ISUPPORTS
   102     NS_DECL_NSIXPCCOMPONENTS_INTERFACES
   103     NS_DECL_NSIXPCSCRIPTABLE
   104     NS_DECL_NSICLASSINFO
   106 public:
   107     nsXPCComponents_Interfaces();
   108     virtual ~nsXPCComponents_Interfaces();
   110 private:
   111     nsCOMArray<nsIInterfaceInfo> mInterfaces;
   112 };
   114 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   115                        out nsIIDPtr array); */
   116 NS_IMETHODIMP
   117 nsXPCComponents_Interfaces::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   118 {
   119     const uint32_t count = 2;
   120     *aCount = count;
   121     nsIID **array;
   122     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   123     if (!array)
   124         return NS_ERROR_OUT_OF_MEMORY;
   126     uint32_t index = 0;
   127     nsIID* clone;
   128 #define PUSH_IID(id)                                                          \
   129     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   130                                                  sizeof(nsIID)));             \
   131     if (!clone)                                                               \
   132         goto oom;                                                             \
   133     array[index++] = clone;
   135     PUSH_IID(nsIXPCComponents_Interfaces)
   136     PUSH_IID(nsIXPCScriptable)
   137 #undef PUSH_IID
   139     return NS_OK;
   140 oom:
   141     while (index)
   142         nsMemory::Free(array[--index]);
   143     nsMemory::Free(array);
   144     *aArray = nullptr;
   145     return NS_ERROR_OUT_OF_MEMORY;
   146 }
   148 /* nsISupports getHelperForLanguage (in uint32_t language); */
   149 NS_IMETHODIMP
   150 nsXPCComponents_Interfaces::GetHelperForLanguage(uint32_t language,
   151                                                  nsISupports **retval)
   152 {
   153     *retval = nullptr;
   154     return NS_OK;
   155 }
   157 /* readonly attribute string contractID; */
   158 NS_IMETHODIMP
   159 nsXPCComponents_Interfaces::GetContractID(char * *aContractID)
   160 {
   161     *aContractID = nullptr;
   162     return NS_ERROR_NOT_AVAILABLE;
   163 }
   165 /* readonly attribute string classDescription; */
   166 NS_IMETHODIMP
   167 nsXPCComponents_Interfaces::GetClassDescription(char * *aClassDescription)
   168 {
   169     static const char classDescription[] = "XPCComponents_Interfaces";
   170     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   171     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   172 }
   174 /* readonly attribute nsCIDPtr classID; */
   175 NS_IMETHODIMP
   176 nsXPCComponents_Interfaces::GetClassID(nsCID * *aClassID)
   177 {
   178     *aClassID = nullptr;
   179     return NS_OK;
   180 }
   182 /* readonly attribute uint32_t implementationLanguage; */
   183 NS_IMETHODIMP
   184 nsXPCComponents_Interfaces::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   185 {
   186     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   187     return NS_OK;
   188 }
   190 /* readonly attribute uint32_t flags; */
   191 NS_IMETHODIMP
   192 nsXPCComponents_Interfaces::GetFlags(uint32_t *aFlags)
   193 {
   194     // Mark ourselves as a DOM object so that instances may be created in
   195     // unprivileged scopes.
   196     *aFlags = nsIClassInfo::DOM_OBJECT;
   197     return NS_OK;
   198 }
   200 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   201 NS_IMETHODIMP
   202 nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   203 {
   204     return NS_ERROR_NOT_AVAILABLE;
   205 }
   207 nsXPCComponents_Interfaces::nsXPCComponents_Interfaces()
   208 {
   209 }
   211 nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces()
   212 {
   213     // empty
   214 }
   217 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces)
   218   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Interfaces)
   219   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   220   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   221   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Interfaces)
   222 NS_INTERFACE_MAP_END
   224 NS_IMPL_ADDREF(nsXPCComponents_Interfaces)
   225 NS_IMPL_RELEASE(nsXPCComponents_Interfaces)
   227 // The nsIXPCScriptable map declaration that will generate stubs for us...
   228 #define XPC_MAP_CLASSNAME           nsXPCComponents_Interfaces
   229 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Interfaces"
   230 #define                             XPC_MAP_WANT_NEWRESOLVE
   231 #define                             XPC_MAP_WANT_NEWENUMERATE
   232 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   233                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   234 #include "xpc_map_end.h" /* This will #undef the above */
   237 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   238 NS_IMETHODIMP
   239 nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   240                                          JSContext * cx, JSObject * obj,
   241                                          uint32_t enum_op, jsval * statep,
   242                                          jsid * idp, bool *_retval)
   243 {
   244     switch (enum_op) {
   245         case JSENUMERATE_INIT:
   246         case JSENUMERATE_INIT_ALL:
   247         {
   248             // Lazily init the list of interfaces when someone tries to
   249             // enumerate them.
   250             if (mInterfaces.IsEmpty()) {
   251                 XPTInterfaceInfoManager::GetSingleton()->
   252                     GetScriptableInterfaces(mInterfaces);
   253             }
   255             *statep = JSVAL_ZERO;
   256             if (idp)
   257                 *idp = INT_TO_JSID(mInterfaces.Length());
   258             return NS_OK;
   259         }
   260         case JSENUMERATE_NEXT:
   261         {
   262             uint32_t idx = JSVAL_TO_INT(*statep);
   263             nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
   264             *statep = UINT_TO_JSVAL(idx + 1);
   266             if (interface) {
   267                 const char* name;
   269                 RootedId id(cx);
   270                 if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) {
   271                     RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
   272                     if (idstr && JS_StringToId(cx, idstr, &id)) {
   273                         *idp = id;
   274                         return NS_OK;
   275                     }
   276                 }
   277             }
   278             // fall through
   279         }
   281         case JSENUMERATE_DESTROY:
   282         default:
   283             *statep = JSVAL_NULL;
   284             return NS_OK;
   285     }
   286 }
   288 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
   289 NS_IMETHODIMP
   290 nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper,
   291                                        JSContext *cx, JSObject *objArg,
   292                                        jsid idArg, JSObject **objp,
   293                                        bool *_retval)
   294 {
   295     RootedObject obj(cx, objArg);
   296     RootedId id(cx, idArg);
   298     if (!JSID_IS_STRING(id))
   299         return NS_OK;
   301     JSAutoByteString name;
   302     RootedString str(cx, JSID_TO_STRING(id));
   304     // we only allow interfaces by name here
   305     if (name.encodeLatin1(cx, str) && name.ptr()[0] != '{') {
   306         nsCOMPtr<nsIInterfaceInfo> info;
   307         XPTInterfaceInfoManager::GetSingleton()->
   308             GetInfoForName(name.ptr(), getter_AddRefs(info));
   309         if (!info)
   310             return NS_OK;
   312         nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
   314         if (nsid) {
   315             nsXPConnect* xpc = nsXPConnect::XPConnect();
   316             nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   317             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
   318                                              static_cast<nsIJSIID*>(nsid),
   319                                              NS_GET_IID(nsIJSIID),
   320                                              getter_AddRefs(holder)))) {
   321                 RootedObject idobj(cx);
   322                 if (holder &&
   323                     // Assign, not compare
   324                     (idobj = holder->GetJSObject())) {
   325                     *objp = obj;
   326                     *_retval = JS_DefinePropertyById(cx, obj, id,
   327                                                      OBJECT_TO_JSVAL(idobj),
   328                                                      nullptr, nullptr,
   329                                                      JSPROP_ENUMERATE |
   330                                                      JSPROP_READONLY |
   331                                                      JSPROP_PERMANENT);
   332                 }
   333             }
   334         }
   335     }
   336     return NS_OK;
   337 }
   339 /***************************************************************************/
   340 /***************************************************************************/
   341 /***************************************************************************/
   343 class nsXPCComponents_InterfacesByID :
   344             public nsIXPCComponents_InterfacesByID,
   345             public nsIXPCScriptable,
   346             public nsIClassInfo
   347 {
   348 public:
   349     // all the interface method declarations...
   350     NS_DECL_ISUPPORTS
   351     NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID
   352     NS_DECL_NSIXPCSCRIPTABLE
   353     NS_DECL_NSICLASSINFO
   355 public:
   356     nsXPCComponents_InterfacesByID();
   357     virtual ~nsXPCComponents_InterfacesByID();
   359 private:
   360     nsCOMArray<nsIInterfaceInfo> mInterfaces;
   361 };
   363 /***************************************************************************/
   364 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   365                        out nsIIDPtr array); */
   366 NS_IMETHODIMP
   367 nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   368 {
   369     const uint32_t count = 2;
   370     *aCount = count;
   371     nsIID **array;
   372     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   373     if (!array)
   374         return NS_ERROR_OUT_OF_MEMORY;
   376     uint32_t index = 0;
   377     nsIID* clone;
   378 #define PUSH_IID(id)                                                          \
   379     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   380                                                  sizeof(nsIID)));             \
   381     if (!clone)                                                               \
   382         goto oom;                                                             \
   383     array[index++] = clone;
   385     PUSH_IID(nsIXPCComponents_InterfacesByID)
   386     PUSH_IID(nsIXPCScriptable)
   387 #undef PUSH_IID
   389     return NS_OK;
   390 oom:
   391     while (index)
   392         nsMemory::Free(array[--index]);
   393     nsMemory::Free(array);
   394     *aArray = nullptr;
   395     return NS_ERROR_OUT_OF_MEMORY;
   396 }
   398 /* nsISupports getHelperForLanguage (in uint32_t language); */
   399 NS_IMETHODIMP
   400 nsXPCComponents_InterfacesByID::GetHelperForLanguage(uint32_t language,
   401                                                      nsISupports **retval)
   402 {
   403     *retval = nullptr;
   404     return NS_OK;
   405 }
   407 /* readonly attribute string contractID; */
   408 NS_IMETHODIMP
   409 nsXPCComponents_InterfacesByID::GetContractID(char * *aContractID)
   410 {
   411     *aContractID = nullptr;
   412     return NS_ERROR_NOT_AVAILABLE;
   413 }
   415 /* readonly attribute string classDescription; */
   416 NS_IMETHODIMP
   417 nsXPCComponents_InterfacesByID::GetClassDescription(char * *aClassDescription)
   418 {
   419     static const char classDescription[] = "XPCComponents_InterfacesByID";
   420     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   421     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   422 }
   424 /* readonly attribute nsCIDPtr classID; */
   425 NS_IMETHODIMP
   426 nsXPCComponents_InterfacesByID::GetClassID(nsCID * *aClassID)
   427 {
   428     *aClassID = nullptr;
   429     return NS_OK;
   430 }
   432 /* readonly attribute uint32_t implementationLanguage; */
   433 NS_IMETHODIMP
   434 nsXPCComponents_InterfacesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   435 {
   436     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   437     return NS_OK;
   438 }
   440 /* readonly attribute uint32_t flags; */
   441 NS_IMETHODIMP
   442 nsXPCComponents_InterfacesByID::GetFlags(uint32_t *aFlags)
   443 {
   444     // Mark ourselves as a DOM object so that instances may be created in
   445     // unprivileged scopes.
   446     *aFlags = nsIClassInfo::DOM_OBJECT;
   447     return NS_OK;
   448 }
   450 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   451 NS_IMETHODIMP
   452 nsXPCComponents_InterfacesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   453 {
   454     return NS_ERROR_NOT_AVAILABLE;
   455 }
   457 nsXPCComponents_InterfacesByID::nsXPCComponents_InterfacesByID()
   458 {
   459 }
   461 nsXPCComponents_InterfacesByID::~nsXPCComponents_InterfacesByID()
   462 {
   463     // empty
   464 }
   466 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID)
   467   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_InterfacesByID)
   468   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   469   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   470   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_InterfacesByID)
   471 NS_INTERFACE_MAP_END
   473 NS_IMPL_ADDREF(nsXPCComponents_InterfacesByID)
   474 NS_IMPL_RELEASE(nsXPCComponents_InterfacesByID)
   476 // The nsIXPCScriptable map declaration that will generate stubs for us...
   477 #define XPC_MAP_CLASSNAME           nsXPCComponents_InterfacesByID
   478 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_InterfacesByID"
   479 #define                             XPC_MAP_WANT_NEWRESOLVE
   480 #define                             XPC_MAP_WANT_NEWENUMERATE
   481 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   482                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   483 #include "xpc_map_end.h" /* This will #undef the above */
   485 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   486 NS_IMETHODIMP
   487 nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   488                                              JSContext * cx, JSObject * obj,
   489                                              uint32_t enum_op, jsval * statep,
   490                                              jsid * idp, bool *_retval)
   491 {
   492     switch (enum_op) {
   493         case JSENUMERATE_INIT:
   494         case JSENUMERATE_INIT_ALL:
   495         {
   496             // Lazily init the list of interfaces when someone tries to
   497             // enumerate them.
   498             if (mInterfaces.IsEmpty()) {
   499                 XPTInterfaceInfoManager::GetSingleton()->
   500                     GetScriptableInterfaces(mInterfaces);
   501             }
   503             *statep = JSVAL_ZERO;
   504             if (idp)
   505                 *idp = INT_TO_JSID(mInterfaces.Length());
   506             return NS_OK;
   507         }
   508         case JSENUMERATE_NEXT:
   509         {
   510             uint32_t idx = JSVAL_TO_INT(*statep);
   511             nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
   512             *statep = UINT_TO_JSVAL(idx + 1);
   513             if (interface) {
   514                 nsIID const *iid;
   515                 char idstr[NSID_LENGTH];
   517                 if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
   518                     iid->ToProvidedString(idstr);
   519                     RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr));
   520                     RootedId id(cx);
   521                     if (jsstr && JS_StringToId(cx, jsstr, &id)) {
   522                         *idp = id;
   523                         return NS_OK;
   524                     }
   525                 }
   526             }
   527             // FALL THROUGH
   528         }
   530         case JSENUMERATE_DESTROY:
   531         default:
   532             *statep = JSVAL_NULL;
   533             return NS_OK;
   534     }
   535 }
   537 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
   538 NS_IMETHODIMP
   539 nsXPCComponents_InterfacesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
   540                                            JSContext *cx, JSObject *objArg,
   541                                            jsid idArg, JSObject **objp,
   542                                            bool *_retval)
   543 {
   544     RootedObject obj(cx, objArg);
   545     RootedId id(cx, idArg);
   547     if (!JSID_IS_STRING(id))
   548         return NS_OK;
   550     RootedString str(cx, JSID_TO_STRING(id));
   551     if (38 != JS_GetStringLength(str))
   552         return NS_OK;
   554     if (const jschar *name = JS_GetInternedStringChars(str)) {
   555         nsID iid;
   556         if (!iid.Parse(NS_ConvertUTF16toUTF8(name).get()))
   557             return NS_OK;
   559         nsCOMPtr<nsIInterfaceInfo> info;
   560         XPTInterfaceInfoManager::GetSingleton()->
   561             GetInfoForIID(&iid, getter_AddRefs(info));
   562         if (!info)
   563             return NS_OK;
   565         nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
   567         if (!nsid)
   568             return NS_ERROR_OUT_OF_MEMORY;
   570         nsXPConnect* xpc = nsXPConnect::XPConnect();
   571         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   572         if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
   573                                          static_cast<nsIJSIID*>(nsid),
   574                                             NS_GET_IID(nsIJSIID),
   575                                             getter_AddRefs(holder)))) {
   576             RootedObject idobj(cx);
   577             if (holder &&
   578                 // Assign, not compare
   579                 (idobj = holder->GetJSObject())) {
   580                 *objp = obj;
   581                 *_retval =
   582                     JS_DefinePropertyById(cx, obj, id,
   583                                           OBJECT_TO_JSVAL(idobj),
   584                                           nullptr, nullptr,
   585                                           JSPROP_ENUMERATE |
   586                                           JSPROP_READONLY |
   587                                           JSPROP_PERMANENT);
   588             }
   589         }
   590     }
   591     return NS_OK;
   592 }
   594 /***************************************************************************/
   595 /***************************************************************************/
   596 /***************************************************************************/
   600 class nsXPCComponents_Classes :
   601   public nsIXPCComponents_Classes,
   602   public nsIXPCScriptable,
   603   public nsIClassInfo
   604 {
   605 public:
   606     // all the interface method declarations...
   607     NS_DECL_ISUPPORTS
   608     NS_DECL_NSIXPCCOMPONENTS_CLASSES
   609     NS_DECL_NSIXPCSCRIPTABLE
   610     NS_DECL_NSICLASSINFO
   612 public:
   613     nsXPCComponents_Classes();
   614     virtual ~nsXPCComponents_Classes();
   615 };
   617 /***************************************************************************/
   618 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   619                        out nsIIDPtr array); */
   620 NS_IMETHODIMP
   621 nsXPCComponents_Classes::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   622 {
   623     const uint32_t count = 2;
   624     *aCount = count;
   625     nsIID **array;
   626     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   627     if (!array)
   628         return NS_ERROR_OUT_OF_MEMORY;
   630     uint32_t index = 0;
   631     nsIID* clone;
   632 #define PUSH_IID(id)                                                          \
   633     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   634                                                  sizeof(nsIID)));             \
   635     if (!clone)                                                               \
   636         goto oom;                                                             \
   637     array[index++] = clone;
   639     PUSH_IID(nsIXPCComponents_Classes)
   640     PUSH_IID(nsIXPCScriptable)
   641 #undef PUSH_IID
   643     return NS_OK;
   644 oom:
   645     while (index)
   646         nsMemory::Free(array[--index]);
   647     nsMemory::Free(array);
   648     *aArray = nullptr;
   649     return NS_ERROR_OUT_OF_MEMORY;
   650 }
   652 /* nsISupports getHelperForLanguage (in uint32_t language); */
   653 NS_IMETHODIMP
   654 nsXPCComponents_Classes::GetHelperForLanguage(uint32_t language,
   655                                               nsISupports **retval)
   656 {
   657     *retval = nullptr;
   658     return NS_OK;
   659 }
   661 /* readonly attribute string contractID; */
   662 NS_IMETHODIMP
   663 nsXPCComponents_Classes::GetContractID(char * *aContractID)
   664 {
   665     *aContractID = nullptr;
   666     return NS_ERROR_NOT_AVAILABLE;
   667 }
   669 /* readonly attribute string classDescription; */
   670 NS_IMETHODIMP
   671 nsXPCComponents_Classes::GetClassDescription(char * *aClassDescription)
   672 {
   673     static const char classDescription[] = "XPCComponents_Classes";
   674     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   675     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   676 }
   678 /* readonly attribute nsCIDPtr classID; */
   679 NS_IMETHODIMP
   680 nsXPCComponents_Classes::GetClassID(nsCID * *aClassID)
   681 {
   682     *aClassID = nullptr;
   683     return NS_OK;
   684 }
   686 /* readonly attribute uint32_t implementationLanguage; */
   687 NS_IMETHODIMP
   688 nsXPCComponents_Classes::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   689 {
   690     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   691     return NS_OK;
   692 }
   694 /* readonly attribute uint32_t flags; */
   695 NS_IMETHODIMP
   696 nsXPCComponents_Classes::GetFlags(uint32_t *aFlags)
   697 {
   698     *aFlags = 0;
   699     return NS_OK;
   700 }
   702 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   703 NS_IMETHODIMP
   704 nsXPCComponents_Classes::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   705 {
   706     return NS_ERROR_NOT_AVAILABLE;
   707 }
   709 nsXPCComponents_Classes::nsXPCComponents_Classes()
   710 {
   711 }
   713 nsXPCComponents_Classes::~nsXPCComponents_Classes()
   714 {
   715     // empty
   716 }
   718 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Classes)
   719   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Classes)
   720   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   721   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   722   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Classes)
   723 NS_INTERFACE_MAP_END
   725 NS_IMPL_ADDREF(nsXPCComponents_Classes)
   726 NS_IMPL_RELEASE(nsXPCComponents_Classes)
   728 // The nsIXPCScriptable map declaration that will generate stubs for us...
   729 #define XPC_MAP_CLASSNAME           nsXPCComponents_Classes
   730 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Classes"
   731 #define                             XPC_MAP_WANT_NEWRESOLVE
   732 #define                             XPC_MAP_WANT_NEWENUMERATE
   733 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   734                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   735 #include "xpc_map_end.h" /* This will #undef the above */
   738 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   739 NS_IMETHODIMP
   740 nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   741                                       JSContext * cx, JSObject * obj,
   742                                       uint32_t enum_op, jsval * statep,
   743                                       jsid * idp, bool *_retval)
   744 {
   745     nsISimpleEnumerator* e;
   747     switch (enum_op) {
   748         case JSENUMERATE_INIT:
   749         case JSENUMERATE_INIT_ALL:
   750         {
   751             nsCOMPtr<nsIComponentRegistrar> compMgr;
   752             if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
   753                 NS_FAILED(compMgr->EnumerateContractIDs(&e)) || !e ) {
   754                 *statep = JSVAL_NULL;
   755                 return NS_ERROR_UNEXPECTED;
   756             }
   758             *statep = PRIVATE_TO_JSVAL(e);
   759             if (idp)
   760                 *idp = INT_TO_JSID(0); // indicate that we don't know the count
   761             return NS_OK;
   762         }
   763         case JSENUMERATE_NEXT:
   764         {
   765             nsCOMPtr<nsISupports> isup;
   766             bool hasMore;
   767             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
   769             if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
   770                 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
   771                 nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
   772                 if (holder) {
   773                     nsAutoCString name;
   774                     if (NS_SUCCEEDED(holder->GetData(name))) {
   775                         RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
   776                         RootedId id(cx);
   777                         if (idstr && JS_StringToId(cx, idstr, &id)) {
   778                             *idp = id;
   779                             return NS_OK;
   780                         }
   781                     }
   782                 }
   783             }
   784             // else... FALL THROUGH
   785         }
   787         case JSENUMERATE_DESTROY:
   788         default:
   789             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
   790             NS_IF_RELEASE(e);
   791             *statep = JSVAL_NULL;
   792             return NS_OK;
   793     }
   794 }
   796 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
   797 NS_IMETHODIMP
   798 nsXPCComponents_Classes::NewResolve(nsIXPConnectWrappedNative *wrapper,
   799                                     JSContext *cx, JSObject *objArg,
   800                                     jsid idArg, JSObject **objp,
   801                                     bool *_retval)
   803 {
   804     RootedId id(cx, idArg);
   805     RootedObject obj(cx, objArg);
   807     JSAutoByteString name;
   808     if (JSID_IS_STRING(id) &&
   809         name.encodeLatin1(cx, JSID_TO_STRING(id)) &&
   810         name.ptr()[0] != '{') { // we only allow contractids here
   811         nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
   812         if (nsid) {
   813             nsXPConnect* xpc = nsXPConnect::XPConnect();
   814             nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   815             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
   816                                              static_cast<nsIJSCID*>(nsid),
   817                                              NS_GET_IID(nsIJSCID),
   818                                              getter_AddRefs(holder)))) {
   819                 RootedObject idobj(cx);
   820                 if (holder &&
   821                     // Assign, not compare
   822                         (idobj = holder->GetJSObject())) {
   823                     *objp = obj;
   824                     *_retval = JS_DefinePropertyById(cx, obj, id,
   825                                                      OBJECT_TO_JSVAL(idobj),
   826                                                      nullptr, nullptr,
   827                                                      JSPROP_ENUMERATE |
   828                                                      JSPROP_READONLY |
   829                                                      JSPROP_PERMANENT);
   830                 }
   831             }
   832         }
   833     }
   834     return NS_OK;
   835 }
   837 /***************************************************************************/
   838 /***************************************************************************/
   839 /***************************************************************************/
   841 class nsXPCComponents_ClassesByID :
   842   public nsIXPCComponents_ClassesByID,
   843   public nsIXPCScriptable,
   844   public nsIClassInfo
   845 {
   846 public:
   847     // all the interface method declarations...
   848     NS_DECL_ISUPPORTS
   849     NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID
   850     NS_DECL_NSIXPCSCRIPTABLE
   851     NS_DECL_NSICLASSINFO
   853 public:
   854     nsXPCComponents_ClassesByID();
   855     virtual ~nsXPCComponents_ClassesByID();
   856 };
   858 /***************************************************************************/
   859 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
   860                        out nsIIDPtr array); */
   861 NS_IMETHODIMP
   862 nsXPCComponents_ClassesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
   863 {
   864     const uint32_t count = 2;
   865     *aCount = count;
   866     nsIID **array;
   867     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
   868     if (!array)
   869         return NS_ERROR_OUT_OF_MEMORY;
   871     uint32_t index = 0;
   872     nsIID* clone;
   873 #define PUSH_IID(id)                                                          \
   874     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
   875                                                  sizeof(nsIID)));             \
   876     if (!clone)                                                               \
   877         goto oom;                                                             \
   878     array[index++] = clone;
   880     PUSH_IID(nsIXPCComponents_ClassesByID)
   881     PUSH_IID(nsIXPCScriptable)
   882 #undef PUSH_IID
   884     return NS_OK;
   885 oom:
   886     while (index)
   887         nsMemory::Free(array[--index]);
   888     nsMemory::Free(array);
   889     *aArray = nullptr;
   890     return NS_ERROR_OUT_OF_MEMORY;
   891 }
   893 /* nsISupports getHelperForLanguage (in uint32_t language); */
   894 NS_IMETHODIMP
   895 nsXPCComponents_ClassesByID::GetHelperForLanguage(uint32_t language,
   896                                                   nsISupports **retval)
   897 {
   898     *retval = nullptr;
   899     return NS_OK;
   900 }
   902 /* readonly attribute string contractID; */
   903 NS_IMETHODIMP
   904 nsXPCComponents_ClassesByID::GetContractID(char * *aContractID)
   905 {
   906     *aContractID = nullptr;
   907     return NS_ERROR_NOT_AVAILABLE;
   908 }
   910 /* readonly attribute string classDescription; */
   911 NS_IMETHODIMP
   912 nsXPCComponents_ClassesByID::GetClassDescription(char * *aClassDescription)
   913 {
   914     static const char classDescription[] = "XPCComponents_ClassesByID";
   915     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
   916     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   917 }
   919 /* readonly attribute nsCIDPtr classID; */
   920 NS_IMETHODIMP
   921 nsXPCComponents_ClassesByID::GetClassID(nsCID * *aClassID)
   922 {
   923     *aClassID = nullptr;
   924     return NS_OK;
   925 }
   927 /* readonly attribute uint32_t implementationLanguage; */
   928 NS_IMETHODIMP
   929 nsXPCComponents_ClassesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
   930 {
   931     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
   932     return NS_OK;
   933 }
   935 /* readonly attribute uint32_t flags; */
   936 NS_IMETHODIMP
   937 nsXPCComponents_ClassesByID::GetFlags(uint32_t *aFlags)
   938 {
   939     *aFlags = 0;
   940     return NS_OK;
   941 }
   943 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
   944 NS_IMETHODIMP
   945 nsXPCComponents_ClassesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   946 {
   947     return NS_ERROR_NOT_AVAILABLE;
   948 }
   950 nsXPCComponents_ClassesByID::nsXPCComponents_ClassesByID()
   951 {
   952 }
   954 nsXPCComponents_ClassesByID::~nsXPCComponents_ClassesByID()
   955 {
   956     // empty
   957 }
   959 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ClassesByID)
   960   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ClassesByID)
   961   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   962   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   963   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ClassesByID)
   964 NS_INTERFACE_MAP_END
   966 NS_IMPL_ADDREF(nsXPCComponents_ClassesByID)
   967 NS_IMPL_RELEASE(nsXPCComponents_ClassesByID)
   969 // The nsIXPCScriptable map declaration that will generate stubs for us...
   970 #define XPC_MAP_CLASSNAME           nsXPCComponents_ClassesByID
   971 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ClassesByID"
   972 #define                             XPC_MAP_WANT_NEWRESOLVE
   973 #define                             XPC_MAP_WANT_NEWENUMERATE
   974 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
   975                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
   976 #include "xpc_map_end.h" /* This will #undef the above */
   978 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
   979 NS_IMETHODIMP
   980 nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
   981                                           JSContext * cx, JSObject * obj,
   982                                           uint32_t enum_op, jsval * statep,
   983                                           jsid * idp, bool *_retval)
   984 {
   985     nsISimpleEnumerator* e;
   987     switch (enum_op) {
   988         case JSENUMERATE_INIT:
   989         case JSENUMERATE_INIT_ALL:
   990         {
   991             nsCOMPtr<nsIComponentRegistrar> compMgr;
   992             if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
   993                 NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e ) {
   994                 *statep = JSVAL_NULL;
   995                 return NS_ERROR_UNEXPECTED;
   996             }
   998             *statep = PRIVATE_TO_JSVAL(e);
   999             if (idp)
  1000                 *idp = INT_TO_JSID(0); // indicate that we don't know the count
  1001             return NS_OK;
  1003         case JSENUMERATE_NEXT:
  1005             nsCOMPtr<nsISupports> isup;
  1006             bool hasMore;
  1007             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
  1009             if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
  1010                 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
  1011                 nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
  1012                 if (holder) {
  1013                     char* name;
  1014                     if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
  1015                         RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
  1016                         nsMemory::Free(name);
  1017                         RootedId id(cx);
  1018                         if (idstr && JS_StringToId(cx, idstr, &id)) {
  1019                             *idp = id;
  1020                             return NS_OK;
  1025             // else... FALL THROUGH
  1028         case JSENUMERATE_DESTROY:
  1029         default:
  1030             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
  1031             NS_IF_RELEASE(e);
  1032             *statep = JSVAL_NULL;
  1033             return NS_OK;
  1037 static bool
  1038 IsRegisteredCLSID(const char* str)
  1040     bool registered;
  1041     nsID id;
  1043     if (!id.Parse(str))
  1044         return false;
  1046     nsCOMPtr<nsIComponentRegistrar> compMgr;
  1047     if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
  1048         NS_FAILED(compMgr->IsCIDRegistered(id, &registered)))
  1049         return false;
  1051     return registered;
  1054 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
  1055 NS_IMETHODIMP
  1056 nsXPCComponents_ClassesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
  1057                                         JSContext *cx, JSObject *objArg,
  1058                                         jsid idArg, JSObject **objp,
  1059                                         bool *_retval)
  1061     RootedObject obj(cx, objArg);
  1062     RootedId id(cx, idArg);
  1064     if (!JSID_IS_STRING(id))
  1065         return NS_OK;
  1067     JSAutoByteString name;
  1068     RootedString str(cx, JSID_TO_STRING(id));
  1069     if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' &&
  1070         IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
  1072         nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
  1073         if (nsid) {
  1074             nsXPConnect* xpc = nsXPConnect::XPConnect();
  1075             nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  1076             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
  1077                                              static_cast<nsIJSCID*>(nsid),
  1078                                              NS_GET_IID(nsIJSCID),
  1079                                              getter_AddRefs(holder)))) {
  1080                 RootedObject idobj(cx);
  1081                 if (holder &&
  1082                     // Assign, not compare
  1083                     (idobj = holder->GetJSObject())) {
  1084                     *objp = obj;
  1085                     *_retval = JS_DefinePropertyById(cx, obj, id,
  1086                                                      ObjectValue(*idobj),
  1087                                                      nullptr, nullptr,
  1088                                                      JSPROP_ENUMERATE |
  1089                                                      JSPROP_READONLY |
  1090                                                      JSPROP_PERMANENT);
  1095     return NS_OK;
  1099 /***************************************************************************/
  1101 // Currently the possible results do not change at runtime, so they are only
  1102 // cached once (unlike ContractIDs, CLSIDs, and IIDs)
  1104 class nsXPCComponents_Results :
  1105   public nsIXPCComponents_Results,
  1106   public nsIXPCScriptable,
  1107   public nsIClassInfo
  1109 public:
  1110     // all the interface method declarations...
  1111     NS_DECL_ISUPPORTS
  1112     NS_DECL_NSIXPCCOMPONENTS_RESULTS
  1113     NS_DECL_NSIXPCSCRIPTABLE
  1114     NS_DECL_NSICLASSINFO
  1116 public:
  1117     nsXPCComponents_Results();
  1118     virtual ~nsXPCComponents_Results();
  1119 };
  1121 /***************************************************************************/
  1122 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1123                        out nsIIDPtr array); */
  1124 NS_IMETHODIMP
  1125 nsXPCComponents_Results::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1127     const uint32_t count = 2;
  1128     *aCount = count;
  1129     nsIID **array;
  1130     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1131     if (!array)
  1132         return NS_ERROR_OUT_OF_MEMORY;
  1134     uint32_t index = 0;
  1135     nsIID* clone;
  1136 #define PUSH_IID(id)                                                          \
  1137     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1138                                                  sizeof(nsIID)));             \
  1139     if (!clone)                                                               \
  1140         goto oom;                                                             \
  1141     array[index++] = clone;
  1143     PUSH_IID(nsIXPCComponents_Results)
  1144     PUSH_IID(nsIXPCScriptable)
  1145 #undef PUSH_IID
  1147     return NS_OK;
  1148 oom:
  1149     while (index)
  1150         nsMemory::Free(array[--index]);
  1151     nsMemory::Free(array);
  1152     *aArray = nullptr;
  1153     return NS_ERROR_OUT_OF_MEMORY;
  1156 /* nsISupports getHelperForLanguage (in uint32_t language); */
  1157 NS_IMETHODIMP
  1158 nsXPCComponents_Results::GetHelperForLanguage(uint32_t language,
  1159                                               nsISupports **retval)
  1161     *retval = nullptr;
  1162     return NS_OK;
  1165 /* readonly attribute string contractID; */
  1166 NS_IMETHODIMP
  1167 nsXPCComponents_Results::GetContractID(char * *aContractID)
  1169     *aContractID = nullptr;
  1170     return NS_ERROR_NOT_AVAILABLE;
  1173 /* readonly attribute string classDescription; */
  1174 NS_IMETHODIMP
  1175 nsXPCComponents_Results::GetClassDescription(char * *aClassDescription)
  1177     static const char classDescription[] = "XPCComponents_Results";
  1178     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1179     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1182 /* readonly attribute nsCIDPtr classID; */
  1183 NS_IMETHODIMP
  1184 nsXPCComponents_Results::GetClassID(nsCID * *aClassID)
  1186     *aClassID = nullptr;
  1187     return NS_OK;
  1190 /* readonly attribute uint32_t implementationLanguage; */
  1191 NS_IMETHODIMP
  1192 nsXPCComponents_Results::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1194     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1195     return NS_OK;
  1198 /* readonly attribute uint32_t flags; */
  1199 NS_IMETHODIMP
  1200 nsXPCComponents_Results::GetFlags(uint32_t *aFlags)
  1202     // Mark ourselves as a DOM object so that instances may be created in
  1203     // unprivileged scopes.
  1204     *aFlags = nsIClassInfo::DOM_OBJECT;
  1205     return NS_OK;
  1208 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1209 NS_IMETHODIMP
  1210 nsXPCComponents_Results::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1212     return NS_ERROR_NOT_AVAILABLE;
  1215 nsXPCComponents_Results::nsXPCComponents_Results()
  1219 nsXPCComponents_Results::~nsXPCComponents_Results()
  1221     // empty
  1224 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Results)
  1225   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Results)
  1226   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1227   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1228   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Results)
  1229 NS_INTERFACE_MAP_END
  1231 NS_IMPL_ADDREF(nsXPCComponents_Results)
  1232 NS_IMPL_RELEASE(nsXPCComponents_Results)
  1234 // The nsIXPCScriptable map declaration that will generate stubs for us...
  1235 #define XPC_MAP_CLASSNAME           nsXPCComponents_Results
  1236 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Results"
  1237 #define                             XPC_MAP_WANT_NEWRESOLVE
  1238 #define                             XPC_MAP_WANT_NEWENUMERATE
  1239 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
  1240                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1241 #include "xpc_map_end.h" /* This will #undef the above */
  1243 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
  1244 NS_IMETHODIMP
  1245 nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
  1246                                       JSContext * cx, JSObject * obj,
  1247                                       uint32_t enum_op, jsval * statep,
  1248                                       jsid * idp, bool *_retval)
  1250     const void** iter;
  1252     switch (enum_op) {
  1253         case JSENUMERATE_INIT:
  1254         case JSENUMERATE_INIT_ALL:
  1256             if (idp)
  1257                 *idp = INT_TO_JSID(nsXPCException::GetNSResultCount());
  1259             void** space = (void**) new char[sizeof(void*)];
  1260             *space = nullptr;
  1261             *statep = PRIVATE_TO_JSVAL(space);
  1262             return NS_OK;
  1264         case JSENUMERATE_NEXT:
  1266             const char* name;
  1267             iter = (const void**) JSVAL_TO_PRIVATE(*statep);
  1268             if (nsXPCException::IterateNSResults(nullptr, &name, nullptr, iter)) {
  1269                 RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
  1270                 JS::RootedId id(cx);
  1271                 if (idstr && JS_StringToId(cx, idstr, &id)) {
  1272                     *idp = id;
  1273                     return NS_OK;
  1276             // else... FALL THROUGH
  1279         case JSENUMERATE_DESTROY:
  1280         default:
  1281             iter = (const void**) JSVAL_TO_PRIVATE(*statep);
  1282             delete [] (char*) iter;
  1283             *statep = JSVAL_NULL;
  1284             return NS_OK;
  1289 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
  1290 NS_IMETHODIMP
  1291 nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper,
  1292                                     JSContext *cx, JSObject *objArg,
  1293                                     jsid idArg, JSObject * *objp,
  1294                                     bool *_retval)
  1296     RootedObject obj(cx, objArg);
  1297     RootedId id(cx, idArg);
  1298     JSAutoByteString name;
  1300     if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) {
  1301         const char* rv_name;
  1302         const void* iter = nullptr;
  1303         nsresult rv;
  1304         while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) {
  1305             if (!strcmp(name.ptr(), rv_name)) {
  1306                 jsval val = JS_NumberValue((double)rv);
  1308                 *objp = obj;
  1309                 if (!JS_DefinePropertyById(cx, obj, id, val,
  1310                                            nullptr, nullptr,
  1311                                            JSPROP_ENUMERATE |
  1312                                            JSPROP_READONLY |
  1313                                            JSPROP_PERMANENT)) {
  1314                     return NS_ERROR_UNEXPECTED;
  1319     return NS_OK;
  1322 /***************************************************************************/
  1323 // JavaScript Constructor for nsIJSID objects (Components.ID)
  1325 class nsXPCComponents_ID :
  1326   public nsIXPCComponents_ID,
  1327   public nsIXPCScriptable,
  1328   public nsIClassInfo
  1330 public:
  1331     // all the interface method declarations...
  1332     NS_DECL_ISUPPORTS
  1333     NS_DECL_NSIXPCCOMPONENTS_ID
  1334     NS_DECL_NSIXPCSCRIPTABLE
  1335     NS_DECL_NSICLASSINFO
  1338 public:
  1339     nsXPCComponents_ID();
  1340     virtual ~nsXPCComponents_ID();
  1342 private:
  1343     static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1344                                     JSContext *cx, HandleObject obj,
  1345                                     const CallArgs &args, bool *_retval);
  1346 };
  1348 /***************************************************************************/
  1349 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1350                        out nsIIDPtr array); */
  1351 NS_IMETHODIMP
  1352 nsXPCComponents_ID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1354     const uint32_t count = 2;
  1355     *aCount = count;
  1356     nsIID **array;
  1357     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1358     if (!array)
  1359         return NS_ERROR_OUT_OF_MEMORY;
  1361     uint32_t index = 0;
  1362     nsIID* clone;
  1363 #define PUSH_IID(id)                                                          \
  1364     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1365                                                  sizeof(nsIID)));             \
  1366     if (!clone)                                                               \
  1367         goto oom;                                                             \
  1368     array[index++] = clone;
  1370     PUSH_IID(nsIXPCComponents_ID)
  1371     PUSH_IID(nsIXPCScriptable)
  1372 #undef PUSH_IID
  1374     return NS_OK;
  1375 oom:
  1376     while (index)
  1377         nsMemory::Free(array[--index]);
  1378     nsMemory::Free(array);
  1379     *aArray = nullptr;
  1380     return NS_ERROR_OUT_OF_MEMORY;
  1383 /* nsISupports getHelperForLanguage (in uint32_t language); */
  1384 NS_IMETHODIMP
  1385 nsXPCComponents_ID::GetHelperForLanguage(uint32_t language,
  1386                                          nsISupports **retval)
  1388     *retval = nullptr;
  1389     return NS_OK;
  1392 /* readonly attribute string contractID; */
  1393 NS_IMETHODIMP
  1394 nsXPCComponents_ID::GetContractID(char * *aContractID)
  1396     *aContractID = nullptr;
  1397     return NS_ERROR_NOT_AVAILABLE;
  1400 /* readonly attribute string classDescription; */
  1401 NS_IMETHODIMP
  1402 nsXPCComponents_ID::GetClassDescription(char * *aClassDescription)
  1404     static const char classDescription[] = "XPCComponents_ID";
  1405     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1406     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1409 /* readonly attribute nsCIDPtr classID; */
  1410 NS_IMETHODIMP
  1411 nsXPCComponents_ID::GetClassID(nsCID * *aClassID)
  1413     *aClassID = nullptr;
  1414     return NS_OK;
  1417 /* readonly attribute uint32_t implementationLanguage; */
  1418 NS_IMETHODIMP
  1419 nsXPCComponents_ID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1421     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1422     return NS_OK;
  1425 /* readonly attribute uint32_t flags; */
  1426 NS_IMETHODIMP
  1427 nsXPCComponents_ID::GetFlags(uint32_t *aFlags)
  1429     *aFlags = 0;
  1430     return NS_OK;
  1433 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1434 NS_IMETHODIMP
  1435 nsXPCComponents_ID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1437     return NS_ERROR_NOT_AVAILABLE;
  1440 nsXPCComponents_ID::nsXPCComponents_ID()
  1444 nsXPCComponents_ID::~nsXPCComponents_ID()
  1446     // empty
  1449 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ID)
  1450   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ID)
  1451   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1452   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1453   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ID)
  1454 NS_INTERFACE_MAP_END
  1456 NS_IMPL_ADDREF(nsXPCComponents_ID)
  1457 NS_IMPL_RELEASE(nsXPCComponents_ID)
  1459 // The nsIXPCScriptable map declaration that will generate stubs for us...
  1460 #define XPC_MAP_CLASSNAME           nsXPCComponents_ID
  1461 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ID"
  1462 #define                             XPC_MAP_WANT_CALL
  1463 #define                             XPC_MAP_WANT_CONSTRUCT
  1464 #define                             XPC_MAP_WANT_HASINSTANCE
  1465 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1466 #include "xpc_map_end.h" /* This will #undef the above */
  1469 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1470 NS_IMETHODIMP
  1471 nsXPCComponents_ID::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1472                          const CallArgs &args, bool *_retval)
  1474     RootedObject obj(cx, objArg);
  1475     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1478 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1479 NS_IMETHODIMP
  1480 nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1481                               const CallArgs &args, bool *_retval)
  1483     RootedObject obj(cx, objArg);
  1484     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1487 // static
  1488 nsresult
  1489 nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1490                                     JSContext *cx, HandleObject obj,
  1491                                     const CallArgs &args, bool *_retval)
  1493     // make sure we have at least one arg
  1495     if (args.length() < 1)
  1496         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
  1498     // Do the security check if necessary
  1500     nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager();
  1501     if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsJSID::GetCID()))) {
  1502         // the security manager vetoed. It should have set an exception.
  1503         *_retval = false;
  1504         return NS_OK;
  1507     // convert the first argument into a string and see if it looks like an id
  1509     JSString* jsstr;
  1510     JSAutoByteString bytes;
  1511     nsID id;
  1513     if (!(jsstr = ToString(cx, args[0])) ||
  1514         !bytes.encodeLatin1(cx, jsstr) ||
  1515         !id.Parse(bytes.ptr())) {
  1516         return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
  1519     // make the new object and return it.
  1521     JSObject* newobj = xpc_NewIDObject(cx, obj, id);
  1522     if (!newobj)
  1523         return NS_ERROR_UNEXPECTED;
  1525     args.rval().setObject(*newobj);
  1526     return NS_OK;
  1529 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
  1530 NS_IMETHODIMP
  1531 nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative *wrapper,
  1532                                 JSContext *cx, JSObject *obj,
  1533                                 HandleValue val, bool *bp, bool *_retval)
  1535     if (bp)
  1536         *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIJSID));
  1537     return NS_OK;
  1540 /***************************************************************************/
  1541 // JavaScript Constructor for nsIXPCException objects (Components.Exception)
  1543 class nsXPCComponents_Exception :
  1544   public nsIXPCComponents_Exception,
  1545   public nsIXPCScriptable,
  1546   public nsIClassInfo
  1548 public:
  1549     // all the interface method declarations...
  1550     NS_DECL_ISUPPORTS
  1551     NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
  1552     NS_DECL_NSIXPCSCRIPTABLE
  1553     NS_DECL_NSICLASSINFO
  1556 public:
  1557     nsXPCComponents_Exception();
  1558     virtual ~nsXPCComponents_Exception();
  1560 private:
  1561     static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1562                                     JSContext *cx, HandleObject obj,
  1563                                     const CallArgs &args, bool *_retval);
  1564 };
  1566 /***************************************************************************/
  1567 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1568                        out nsIIDPtr array); */
  1569 NS_IMETHODIMP
  1570 nsXPCComponents_Exception::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1572     const uint32_t count = 2;
  1573     *aCount = count;
  1574     nsIID **array;
  1575     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1576     if (!array)
  1577         return NS_ERROR_OUT_OF_MEMORY;
  1579     uint32_t index = 0;
  1580     nsIID* clone;
  1581 #define PUSH_IID(id)                                                          \
  1582     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1583                                                  sizeof(nsIID)));             \
  1584     if (!clone)                                                               \
  1585         goto oom;                                                             \
  1586     array[index++] = clone;
  1588     PUSH_IID(nsIXPCComponents_Exception)
  1589     PUSH_IID(nsIXPCScriptable)
  1590 #undef PUSH_IID
  1592     return NS_OK;
  1593 oom:
  1594     while (index)
  1595         nsMemory::Free(array[--index]);
  1596     nsMemory::Free(array);
  1597     *aArray = nullptr;
  1598     return NS_ERROR_OUT_OF_MEMORY;
  1601 /* nsISupports getHelperForLanguage (in uint32_t language); */
  1602 NS_IMETHODIMP
  1603 nsXPCComponents_Exception::GetHelperForLanguage(uint32_t language,
  1604                                                 nsISupports **retval)
  1606     *retval = nullptr;
  1607     return NS_OK;
  1610 /* readonly attribute string contractID; */
  1611 NS_IMETHODIMP
  1612 nsXPCComponents_Exception::GetContractID(char * *aContractID)
  1614     *aContractID = nullptr;
  1615     return NS_ERROR_NOT_AVAILABLE;
  1618 /* readonly attribute string classDescription; */
  1619 NS_IMETHODIMP
  1620 nsXPCComponents_Exception::GetClassDescription(char * *aClassDescription)
  1622     static const char classDescription[] = "XPCComponents_Exception";
  1623     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  1624     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1627 /* readonly attribute nsCIDPtr classID; */
  1628 NS_IMETHODIMP
  1629 nsXPCComponents_Exception::GetClassID(nsCID * *aClassID)
  1631     *aClassID = nullptr;
  1632     return NS_OK;
  1635 /* readonly attribute uint32_t implementationLanguage; */
  1636 NS_IMETHODIMP
  1637 nsXPCComponents_Exception::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  1639     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  1640     return NS_OK;
  1643 /* readonly attribute uint32_t flags; */
  1644 NS_IMETHODIMP
  1645 nsXPCComponents_Exception::GetFlags(uint32_t *aFlags)
  1647     *aFlags = 0;
  1648     return NS_OK;
  1651 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  1652 NS_IMETHODIMP
  1653 nsXPCComponents_Exception::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  1655     return NS_ERROR_NOT_AVAILABLE;
  1658 nsXPCComponents_Exception::nsXPCComponents_Exception()
  1662 nsXPCComponents_Exception::~nsXPCComponents_Exception()
  1664     // empty
  1667 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Exception)
  1668   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Exception)
  1669   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  1670   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  1671   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Exception)
  1672 NS_INTERFACE_MAP_END
  1674 NS_IMPL_ADDREF(nsXPCComponents_Exception)
  1675 NS_IMPL_RELEASE(nsXPCComponents_Exception)
  1677 // The nsIXPCScriptable map declaration that will generate stubs for us...
  1678 #define XPC_MAP_CLASSNAME           nsXPCComponents_Exception
  1679 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Exception"
  1680 #define                             XPC_MAP_WANT_CALL
  1681 #define                             XPC_MAP_WANT_CONSTRUCT
  1682 #define                             XPC_MAP_WANT_HASINSTANCE
  1683 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  1684 #include "xpc_map_end.h" /* This will #undef the above */
  1687 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1688 NS_IMETHODIMP
  1689 nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  1690                                 const CallArgs &args, bool *_retval)
  1692     RootedObject obj(cx, objArg);
  1693     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1696 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  1697 NS_IMETHODIMP
  1698 nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  1699                                      JSObject *objArg, const CallArgs &args, bool *_retval)
  1701     RootedObject obj(cx, objArg);
  1702     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  1705 struct MOZ_STACK_CLASS ExceptionArgParser
  1707     ExceptionArgParser(JSContext *context,
  1708                        nsXPConnect *xpconnect)
  1709         : eMsg("exception")
  1710         , eResult(NS_ERROR_FAILURE)
  1711         , cx(context)
  1712         , xpc(xpconnect)
  1713     {}
  1715     // Public exception parameter values. During construction, these are
  1716     // initialized to the appropriate defaults.
  1717     const char*             eMsg;
  1718     nsresult                eResult;
  1719     nsCOMPtr<nsIStackFrame> eStack;
  1720     nsCOMPtr<nsISupports>   eData;
  1722     // Parse the constructor arguments into the above |eFoo| parameter values.
  1723     bool parse(const CallArgs &args) {
  1724         /*
  1725          * The Components.Exception takes a series of arguments, all of them
  1726          * optional:
  1728          * Argument 0: Exception message (defaults to 'exception').
  1729          * Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options
  1730          *             object (see below).
  1731          * Argument 2: Stack (defaults to the current stack, which we trigger
  1732          *                    by leaving this nullptr in the parser).
  1733          * Argument 3: Optional user data (defaults to nullptr).
  1735          * To dig our way out of this clunky API, we now support passing an
  1736          * options object as the second parameter (as opposed to a result code).
  1737          * If this is the case, all subsequent arguments are ignored, and the
  1738          * following properties are parsed out of the object (using the
  1739          * associated default if the property does not exist):
  1741          *   result:    Result code (see argument 1).
  1742          *   stack:     Call stack (see argument 2).
  1743          *   data:      User data (see argument 3).
  1744          */
  1745         if (args.length() > 0 && !parseMessage(args[0]))
  1746             return false;
  1747         if (args.length() > 1) {
  1748             if (args[1].isObject()) {
  1749                 RootedObject obj(cx, &args[1].toObject());
  1750                 return parseOptionsObject(obj);
  1752             if (!parseResult(args[1]))
  1753                 return false;
  1755         if (args.length() > 2) {
  1756             if (!parseStack(args[2]))
  1757                 return false;
  1759         if (args.length() > 3) {
  1760             if (!parseData(args[3]))
  1761                 return false;
  1763         return true;
  1766   protected:
  1768     /*
  1769      * Parsing helpers.
  1770      */
  1772     bool parseMessage(HandleValue v) {
  1773         JSString *str = ToString(cx, v);
  1774         if (!str)
  1775            return false;
  1776         eMsg = messageBytes.encodeLatin1(cx, str);
  1777         return !!eMsg;
  1780     bool parseResult(HandleValue v) {
  1781         return JS::ToUint32(cx, v, (uint32_t*) &eResult);
  1784     bool parseStack(HandleValue v) {
  1785         if (!v.isObject()) {
  1786             // eStack has already been initialized to null, which is what we want
  1787             // for any non-object values (including null).
  1788             return true;
  1791         return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
  1792                                         NS_GET_IID(nsIStackFrame),
  1793                                         getter_AddRefs(eStack)));
  1796     bool parseData(HandleValue v) {
  1797         if (!v.isObject()) {
  1798             // eData has already been initialized to null, which is what we want
  1799             // for any non-object values (including null).
  1800             return true;
  1803         return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
  1804                                         NS_GET_IID(nsISupports),
  1805                                         getter_AddRefs(eData)));
  1808     bool parseOptionsObject(HandleObject obj) {
  1809         RootedValue v(cx);
  1811         if (!getOption(obj, "result", &v) ||
  1812             (!v.isUndefined() && !parseResult(v)))
  1813             return false;
  1815         if (!getOption(obj, "stack", &v) ||
  1816             (!v.isUndefined() && !parseStack(v)))
  1817             return false;
  1819         if (!getOption(obj, "data", &v) ||
  1820             (!v.isUndefined() && !parseData(v)))
  1821             return false;
  1823         return true;
  1826     bool getOption(HandleObject obj, const char *name, MutableHandleValue rv) {
  1827         // Look for the property.
  1828         bool found;
  1829         if (!JS_HasProperty(cx, obj, name, &found))
  1830             return false;
  1832         // If it wasn't found, indicate with undefined.
  1833         if (!found) {
  1834             rv.setUndefined();
  1835             return true;
  1838         // Get the property.
  1839         return JS_GetProperty(cx, obj, name, rv);
  1842     /*
  1843      * Internal data members.
  1844      */
  1846     // If there's a non-default exception string, hold onto the allocated bytes.
  1847     JSAutoByteString messageBytes;
  1849     // Various bits and pieces that are helpful to have around.
  1850     JSContext *cx;
  1851     nsXPConnect *xpc;
  1852 };
  1854 // static
  1855 nsresult
  1856 nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1857                                            JSContext *cx, HandleObject obj,
  1858                                            const CallArgs &args, bool *_retval)
  1860     nsXPConnect* xpc = nsXPConnect::XPConnect();
  1862     // Do the security check if necessary
  1864     nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
  1865     if (sm && NS_FAILED(sm->CanCreateInstance(cx, Exception::GetCID()))) {
  1866         // the security manager vetoed. It should have set an exception.
  1867         *_retval = false;
  1868         return NS_OK;
  1871     // Parse the arguments to the Exception constructor.
  1872     ExceptionArgParser parser(cx, xpc);
  1873     if (!parser.parse(args))
  1874         return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  1876     nsCOMPtr<nsIException> e = new Exception(nsCString(parser.eMsg),
  1877                                              parser.eResult,
  1878                                              EmptyCString(),
  1879                                              parser.eStack,
  1880                                              parser.eData);
  1882     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  1883     RootedObject newObj(cx);
  1885     if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
  1886                                   getter_AddRefs(holder))) || !holder ||
  1887         // Assign, not compare
  1888         !(newObj = holder->GetJSObject())) {
  1889         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
  1892     args.rval().setObject(*newObj);
  1893     return NS_OK;
  1896 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
  1897 NS_IMETHODIMP
  1898 nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper,
  1899                                        JSContext * cx, JSObject * obj,
  1900                                        HandleValue val, bool *bp,
  1901                                        bool *_retval)
  1903     using namespace mozilla::dom;
  1905     RootedValue v(cx, val);
  1906     if (bp) {
  1907         Exception* e;
  1908         *bp = NS_SUCCEEDED(UNWRAP_OBJECT(Exception, v.toObjectOrNull(), e)) ||
  1909               JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException));
  1911     return NS_OK;
  1914 /***************************************************************************/
  1915 // This class is for the thing returned by "new Component.Constructor".
  1917 // XXXjband we use this CID for security check, but security system can't see
  1918 // it since it has no registed factory. Security really kicks in when we try
  1919 // to build a wrapper around an instance.
  1921 // {B4A95150-E25A-11d3-8F61-0010A4E73D9A}
  1922 #define NS_XPCCONSTRUCTOR_CID                                                 \
  1923 { 0xb4a95150, 0xe25a, 0x11d3,                                                 \
  1924     { 0x8f, 0x61, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
  1926 class nsXPCConstructor :
  1927   public nsIXPCConstructor,
  1928   public nsIXPCScriptable,
  1929   public nsIClassInfo
  1931 public:
  1932     NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID)
  1933 public:
  1934     // all the interface method declarations...
  1935     NS_DECL_ISUPPORTS
  1936     NS_DECL_NSIXPCCONSTRUCTOR
  1937     NS_DECL_NSIXPCSCRIPTABLE
  1938     NS_DECL_NSICLASSINFO
  1940 public:
  1941     nsXPCConstructor(); // not implemented
  1942     nsXPCConstructor(nsIJSCID* aClassID,
  1943                      nsIJSIID* aInterfaceID,
  1944                      const char* aInitializer);
  1945     virtual ~nsXPCConstructor();
  1947 private:
  1948     nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  1949                              JSContext *cx, HandleObject obj,
  1950                              const CallArgs &args, bool *_retval);
  1951 private:
  1952     nsRefPtr<nsIJSCID> mClassID;
  1953     nsRefPtr<nsIJSIID> mInterfaceID;
  1954     char*              mInitializer;
  1955 };
  1957 /***************************************************************************/
  1958 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  1959                        out nsIIDPtr array); */
  1960 NS_IMETHODIMP
  1961 nsXPCConstructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  1963     const uint32_t count = 2;
  1964     *aCount = count;
  1965     nsIID **array;
  1966     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  1967     if (!array)
  1968         return NS_ERROR_OUT_OF_MEMORY;
  1970     uint32_t index = 0;
  1971     nsIID* clone;
  1972 #define PUSH_IID(id)                                                          \
  1973     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  1974                                                  sizeof(nsIID)));             \
  1975     if (!clone)                                                               \
  1976         goto oom;                                                             \
  1977     array[index++] = clone;
  1979     PUSH_IID(nsIXPCConstructor)
  1980     PUSH_IID(nsIXPCScriptable)
  1981 #undef PUSH_IID
  1983     return NS_OK;
  1984 oom:
  1985     while (index)
  1986         nsMemory::Free(array[--index]);
  1987     nsMemory::Free(array);
  1988     *aArray = nullptr;
  1989     return NS_ERROR_OUT_OF_MEMORY;
  1992 /* nsISupports getHelperForLanguage (in uint32_t language); */
  1993 NS_IMETHODIMP
  1994 nsXPCConstructor::GetHelperForLanguage(uint32_t language,
  1995                                        nsISupports **retval)
  1997     *retval = nullptr;
  1998     return NS_OK;
  2001 /* readonly attribute string contractID; */
  2002 NS_IMETHODIMP
  2003 nsXPCConstructor::GetContractID(char * *aContractID)
  2005     *aContractID = nullptr;
  2006     return NS_ERROR_NOT_AVAILABLE;
  2009 /* readonly attribute string classDescription; */
  2010 NS_IMETHODIMP
  2011 nsXPCConstructor::GetClassDescription(char * *aClassDescription)
  2013     static const char classDescription[] = "XPCConstructor";
  2014     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  2015     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  2018 /* readonly attribute nsCIDPtr classID; */
  2019 NS_IMETHODIMP
  2020 nsXPCConstructor::GetClassID(nsCID * *aClassID)
  2022     *aClassID = nullptr;
  2023     return NS_OK;
  2026 /* readonly attribute uint32_t implementationLanguage; */
  2027 NS_IMETHODIMP
  2028 nsXPCConstructor::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  2030     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  2031     return NS_OK;
  2034 /* readonly attribute uint32_t flags; */
  2035 NS_IMETHODIMP
  2036 nsXPCConstructor::GetFlags(uint32_t *aFlags)
  2038     *aFlags = 0;
  2039     return NS_OK;
  2042 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  2043 NS_IMETHODIMP
  2044 nsXPCConstructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  2046     return NS_ERROR_NOT_AVAILABLE;
  2049 nsXPCConstructor::nsXPCConstructor(nsIJSCID* aClassID,
  2050                                    nsIJSIID* aInterfaceID,
  2051                                    const char* aInitializer)
  2052     : mClassID(aClassID),
  2053       mInterfaceID(aInterfaceID)
  2055     mInitializer = aInitializer ?
  2056         (char*) nsMemory::Clone(aInitializer, strlen(aInitializer)+1) :
  2057         nullptr;
  2060 nsXPCConstructor::~nsXPCConstructor()
  2062     if (mInitializer)
  2063         nsMemory::Free(mInitializer);
  2066 /* readonly attribute nsIJSCID classID; */
  2067 NS_IMETHODIMP
  2068 nsXPCConstructor::GetClassID(nsIJSCID * *aClassID)
  2070     nsRefPtr<nsIJSCID> rval = mClassID;
  2071     rval.forget(aClassID);
  2072     return NS_OK;
  2075 /* readonly attribute nsIJSIID interfaceID; */
  2076 NS_IMETHODIMP
  2077 nsXPCConstructor::GetInterfaceID(nsIJSIID * *aInterfaceID)
  2079     nsRefPtr<nsIJSIID> rval = mInterfaceID;
  2080     rval.forget(aInterfaceID);
  2081     return NS_OK;
  2084 /* readonly attribute string initializer; */
  2085 NS_IMETHODIMP
  2086 nsXPCConstructor::GetInitializer(char * *aInitializer)
  2088     XPC_STRING_GETTER_BODY(aInitializer, mInitializer);
  2091 NS_INTERFACE_MAP_BEGIN(nsXPCConstructor)
  2092   NS_INTERFACE_MAP_ENTRY(nsIXPCConstructor)
  2093   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  2094   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  2095   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCConstructor)
  2096 NS_INTERFACE_MAP_END
  2098 NS_IMPL_ADDREF(nsXPCConstructor)
  2099 NS_IMPL_RELEASE(nsXPCConstructor)
  2101 // The nsIXPCScriptable map declaration that will generate stubs for us...
  2102 #define XPC_MAP_CLASSNAME           nsXPCConstructor
  2103 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCConstructor"
  2104 #define                             XPC_MAP_WANT_CALL
  2105 #define                             XPC_MAP_WANT_CONSTRUCT
  2106 #define XPC_MAP_FLAGS               0
  2107 #include "xpc_map_end.h" /* This will #undef the above */
  2110 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  2111 NS_IMETHODIMP
  2112 nsXPCConstructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  2113                        const CallArgs &args, bool *_retval)
  2115     RootedObject obj(cx, objArg);
  2116     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  2120 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  2121 NS_IMETHODIMP
  2122 nsXPCConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
  2123                             const CallArgs &args, bool *_retval)
  2125     RootedObject obj(cx, objArg);
  2126     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  2129 // static
  2130 nsresult
  2131 nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,JSContext *cx,
  2132                                   HandleObject obj, const CallArgs &args, bool *_retval)
  2134     nsXPConnect* xpc = nsXPConnect::XPConnect();
  2136     // security check not required because we are going to call through the
  2137     // code which is reflected into JS which will do that for us later.
  2139     nsCOMPtr<nsIXPConnectJSObjectHolder> cidHolder;
  2140     nsCOMPtr<nsIXPConnectJSObjectHolder> iidHolder;
  2141     RootedObject cidObj(cx);
  2142     RootedObject iidObj(cx);
  2144     if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID),
  2145                                   getter_AddRefs(cidHolder))) || !cidHolder ||
  2146         // Assign, not compare
  2147         !(cidObj = cidHolder->GetJSObject()) ||
  2148         NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID),
  2149                                   getter_AddRefs(iidHolder))) || !iidHolder ||
  2150         // Assign, not compare
  2151         !(iidObj = iidHolder->GetJSObject())) {
  2152         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
  2155     JS::Rooted<JS::Value> arg(cx, ObjectValue(*iidObj));
  2156     RootedValue rval(cx);
  2157     if (!JS_CallFunctionName(cx, cidObj, "createInstance", arg, &rval) ||
  2158         rval.isPrimitive()) {
  2159         // createInstance will have thrown an exception
  2160         *_retval = false;
  2161         return NS_OK;
  2164     args.rval().set(rval);
  2166     // call initializer method if supplied
  2167     if (mInitializer) {
  2168         RootedObject newObj(cx, &rval.toObject());
  2169         // first check existence of function property for better error reporting
  2170         RootedValue fun(cx);
  2171         if (!JS_GetProperty(cx, newObj, mInitializer, &fun) ||
  2172             fun.isPrimitive()) {
  2173             return ThrowAndFail(NS_ERROR_XPC_BAD_INITIALIZER_NAME, cx, _retval);
  2176         RootedValue dummy(cx);
  2177         if (!JS_CallFunctionValue(cx, newObj, fun, args, &dummy)) {
  2178             // function should have thrown an exception
  2179             *_retval = false;
  2180             return NS_OK;
  2184     return NS_OK;
  2187 /*******************************************************/
  2188 // JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
  2190 class nsXPCComponents_Constructor :
  2191   public nsIXPCComponents_Constructor,
  2192   public nsIXPCScriptable,
  2193   public nsIClassInfo
  2195 public:
  2196     // all the interface method declarations...
  2197     NS_DECL_ISUPPORTS
  2198     NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
  2199     NS_DECL_NSIXPCSCRIPTABLE
  2200     NS_DECL_NSICLASSINFO
  2202 public:
  2203     nsXPCComponents_Constructor();
  2204     virtual ~nsXPCComponents_Constructor();
  2206 private:
  2207     static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  2208                                     JSContext *cx, HandleObject obj,
  2209                                     const CallArgs &args, bool *_retval);
  2210 };
  2212 /***************************************************************************/
  2213 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
  2214                        out nsIIDPtr array); */
  2215 NS_IMETHODIMP
  2216 nsXPCComponents_Constructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
  2218     const uint32_t count = 2;
  2219     *aCount = count;
  2220     nsIID **array;
  2221     *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
  2222     if (!array)
  2223         return NS_ERROR_OUT_OF_MEMORY;
  2225     uint32_t index = 0;
  2226     nsIID* clone;
  2227 #define PUSH_IID(id)                                                          \
  2228     clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
  2229                                                  sizeof(nsIID)));             \
  2230     if (!clone)                                                               \
  2231         goto oom;                                                             \
  2232     array[index++] = clone;
  2234     PUSH_IID(nsIXPCComponents_Constructor)
  2235     PUSH_IID(nsIXPCScriptable)
  2236 #undef PUSH_IID
  2238     return NS_OK;
  2239 oom:
  2240     while (index)
  2241         nsMemory::Free(array[--index]);
  2242     nsMemory::Free(array);
  2243     *aArray = nullptr;
  2244     return NS_ERROR_OUT_OF_MEMORY;
  2247 /* nsISupports getHelperForLanguage (in uint32_t language); */
  2248 NS_IMETHODIMP
  2249 nsXPCComponents_Constructor::GetHelperForLanguage(uint32_t language,
  2250                                                   nsISupports **retval)
  2252     *retval = nullptr;
  2253     return NS_OK;
  2256 /* readonly attribute string contractID; */
  2257 NS_IMETHODIMP
  2258 nsXPCComponents_Constructor::GetContractID(char * *aContractID)
  2260     *aContractID = nullptr;
  2261     return NS_ERROR_NOT_AVAILABLE;
  2264 /* readonly attribute string classDescription; */
  2265 NS_IMETHODIMP
  2266 nsXPCComponents_Constructor::GetClassDescription(char * *aClassDescription)
  2268     static const char classDescription[] = "XPCComponents_Constructor";
  2269     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
  2270     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  2273 /* readonly attribute nsCIDPtr classID; */
  2274 NS_IMETHODIMP
  2275 nsXPCComponents_Constructor::GetClassID(nsCID * *aClassID)
  2277     *aClassID = nullptr;
  2278     return NS_OK;
  2281 /* readonly attribute uint32_t implementationLanguage; */
  2282 NS_IMETHODIMP
  2283 nsXPCComponents_Constructor::GetImplementationLanguage(uint32_t *aImplementationLanguage)
  2285     *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  2286     return NS_OK;
  2289 /* readonly attribute uint32_t flags; */
  2290 NS_IMETHODIMP
  2291 nsXPCComponents_Constructor::GetFlags(uint32_t *aFlags)
  2293     *aFlags = 0;
  2294     return NS_OK;
  2297 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
  2298 NS_IMETHODIMP
  2299 nsXPCComponents_Constructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  2301     return NS_ERROR_NOT_AVAILABLE;
  2304 nsXPCComponents_Constructor::nsXPCComponents_Constructor()
  2308 nsXPCComponents_Constructor::~nsXPCComponents_Constructor()
  2310     // empty
  2313 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Constructor)
  2314   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Constructor)
  2315   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  2316   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
  2317   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Constructor)
  2318 NS_INTERFACE_MAP_END
  2320 NS_IMPL_ADDREF(nsXPCComponents_Constructor)
  2321 NS_IMPL_RELEASE(nsXPCComponents_Constructor)
  2323 // The nsIXPCScriptable map declaration that will generate stubs for us...
  2324 #define XPC_MAP_CLASSNAME           nsXPCComponents_Constructor
  2325 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Constructor"
  2326 #define                             XPC_MAP_WANT_CALL
  2327 #define                             XPC_MAP_WANT_CONSTRUCT
  2328 #define                             XPC_MAP_WANT_HASINSTANCE
  2329 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  2330 #include "xpc_map_end.h" /* This will #undef the above */
  2333 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  2334 NS_IMETHODIMP
  2335 nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  2336                                   JSObject *objArg, const CallArgs &args, bool *_retval)
  2338     RootedObject obj(cx, objArg);
  2339     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  2342 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
  2343 NS_IMETHODIMP
  2344 nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
  2345                                        JSObject *objArg, const CallArgs &args, bool *_retval)
  2347     RootedObject obj(cx, objArg);
  2348     return CallOrConstruct(wrapper, cx, obj, args, _retval);
  2351 // static
  2352 nsresult
  2353 nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
  2354                                              JSContext *cx, HandleObject obj,
  2355                                              const CallArgs &args, bool *_retval)
  2357     // make sure we have at least one arg
  2359     if (args.length() < 1)
  2360         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
  2362     // get the various other object pointers we need
  2364     nsXPConnect* xpc = nsXPConnect::XPConnect();
  2365     XPCWrappedNativeScope* scope = GetObjectScope(obj);
  2366     nsCOMPtr<nsIXPCComponents> comp;
  2368     if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents())))
  2369         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  2371     // Do the security check if necessary
  2373     nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
  2374     if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCConstructor::GetCID()))) {
  2375         // the security manager vetoed. It should have set an exception.
  2376         *_retval = false;
  2377         return NS_OK;
  2380     // initialization params for the Constructor object we will create
  2381     nsCOMPtr<nsIJSCID> cClassID;
  2382     nsCOMPtr<nsIJSIID> cInterfaceID;
  2383     const char*        cInitializer = nullptr;
  2384     JSAutoByteString  cInitializerBytes;
  2386     if (args.length() >= 3) {
  2387         // args[2] is an initializer function or property name
  2388         RootedString str(cx, ToString(cx, args[2]));
  2389         if (!str || !(cInitializer = cInitializerBytes.encodeLatin1(cx, str)))
  2390             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  2393     if (args.length() >= 2) {
  2394         // args[1] is an iid name string
  2395         // XXXjband support passing "Components.interfaces.foo"?
  2397         nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
  2398         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  2399         RootedObject ifacesObj(cx);
  2401         // we do the lookup by asking the Components.interfaces object
  2402         // for the property with this name - i.e. we let its caching of these
  2403         // nsIJSIID objects work for us.
  2405         if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
  2406             NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
  2407                                       NS_GET_IID(nsIXPCComponents_Interfaces),
  2408                                       getter_AddRefs(holder))) || !holder ||
  2409             // Assign, not compare
  2410             !(ifacesObj = holder->GetJSObject())) {
  2411             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  2414         RootedString str(cx, ToString(cx, args[1]));
  2415         RootedId id(cx);
  2416         if (!str || !JS_StringToId(cx, str, &id))
  2417             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  2419         RootedValue val(cx);
  2420         if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive())
  2421             return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
  2423         nsCOMPtr<nsIXPConnectWrappedNative> wn;
  2424         if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(),
  2425                                                       getter_AddRefs(wn))) || !wn ||
  2426             !(cInterfaceID = do_QueryWrappedNative(wn))) {
  2427             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  2429     } else {
  2430         nsCOMPtr<nsIInterfaceInfo> info;
  2431         xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info));
  2433         if (info) {
  2434             cInterfaceID = nsJSIID::NewID(info);
  2436         if (!cInterfaceID)
  2437             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  2440     // a new scope to avoid warnings about shadowed names
  2442         // argv[0] is a contractid name string
  2443         // XXXjband support passing "Components.classes.foo"?
  2445         // we do the lookup by asking the Components.classes object
  2446         // for the property with this name - i.e. we let its caching of these
  2447         // nsIJSCID objects work for us.
  2449         nsCOMPtr<nsIXPCComponents_Classes> classes;
  2450         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
  2451         RootedObject classesObj(cx);
  2453         if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
  2454             NS_FAILED(xpc->WrapNative(cx, obj, classes,
  2455                                       NS_GET_IID(nsIXPCComponents_Classes),
  2456                                       getter_AddRefs(holder))) || !holder ||
  2457             // Assign, not compare
  2458             !(classesObj = holder->GetJSObject())) {
  2459             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  2462         RootedString str(cx, ToString(cx, args[0]));
  2463         RootedId id(cx);
  2464         if (!str || !JS_StringToId(cx, str, &id))
  2465             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
  2467         RootedValue val(cx);
  2468         if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive())
  2469             return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
  2471         nsCOMPtr<nsIXPConnectWrappedNative> wn;
  2472         if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val),
  2473                                                       getter_AddRefs(wn))) || !wn ||
  2474             !(cClassID = do_QueryWrappedNative(wn))) {
  2475             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
  2479     nsCOMPtr<nsIXPCConstructor> ctor = new nsXPCConstructor(cClassID, cInterfaceID, cInitializer);
  2480     nsCOMPtr<nsIXPConnectJSObjectHolder> holder2;
  2481     RootedObject newObj(cx);
  2483     if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor),
  2484                                   getter_AddRefs(holder2))) || !holder2 ||
  2485         // Assign, not compare
  2486         !(newObj = holder2->GetJSObject())) {
  2487         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
  2490     args.rval().setObject(*newObj);
  2491     return NS_OK;
  2494 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
  2495 NS_IMETHODIMP
  2496 nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
  2497                                          JSContext * cx, JSObject * obj,
  2498                                          HandleValue val, bool *bp,
  2499                                          bool *_retval)
  2501     if (bp)
  2502         *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIXPCConstructor));
  2503     return NS_OK;
  2506 class nsXPCComponents_Utils :
  2507             public nsIXPCComponents_Utils,
  2508             public nsIXPCScriptable
  2510 public:
  2511     // all the interface method declarations...
  2512     NS_DECL_ISUPPORTS
  2513     NS_DECL_NSIXPCSCRIPTABLE
  2514     NS_DECL_NSIXPCCOMPONENTS_UTILS
  2516 public:
  2517     nsXPCComponents_Utils() { }
  2518     virtual ~nsXPCComponents_Utils() { }
  2520 private:
  2521     nsCOMPtr<nsIXPCComponents_utils_Sandbox> mSandbox;
  2522 };
  2524 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils)
  2525   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils)
  2526   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  2527   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils)
  2528 NS_INTERFACE_MAP_END
  2530 NS_IMPL_ADDREF(nsXPCComponents_Utils)
  2531 NS_IMPL_RELEASE(nsXPCComponents_Utils)
  2533 // The nsIXPCScriptable map declaration that will generate stubs for us...
  2534 #define XPC_MAP_CLASSNAME           nsXPCComponents_Utils
  2535 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Utils"
  2536 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
  2537 #include "xpc_map_end.h" /* This will #undef the above */
  2539 NS_IMETHODIMP
  2540 nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox **aSandbox)
  2542     NS_ENSURE_ARG_POINTER(aSandbox);
  2543     if (!mSandbox)
  2544         mSandbox = NewSandboxConstructor();
  2546     nsCOMPtr<nsIXPCComponents_utils_Sandbox> rval = mSandbox;
  2547     rval.forget(aSandbox);
  2548     return NS_OK;
  2551 /* void reportError (); */
  2552 NS_IMETHODIMP
  2553 nsXPCComponents_Utils::ReportError(HandleValue error, JSContext *cx)
  2555     // This function shall never fail! Silently eat any failure conditions.
  2557     nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  2559     nsCOMPtr<nsIScriptError> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
  2561     if (!scripterr || !console)
  2562         return NS_OK;
  2564     const uint64_t innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
  2566     RootedObject errorObj(cx, error.isObject() ? &error.toObject() : nullptr);
  2567     JSErrorReport *err = errorObj ? JS_ErrorFromException(cx, errorObj) : nullptr;
  2568     if (err) {
  2569         // It's a proper JS Error
  2570         nsAutoString fileUni;
  2571         CopyUTF8toUTF16(err->filename, fileUni);
  2573         uint32_t column = err->uctokenptr - err->uclinebuf;
  2575         const char16_t* ucmessage =
  2576             static_cast<const char16_t*>(err->ucmessage);
  2577         const char16_t* uclinebuf =
  2578             static_cast<const char16_t*>(err->uclinebuf);
  2580         nsresult rv = scripterr->InitWithWindowID(
  2581                 ucmessage ? nsDependentString(ucmessage) : EmptyString(),
  2582                 fileUni,
  2583                 uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
  2584                 err->lineno,
  2585                 column, err->flags, "XPConnect JavaScript", innerWindowID);
  2586         NS_ENSURE_SUCCESS(rv, NS_OK);
  2588         console->LogMessage(scripterr);
  2589         return NS_OK;
  2592     // It's not a JS Error object, so we synthesize as best we're able.
  2593     RootedString msgstr(cx, ToString(cx, error));
  2594     if (!msgstr)
  2595         return NS_OK;
  2597     nsCOMPtr<nsIStackFrame> frame;
  2598     nsXPConnect *xpc = nsXPConnect::XPConnect();
  2599     xpc->GetCurrentJSStack(getter_AddRefs(frame));
  2601     nsString fileName;
  2602     int32_t lineNo = 0;
  2603     if (frame) {
  2604         frame->GetFilename(fileName);
  2605         frame->GetLineNumber(&lineNo);
  2608     const jschar *msgchars = JS_GetStringCharsZ(cx, msgstr);
  2609     if (!msgchars)
  2610         return NS_OK;
  2612     nsresult rv = scripterr->InitWithWindowID(
  2613             nsDependentString(static_cast<const char16_t *>(msgchars)),
  2614             fileName, EmptyString(), lineNo, 0, 0,
  2615             "XPConnect JavaScript", innerWindowID);
  2616     NS_ENSURE_SUCCESS(rv, NS_OK);
  2618     console->LogMessage(scripterr);
  2619     return NS_OK;
  2622 /* void evalInSandbox(in AString source, in nativeobj sandbox); */
  2623 NS_IMETHODIMP
  2624 nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
  2625                                      HandleValue sandboxVal,
  2626                                      HandleValue version,
  2627                                      const nsACString& filenameArg,
  2628                                      int32_t lineNumber,
  2629                                      JSContext *cx,
  2630                                      uint8_t optionalArgc,
  2631                                      MutableHandleValue retval)
  2633     RootedObject sandbox(cx);
  2634     if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox)
  2635         return NS_ERROR_INVALID_ARG;
  2637     // Optional third argument: JS version, as a string.
  2638     JSVersion jsVersion = JSVERSION_DEFAULT;
  2639     if (optionalArgc >= 1) {
  2640         JSString *jsVersionStr = ToString(cx, version);
  2641         if (!jsVersionStr)
  2642             return NS_ERROR_INVALID_ARG;
  2644         JSAutoByteString bytes(cx, jsVersionStr);
  2645         if (!bytes)
  2646             return NS_ERROR_INVALID_ARG;
  2648         jsVersion = JS_StringToVersion(bytes.ptr());
  2649         // Explicitly check for "latest", which we support for sandboxes but
  2650         // isn't in the set of web-exposed version strings.
  2651         if (jsVersion == JSVERSION_UNKNOWN &&
  2652             !strcmp(bytes.ptr(), "latest"))
  2654             jsVersion = JSVERSION_LATEST;
  2656         if (jsVersion == JSVERSION_UNKNOWN)
  2657             return NS_ERROR_INVALID_ARG;
  2660     // Optional fourth and fifth arguments: filename and line number.
  2661     int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1;
  2662     nsCString filename;
  2663     if (!filenameArg.IsVoid()) {
  2664         filename.Assign(filenameArg);
  2665     } else {
  2666         // Get the current source info from xpc.
  2667         nsresult rv;
  2668         nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
  2669         NS_ENSURE_SUCCESS(rv, rv);
  2671         nsCOMPtr<nsIStackFrame> frame;
  2672         xpc->GetCurrentJSStack(getter_AddRefs(frame));
  2673         if (frame) {
  2674             nsString frameFile;
  2675             frame->GetFilename(frameFile);
  2676             CopyUTF16toUTF8(frameFile, filename);
  2677             frame->GetLineNumber(&lineNo);
  2681     return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo,
  2682                               jsVersion, false, retval);
  2685 NS_IMETHODIMP
  2686 nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal,
  2687                                           JSContext *cx, MutableHandleValue rval)
  2689     if (!sandboxVal.isObject())
  2690         return NS_ERROR_INVALID_ARG;
  2692     RootedObject sandbox(cx, &sandboxVal.toObject());
  2693     sandbox = js::CheckedUnwrap(sandbox);
  2694     if (!sandbox || !xpc::IsSandbox(sandbox))
  2695         return NS_ERROR_INVALID_ARG;
  2697     return xpc::GetSandboxMetadata(cx, sandbox, rval);
  2700 NS_IMETHODIMP
  2701 nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal,
  2702                                           HandleValue metadataVal,
  2703                                           JSContext *cx)
  2705     if (!sandboxVal.isObject())
  2706         return NS_ERROR_INVALID_ARG;
  2708     RootedObject sandbox(cx, &sandboxVal.toObject());
  2709     sandbox = js::CheckedUnwrap(sandbox);
  2710     if (!sandbox || !xpc::IsSandbox(sandbox))
  2711         return NS_ERROR_INVALID_ARG;
  2713     nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadataVal);
  2714     NS_ENSURE_SUCCESS(rv, rv);
  2716     return NS_OK;
  2719 /* JSObject import (in AUTF8String registryLocation,
  2720  *                  [optional] in JSObject targetObj);
  2721  */
  2722 NS_IMETHODIMP
  2723 nsXPCComponents_Utils::Import(const nsACString& registryLocation,
  2724                               HandleValue targetObj,
  2725                               JSContext* cx,
  2726                               uint8_t optionalArgc,
  2727                               MutableHandleValue retval)
  2729     nsCOMPtr<xpcIJSModuleLoader> moduleloader =
  2730         do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
  2731     if (!moduleloader)
  2732         return NS_ERROR_FAILURE;
  2733     return moduleloader->Import(registryLocation, targetObj, cx, optionalArgc, retval);
  2736 /* unload (in AUTF8String registryLocation);
  2737  */
  2738 NS_IMETHODIMP
  2739 nsXPCComponents_Utils::Unload(const nsACString & registryLocation)
  2741     nsCOMPtr<xpcIJSModuleLoader> moduleloader =
  2742         do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
  2743     if (!moduleloader)
  2744         return NS_ERROR_FAILURE;
  2745     return moduleloader->Unload(registryLocation);
  2748 /*
  2749  * JSObject importGlobalProperties (in jsval aPropertyList);
  2750  */
  2751 NS_IMETHODIMP
  2752 nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
  2753                                               JSContext* cx)
  2755     RootedObject global(cx, CurrentGlobalOrNull(cx));
  2756     MOZ_ASSERT(global);
  2757     GlobalProperties options(false);
  2758     NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
  2759     RootedObject propertyList(cx, &aPropertyList.toObject());
  2760     NS_ENSURE_TRUE(JS_IsArrayObject(cx, propertyList), NS_ERROR_INVALID_ARG);
  2761     if (!options.Parse(cx, propertyList) ||
  2762         !options.Define(cx, global))
  2764         return NS_ERROR_FAILURE;
  2767     return NS_OK;
  2770 /* xpcIJSWeakReference getWeakReference (); */
  2771 NS_IMETHODIMP
  2772 nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext *cx,
  2773                                         xpcIJSWeakReference **_retval)
  2775     nsRefPtr<xpcJSWeakReference> ref = new xpcJSWeakReference();
  2776     nsresult rv = ref->Init(cx, object);
  2777     NS_ENSURE_SUCCESS(rv, rv);
  2778     ref.forget(_retval);
  2779     return NS_OK;
  2782 /* void forceGC (); */
  2783 NS_IMETHODIMP
  2784 nsXPCComponents_Utils::ForceGC()
  2786     JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
  2787     PrepareForFullGC(rt);
  2788     GCForReason(rt, gcreason::COMPONENT_UTILS);
  2789     return NS_OK;
  2792 /* void forceCC (); */
  2793 NS_IMETHODIMP
  2794 nsXPCComponents_Utils::ForceCC()
  2796     nsJSContext::CycleCollectNow();
  2797     return NS_OK;
  2800 /* void forceShrinkingGC (); */
  2801 NS_IMETHODIMP
  2802 nsXPCComponents_Utils::ForceShrinkingGC()
  2804     JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
  2805     PrepareForFullGC(rt);
  2806     ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
  2807     return NS_OK;
  2810 class PreciseGCRunnable : public nsRunnable
  2812   public:
  2813     PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking)
  2814     : mCallback(aCallback), mShrinking(aShrinking) {}
  2816     NS_IMETHOD Run()
  2818         JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
  2820         JSContext *cx;
  2821         JSContext *iter = nullptr;
  2822         while ((cx = JS_ContextIterator(rt, &iter)) != nullptr) {
  2823             if (JS_IsRunning(cx)) {
  2824                 return NS_DispatchToMainThread(this);
  2828         PrepareForFullGC(rt);
  2829         if (mShrinking)
  2830             ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
  2831         else
  2832             GCForReason(rt, gcreason::COMPONENT_UTILS);
  2834         mCallback->Callback();
  2835         return NS_OK;
  2838   private:
  2839     nsRefPtr<ScheduledGCCallback> mCallback;
  2840     bool mShrinking;
  2841 };
  2843 /* void schedulePreciseGC(in ScheduledGCCallback callback); */
  2844 NS_IMETHODIMP
  2845 nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback)
  2847     nsRefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, false);
  2848     return NS_DispatchToMainThread(event);
  2851 /* void schedulePreciseShrinkingGC(in ScheduledGCCallback callback); */
  2852 NS_IMETHODIMP
  2853 nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback)
  2855     nsRefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, true);
  2856     return NS_DispatchToMainThread(event);
  2859 /* void unlinkGhostWindows(); */
  2860 NS_IMETHODIMP
  2861 nsXPCComponents_Utils::UnlinkGhostWindows()
  2863 #ifdef DEBUG
  2864     nsWindowMemoryReporter::UnlinkGhostWindows();
  2865     return NS_OK;
  2866 #else
  2867     return NS_ERROR_NOT_IMPLEMENTED;
  2868 #endif
  2871 /* [implicit_jscontext] jsval nondeterministicGetWeakMapKeys(in jsval aMap); */
  2872 NS_IMETHODIMP
  2873 nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(HandleValue aMap,
  2874                                                       JSContext *aCx,
  2875                                                       MutableHandleValue aKeys)
  2877     if (!aMap.isObject()) {
  2878         aKeys.setUndefined();
  2879         return NS_OK;
  2881     RootedObject objRet(aCx);
  2882     RootedObject mapObj(aCx, &aMap.toObject());
  2883     if (!JS_NondeterministicGetWeakMapKeys(aCx, mapObj, &objRet))
  2884         return NS_ERROR_OUT_OF_MEMORY;
  2885      aKeys.set(objRet ? ObjectValue(*objRet) : UndefinedValue());
  2886     return NS_OK;
  2889 /* void getDebugObject(); */
  2890 NS_IMETHODIMP
  2891 nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx,
  2892                                              MutableHandleValue retval)
  2894     JSObject *obj = js::GetTestingFunctions(cx);
  2895     if (!obj)
  2896         return NS_ERROR_XPC_JAVASCRIPT_ERROR;
  2897     retval.setObject(*obj);
  2898     return NS_OK;
  2901 /* void getGlobalForObject(); */
  2902 NS_IMETHODIMP
  2903 nsXPCComponents_Utils::GetGlobalForObject(HandleValue object,
  2904                                           JSContext *cx,
  2905                                           MutableHandleValue retval)
  2907     // First argument must be an object.
  2908     if (object.isPrimitive())
  2909         return NS_ERROR_XPC_BAD_CONVERT_JS;
  2911     // Wrappers are parented to their the global in their home compartment. But
  2912     // when getting the global for a cross-compartment wrapper, we really want
  2913     // a wrapper for the foreign global. So we need to unwrap before getting the
  2914     // parent, enter the compartment for the duration of the call, and wrap the
  2915     // result.
  2916     Rooted<JSObject*> obj(cx, &object.toObject());
  2917     obj = js::UncheckedUnwrap(obj);
  2919         JSAutoCompartment ac(cx, obj);
  2920         obj = JS_GetGlobalForObject(cx, obj);
  2923     if (!JS_WrapObject(cx, &obj))
  2924         return NS_ERROR_FAILURE;
  2926     // Outerize if necessary.
  2927     if (JSObjectOp outerize = js::GetObjectClass(obj)->ext.outerObject)
  2928       obj = outerize(cx, obj);
  2930     retval.setObject(*obj);
  2931     return NS_OK;
  2934 /* jsval createObjectIn(in jsval vobj); */
  2935 bool
  2936 xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectInOptions &options,
  2937                     MutableHandleValue rval)
  2939     if (!vobj.isObject()) {
  2940         JS_ReportError(cx, "Expected an object as the target scope");
  2941         return false;
  2944     RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject()));
  2945     if (!scope) {
  2946         JS_ReportError(cx, "Permission denied to create object in the target scope");
  2947         return false;
  2950     bool define = !JSID_IS_VOID(options.defineAs);
  2952     if (define && js::IsScriptedProxy(scope)) {
  2953         JS_ReportError(cx, "Defining property on proxy object is not allowed");
  2954         return false;
  2957     RootedObject obj(cx);
  2959         JSAutoCompartment ac(cx, scope);
  2960         obj = JS_NewObject(cx, nullptr, JS::NullPtr(), scope);
  2961         if (!obj)
  2962             return false;
  2964         if (define) {
  2965             if (!JS_DefinePropertyById(cx, scope, options.defineAs, ObjectValue(*obj),
  2966                                        JS_PropertyStub, JS_StrictPropertyStub,
  2967                                        JSPROP_ENUMERATE))
  2968                 return false;
  2972     rval.setObject(*obj);
  2973     if (!WrapperFactory::WaiveXrayAndWrap(cx, rval))
  2974         return false;
  2976     return true;
  2979 /* boolean isProxy(in value vobj); */
  2980 NS_IMETHODIMP
  2981 nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext *cx, bool *rval)
  2983     if (!vobj.isObject()) {
  2984         *rval = false;
  2985         return NS_OK;
  2988     RootedObject obj(cx, &vobj.toObject());
  2989     obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
  2990     NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
  2992     *rval = js::IsScriptedProxy(obj);
  2993     return NS_OK;
  2996 /* jsval evalInWindow(in string source, in jsval window); */
  2997 NS_IMETHODIMP
  2998 nsXPCComponents_Utils::EvalInWindow(const nsAString &source, HandleValue window,
  2999                                     JSContext *cx, MutableHandleValue rval)
  3001     if (!window.isObject())
  3002         return NS_ERROR_INVALID_ARG;
  3004     RootedObject rwindow(cx, &window.toObject());
  3005     if (!xpc::EvalInWindow(cx, source, rwindow, rval))
  3006         return NS_ERROR_FAILURE;
  3007     return NS_OK;
  3010 /* jsval exportFunction(in jsval vfunction, in jsval vscope, in jsval voptions); */
  3011 NS_IMETHODIMP
  3012 nsXPCComponents_Utils::ExportFunction(HandleValue vfunction, HandleValue vscope,
  3013                                       HandleValue voptions, JSContext *cx,
  3014                                       MutableHandleValue rval)
  3016     if (!xpc::ExportFunction(cx, vfunction, vscope, voptions, rval))
  3017         return NS_ERROR_FAILURE;
  3018     return NS_OK;
  3021 /* jsval createObjectIn(in jsval vobj, [optional] in jsval voptions); */
  3022 NS_IMETHODIMP
  3023 nsXPCComponents_Utils::CreateObjectIn(HandleValue vobj, HandleValue voptions,
  3024                                       JSContext *cx, MutableHandleValue rval)
  3026     RootedObject optionsObject(cx, voptions.isObject() ? &voptions.toObject()
  3027                                                        : nullptr);
  3028     CreateObjectInOptions options(cx, optionsObject);
  3029     if (voptions.isObject() &&
  3030         !options.Parse())
  3032         return NS_ERROR_FAILURE;
  3035     if (!xpc::CreateObjectIn(cx, vobj, options, rval))
  3036         return NS_ERROR_FAILURE;
  3037     return NS_OK;
  3040 /* void makeObjectPropsNormal(jsval vobj); */
  3041 NS_IMETHODIMP
  3042 nsXPCComponents_Utils::MakeObjectPropsNormal(HandleValue vobj, JSContext *cx)
  3044     if (!cx)
  3045         return NS_ERROR_FAILURE;
  3047     // first argument must be an object
  3048     if (vobj.isPrimitive())
  3049         return NS_ERROR_XPC_BAD_CONVERT_JS;
  3051     RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
  3052     JSAutoCompartment ac(cx, obj);
  3053     AutoIdArray ida(cx, JS_Enumerate(cx, obj));
  3054     if (!ida)
  3055         return NS_ERROR_FAILURE;
  3057     RootedId id(cx);
  3058     RootedValue v(cx);
  3059     for (size_t i = 0; i < ida.length(); ++i) {
  3060         id = ida[i];
  3062         if (!JS_GetPropertyById(cx, obj, id, &v))
  3063             return NS_ERROR_FAILURE;
  3065         if (v.isPrimitive())
  3066             continue;
  3068         RootedObject propobj(cx, &v.toObject());
  3069         // TODO Deal with non-functions.
  3070         if (!js::IsWrapper(propobj) || !JS_ObjectIsCallable(cx, propobj))
  3071             continue;
  3073         if (!NewFunctionForwarder(cx, id, propobj, /* doclone = */ false, &v) ||
  3074             !JS_SetPropertyById(cx, obj, id, v))
  3075             return NS_ERROR_FAILURE;
  3078     return NS_OK;
  3081 NS_IMETHODIMP
  3082 nsXPCComponents_Utils::IsDeadWrapper(HandleValue obj, bool *out)
  3084     *out = false;
  3085     if (obj.isPrimitive())
  3086         return NS_ERROR_INVALID_ARG;
  3088     // Make sure to unwrap first. Once a proxy is nuked, it ceases to be a
  3089     // wrapper, meaning that, if passed to another compartment, we'll generate
  3090     // a CCW for it. Make sure that IsDeadWrapper sees through the confusion.
  3091     *out = JS_IsDeadWrapper(js::CheckedUnwrap(&obj.toObject()));
  3092     return NS_OK;
  3095 /* void recomputerWrappers(jsval vobj); */
  3096 NS_IMETHODIMP
  3097 nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext *cx)
  3099     // Determine the compartment of the given object, if any.
  3100     JSCompartment *c = vobj.isObject()
  3101                        ? js::GetObjectCompartment(js::UncheckedUnwrap(&vobj.toObject()))
  3102                        : nullptr;
  3104     // If no compartment was given, recompute all.
  3105     if (!c)
  3106         js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments());
  3107     // Otherwise, recompute wrappers for the given compartment.
  3108     else
  3109         js::RecomputeWrappers(cx, js::SingleCompartment(c), js::AllCompartments()) &&
  3110         js::RecomputeWrappers(cx, js::AllCompartments(), js::SingleCompartment(c));
  3112     return NS_OK;
  3115 /* jsval setWantXrays(jsval vscope); */
  3116 NS_IMETHODIMP
  3117 nsXPCComponents_Utils::SetWantXrays(HandleValue vscope, JSContext *cx)
  3119     if (!vscope.isObject())
  3120         return NS_ERROR_INVALID_ARG;
  3121     JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
  3122     JSCompartment *compartment = js::GetObjectCompartment(scopeObj);
  3123     EnsureCompartmentPrivate(scopeObj)->wantXrays = true;
  3124     bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
  3125                                     js::AllCompartments());
  3126     NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
  3127     return NS_OK;
  3130 /* jsval forcePrivilegedComponentsForScope(jsval vscope); */
  3131 NS_IMETHODIMP
  3132 nsXPCComponents_Utils::ForcePrivilegedComponentsForScope(HandleValue vscope,
  3133                                                          JSContext *cx)
  3135     if (!vscope.isObject())
  3136         return NS_ERROR_INVALID_ARG;
  3137     JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
  3138     XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
  3139     scope->ForcePrivilegedComponents();
  3140     return NS_OK;
  3143 /* jsval getComponentsForScope(jsval vscope); */
  3144 NS_IMETHODIMP
  3145 nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext *cx,
  3146                                              MutableHandleValue rval)
  3148     if (!vscope.isObject())
  3149         return NS_ERROR_INVALID_ARG;
  3150     JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
  3151     XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
  3152     RootedObject components(cx);
  3153     if (!scope->GetComponentsJSObject(&components))
  3154         return NS_ERROR_FAILURE;
  3155     if (!JS_WrapObject(cx, &components))
  3156         return NS_ERROR_FAILURE;
  3157     rval.setObject(*components);
  3158     return NS_OK;
  3161 NS_IMETHODIMP
  3162 nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
  3163                                 JSContext *cx)
  3165     RootedValue runnable(cx, runnableArg);
  3166     // Enter the given compartment, if any, and rewrap runnable.
  3167     Maybe<JSAutoCompartment> ac;
  3168     if (scope.isObject()) {
  3169         JSObject *scopeObj = js::UncheckedUnwrap(&scope.toObject());
  3170         if (!scopeObj)
  3171             return NS_ERROR_FAILURE;
  3172         ac.construct(cx, scopeObj);
  3173         if (!JS_WrapValue(cx, &runnable))
  3174             return NS_ERROR_FAILURE;
  3177     // Get an XPCWrappedJS for |runnable|.
  3178     if (!runnable.isObject())
  3179         return NS_ERROR_INVALID_ARG;
  3181     nsCOMPtr<nsIRunnable> run;
  3182     nsresult rv = nsXPConnect::XPConnect()->WrapJS(cx, &runnable.toObject(),
  3183                                                    NS_GET_IID(nsIRunnable),
  3184                                                    getter_AddRefs(run));
  3185     NS_ENSURE_SUCCESS(rv, rv);
  3186     MOZ_ASSERT(run);
  3188     // Dispatch.
  3189     return NS_DispatchToMainThread(run);
  3192 #define GENERATE_JSCONTEXTOPTION_GETTER_SETTER(_attr, _getter, _setter) \
  3193     NS_IMETHODIMP                                                       \
  3194     nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue)     \
  3195     {                                                                   \
  3196         *aValue = ContextOptionsRef(cx)._getter();                      \
  3197         return NS_OK;                                                   \
  3198     }                                                                   \
  3199     NS_IMETHODIMP                                                       \
  3200     nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue)      \
  3201     {                                                                   \
  3202         ContextOptionsRef(cx)._setter(aValue);                          \
  3203         return NS_OK;                                                   \
  3206 #define GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(_attr, _getter, _setter) \
  3207     NS_IMETHODIMP                                                       \
  3208     nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue)     \
  3209     {                                                                   \
  3210         *aValue = RuntimeOptionsRef(cx)._getter();                      \
  3211         return NS_OK;                                                   \
  3212     }                                                                   \
  3213     NS_IMETHODIMP                                                       \
  3214     nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue)      \
  3215     {                                                                   \
  3216         RuntimeOptionsRef(cx)._setter(aValue);                          \
  3217         return NS_OK;                                                   \
  3220 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
  3221 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Werror, werror, setWerror)
  3222 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
  3223 GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Ion, ion, setIon)
  3225 #undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
  3226 #undef GENERATE_JSRUNTIMEOPTION_GETTER_SETTER
  3228 NS_IMETHODIMP
  3229 nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx)
  3231 #ifdef JS_GC_ZEAL
  3232     JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ);
  3233 #endif
  3234     return NS_OK;
  3237 NS_IMETHODIMP
  3238 nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext *cx)
  3240     NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG);
  3241     JSObject *wrapper = &obj.toObject();
  3242     NS_ENSURE_TRUE(IsWrapper(wrapper), NS_ERROR_INVALID_ARG);
  3243     JSObject *sb = UncheckedUnwrap(wrapper);
  3244     NS_ENSURE_TRUE(IsSandbox(sb), NS_ERROR_INVALID_ARG);
  3245     NukeCrossCompartmentWrappers(cx, AllCompartments(),
  3246                                  SingleCompartment(GetObjectCompartment(sb)),
  3247                                  NukeWindowReferences);
  3248     return NS_OK;
  3251 NS_IMETHODIMP
  3252 nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
  3253                                             JSContext *cx)
  3255     NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
  3256     RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
  3257                                             /* stopAtOuter = */ false));
  3258     NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
  3259     if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
  3260         JS_ReportError(cx, "Script may not be disabled for system globals");
  3261         return NS_ERROR_FAILURE;
  3263     Scriptability::Get(global).Block();
  3264     return NS_OK;
  3267 NS_IMETHODIMP
  3268 nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
  3269                                               JSContext *cx)
  3271     NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
  3272     RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
  3273                                             /* stopAtOuter = */ false));
  3274     NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
  3275     if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
  3276         JS_ReportError(cx, "Script may not be disabled for system globals");
  3277         return NS_ERROR_FAILURE;
  3279     Scriptability::Get(global).Unblock();
  3280     return NS_OK;
  3283 NS_IMETHODIMP
  3284 nsXPCComponents_Utils::IsXrayWrapper(HandleValue obj, bool* aRetval)
  3286     *aRetval =
  3287         obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
  3288     return NS_OK;
  3291 NS_IMETHODIMP
  3292 nsXPCComponents_Utils::WaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval)
  3294     RootedValue value(aCx, aVal);
  3295     if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value))
  3296         return NS_ERROR_FAILURE;
  3297     aRetval.set(value);
  3298     return NS_OK;
  3301 NS_IMETHODIMP
  3302 nsXPCComponents_Utils::UnwaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval)
  3304     if (!aVal.isObject()) {
  3305         aRetval.set(aVal);
  3306         return NS_OK;
  3309     RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject()));
  3310     if (!JS_WrapObject(aCx, &obj))
  3311         return NS_ERROR_FAILURE;
  3312     aRetval.setObject(*obj);
  3313     return NS_OK;
  3316 NS_IMETHODIMP
  3317 nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap, JSContext *aCx, char **aRv)
  3319     if (!aObj.isObject())
  3320         return NS_ERROR_INVALID_ARG;
  3321     RootedObject obj(aCx, &aObj.toObject());
  3322     if (aUnwrap)
  3323         obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
  3324     *aRv = NS_strdup(js::GetObjectClass(obj)->name);
  3325     NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY);
  3326     return NS_OK;
  3329 NS_IMETHODIMP
  3330 nsXPCComponents_Utils::GetDOMClassInfo(const nsAString& aClassName,
  3331                                        nsIClassInfo** aClassInfo)
  3333     *aClassInfo = nullptr;
  3334     return NS_ERROR_NOT_AVAILABLE;
  3337 NS_IMETHODIMP
  3338 nsXPCComponents_Utils::GetIncumbentGlobal(HandleValue aCallback,
  3339                                           JSContext *aCx, MutableHandleValue aOut)
  3341     nsCOMPtr<nsIGlobalObject> global = mozilla::dom::GetIncumbentGlobal();
  3342     RootedValue globalVal(aCx);
  3344     if (!global) {
  3345         globalVal = NullValue();
  3346     } else {
  3347         // Note: We rely on the wrap call for outerization.
  3348         globalVal = ObjectValue(*global->GetGlobalJSObject());
  3349         if (!JS_WrapValue(aCx, &globalVal))
  3350             return NS_ERROR_FAILURE;
  3353     // Invoke the callback, if passed.
  3354     if (aCallback.isObject()) {
  3355         RootedValue ignored(aCx);
  3356         if (!JS_CallFunctionValue(aCx, JS::NullPtr(), aCallback, globalVal, &ignored))
  3357             return NS_ERROR_FAILURE;
  3360     aOut.set(globalVal);
  3361     return NS_OK;
  3364 /*
  3365  * Below is a bunch of awkward junk to allow JS test code to trigger the
  3366  * creation of an XPCWrappedJS, such that it ends up in the map. We need to
  3367  * hand the caller some sort of reference to hold onto (to prevent the
  3368  * refcount from dropping to zero as soon as the function returns), but trying
  3369  * to return a bonafide XPCWrappedJS to script causes all sorts of trouble. So
  3370  * we create a benign holder class instead, which acts as an opaque reference
  3371  * that script can use to keep the XPCWrappedJS alive and in the map.
  3372  */
  3374 class WrappedJSHolder : public nsISupports
  3376     NS_DECL_ISUPPORTS
  3377     WrappedJSHolder() {}
  3378     virtual ~WrappedJSHolder() {}
  3380     nsRefPtr<nsXPCWrappedJS> mWrappedJS;
  3381 };
  3382 NS_IMPL_ISUPPORTS0(WrappedJSHolder);
  3384 NS_IMETHODIMP
  3385 nsXPCComponents_Utils::GenerateXPCWrappedJS(HandleValue aObj, HandleValue aScope,
  3386                                             JSContext *aCx, nsISupports **aOut)
  3388     if (!aObj.isObject())
  3389         return NS_ERROR_INVALID_ARG;
  3390     RootedObject obj(aCx, &aObj.toObject());
  3391     RootedObject scope(aCx, aScope.isObject() ? js::UncheckedUnwrap(&aScope.toObject())
  3392                                               : CurrentGlobalOrNull(aCx));
  3393     JSAutoCompartment ac(aCx, scope);
  3394     if (!JS_WrapObject(aCx, &obj))
  3395         return NS_ERROR_FAILURE;
  3397     nsRefPtr<WrappedJSHolder> holder = new WrappedJSHolder();
  3398     nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports),
  3399                                                getter_AddRefs(holder->mWrappedJS));
  3400     holder.forget(aOut);
  3401     return rv;
  3404 NS_IMETHODIMP
  3405 nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory, PRTime *aOut)
  3407     WatchdogTimestampCategory category;
  3408     if (aCategory.EqualsLiteral("RuntimeStateChange"))
  3409         category = TimestampRuntimeStateChange;
  3410     else if (aCategory.EqualsLiteral("WatchdogWakeup"))
  3411         category = TimestampWatchdogWakeup;
  3412     else if (aCategory.EqualsLiteral("WatchdogHibernateStart"))
  3413         category = TimestampWatchdogHibernateStart;
  3414     else if (aCategory.EqualsLiteral("WatchdogHibernateStop"))
  3415         category = TimestampWatchdogHibernateStop;
  3416     else
  3417         return NS_ERROR_INVALID_ARG;
  3418     *aOut = XPCJSRuntime::Get()->GetWatchdogTimestamp(category);
  3419     return NS_OK;
  3422 NS_IMETHODIMP
  3423 nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext *cx, MutableHandleValue rval)
  3425     RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
  3426     if (!obj)
  3427         return NS_ERROR_OUT_OF_MEMORY;
  3429     unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
  3431     size_t i = JS_SetProtoCalled(cx);
  3432     RootedValue v(cx, DoubleValue(i));
  3433     if (!JS_DefineProperty(cx, obj, "setProto", v, attrs))
  3434         return NS_ERROR_OUT_OF_MEMORY;
  3436     i = JS_GetCustomIteratorCount(cx);
  3437     v.setDouble(i);
  3438     if (!JS_DefineProperty(cx, obj, "customIter", v, attrs))
  3439         return NS_ERROR_OUT_OF_MEMORY;
  3441     rval.setObject(*obj);
  3442     return NS_OK;
  3445 class MOZ_STACK_CLASS CloneIntoOptions : public OptionsBase
  3447 public:
  3448     CloneIntoOptions(JSContext *cx = xpc_GetSafeJSContext(),
  3449                      JSObject *options = nullptr)
  3450         : OptionsBase(cx, options)
  3451         , cloneFunctions(false)
  3452     {}
  3454     virtual bool Parse()
  3456         return ParseBoolean("cloneFunctions", &cloneFunctions);
  3459     bool cloneFunctions;
  3460 };
  3462 class MOZ_STACK_CLASS CloneIntoCallbacksData
  3464 public:
  3465     CloneIntoCallbacksData(JSContext *aCx, CloneIntoOptions *aOptions)
  3466         : mOptions(aOptions)
  3467         , mFunctions(aCx)
  3468     {}
  3470     CloneIntoOptions *mOptions;
  3471     AutoObjectVector mFunctions;
  3472 };
  3474 static JSObject*
  3475 CloneIntoReadStructuredClone(JSContext *cx,
  3476                              JSStructuredCloneReader *reader,
  3477                              uint32_t tag,
  3478                              uint32_t value,
  3479                              void* closure)
  3481     CloneIntoCallbacksData* data = static_cast<CloneIntoCallbacksData*>(closure);
  3482     MOZ_ASSERT(data);
  3484     if (tag == mozilla::dom::SCTAG_DOM_BLOB || tag == mozilla::dom::SCTAG_DOM_FILELIST) {
  3485         MOZ_ASSERT(!value, "Data should be empty");
  3487         nsISupports *supports;
  3488         if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
  3489             RootedValue val(cx);
  3490             if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val)))
  3491                 return val.toObjectOrNull();
  3495     if (tag == mozilla::dom::SCTAG_DOM_FUNCTION) {
  3496       MOZ_ASSERT(value < data->mFunctions.length());
  3498       RootedValue functionValue(cx);
  3499       RootedObject obj(cx, data->mFunctions[value]);
  3501       if (!JS_WrapObject(cx, &obj))
  3502           return nullptr;
  3504       if (!xpc::NewFunctionForwarder(cx, obj, false, &functionValue))
  3505           return nullptr;
  3507       return &functionValue.toObject();
  3510     return nullptr;
  3513 static bool
  3514 CloneIntoWriteStructuredClone(JSContext *cx,
  3515                               JSStructuredCloneWriter *writer,
  3516                               HandleObject obj,
  3517                               void *closure)
  3519     CloneIntoCallbacksData* data = static_cast<CloneIntoCallbacksData*>(closure);
  3520     MOZ_ASSERT(data);
  3522     nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
  3523     nsContentUtils::XPConnect()->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
  3524     if (wrappedNative) {
  3525         uint32_t scTag = 0;
  3526         nsISupports *supports = wrappedNative->Native();
  3528         nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
  3529         if (blob)
  3530             scTag = mozilla::dom::SCTAG_DOM_BLOB;
  3531         else {
  3532             nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
  3533             if (list)
  3534                 scTag = mozilla::dom::SCTAG_DOM_FILELIST;
  3537         if (scTag) {
  3538             return JS_WriteUint32Pair(writer, scTag, 0) &&
  3539                    JS_WriteBytes(writer, &supports, sizeof(supports));
  3543     if (data->mOptions->cloneFunctions && JS_ObjectIsCallable(cx, obj)) {
  3544         data->mFunctions.append(obj);
  3545         return JS_WriteUint32Pair(writer, mozilla::dom::SCTAG_DOM_FUNCTION,
  3546                                   data->mFunctions.length() - 1);
  3549     return false;
  3552 // These functions serialize raw XPCOM pointers in the data stream, and thus
  3553 // should only be used when the read and write are done together
  3554 // synchronously.
  3555 static JSStructuredCloneCallbacks CloneIntoCallbacks = {
  3556     CloneIntoReadStructuredClone,
  3557     CloneIntoWriteStructuredClone,
  3558     nullptr
  3559 };
  3561 bool
  3562 xpc::CloneInto(JSContext *aCx, HandleValue aValue, HandleValue aScope,
  3563                HandleValue aOptions, MutableHandleValue aCloned)
  3565     if (!aScope.isObject())
  3566         return false;
  3568     RootedObject scope(aCx, &aScope.toObject());
  3569     scope = js::CheckedUnwrap(scope);
  3570     if(!scope) {
  3571         JS_ReportError(aCx, "Permission denied to clone object into scope");
  3572         return false;
  3575     if (!aOptions.isUndefined() && !aOptions.isObject()) {
  3576         JS_ReportError(aCx, "Invalid argument");
  3577         return false;
  3580     RootedObject optionsObject(aCx, aOptions.isObject() ? &aOptions.toObject()
  3581                                                         : nullptr);
  3582     CloneIntoOptions options(aCx, optionsObject);
  3583     if (aOptions.isObject() && !options.Parse())
  3584         return false;
  3587         CloneIntoCallbacksData data(aCx, &options);
  3588         JSAutoCompartment ac(aCx, scope);
  3589         if (!JS_StructuredClone(aCx, aValue, aCloned, &CloneIntoCallbacks, &data))
  3590             return false;
  3593     return JS_WrapValue(aCx, aCloned);
  3596 NS_IMETHODIMP
  3597 nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope,
  3598                                  HandleValue aOptions, JSContext *aCx,
  3599                                  MutableHandleValue aCloned)
  3601     return xpc::CloneInto(aCx, aValue, aScope, aOptions, aCloned) ?
  3602            NS_OK : NS_ERROR_FAILURE;
  3605 NS_IMETHODIMP
  3606 nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal **aResult)
  3608     // This API may only be when the Entry Settings Object corresponds to a
  3609     // JS-implemented WebIDL call. In all other cases, the value will be null,
  3610     // and we throw.
  3611     nsCOMPtr<nsIPrincipal> callerPrin = mozilla::dom::GetWebIDLCallerPrincipal();
  3612     if (!callerPrin)
  3613         return NS_ERROR_NOT_AVAILABLE;
  3614     callerPrin.forget(aResult);
  3615     return NS_OK;
  3618 NS_IMETHODIMP
  3619 nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext *cx,
  3620                                           nsIPrincipal **result)
  3622     if (!val.isObject())
  3623         return NS_ERROR_INVALID_ARG;
  3624     RootedObject obj(cx, &val.toObject());
  3625     obj = js::CheckedUnwrap(obj);
  3626     MOZ_ASSERT(obj);
  3628     nsCOMPtr<nsIPrincipal> prin = nsContentUtils::GetObjectPrincipal(obj);
  3629     prin.forget(result);
  3630     return NS_OK;
  3633 /***************************************************************************/
  3634 /***************************************************************************/
  3635 /***************************************************************************/
  3638 nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope)
  3639     :   mScope(aScope)
  3641     MOZ_ASSERT(aScope, "aScope must not be null");
  3644 nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
  3645     :   nsXPCComponentsBase(aScope)
  3649 nsXPCComponentsBase::~nsXPCComponentsBase()
  3653 nsXPCComponents::~nsXPCComponents()
  3657 void
  3658 nsXPCComponentsBase::ClearMembers()
  3660     mInterfaces = nullptr;
  3661     mInterfacesByID = nullptr;
  3662     mResults = nullptr;
  3665 void
  3666 nsXPCComponents::ClearMembers()
  3668     mClasses = nullptr;
  3669     mClassesByID = nullptr;
  3670     mID = nullptr;
  3671     mException = nullptr;
  3672     mConstructor = nullptr;
  3673     mUtils = nullptr;
  3675     nsXPCComponentsBase::ClearMembers();
  3678 /*******************************************/
  3679 #define XPC_IMPL_GET_OBJ_METHOD(_class, _n)                                   \
  3680 NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n * *a##_n) {               \
  3681     NS_ENSURE_ARG_POINTER(a##_n);                                             \
  3682     if (!m##_n)                                                               \
  3683         m##_n = new nsXPCComponents_##_n();                                   \
  3684     nsRefPtr<nsXPCComponents_##_n> ret = m##_n;                               \
  3685     ret.forget(a##_n);                                                        \
  3686     return NS_OK;                                                             \
  3689 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Interfaces)
  3690 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, InterfacesByID)
  3691 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes)
  3692 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ClassesByID)
  3693 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Results)
  3694 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID)
  3695 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception)
  3696 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor)
  3697 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils)
  3699 #undef XPC_IMPL_GET_OBJ_METHOD
  3700 /*******************************************/
  3702 NS_IMETHODIMP
  3703 nsXPCComponentsBase::IsSuccessCode(nsresult result, bool *out)
  3705     *out = NS_SUCCEEDED(result);
  3706     return NS_OK;
  3709 NS_IMETHODIMP
  3710 nsXPCComponents::GetStack(nsIStackFrame * *aStack)
  3712     nsresult rv;
  3713     nsXPConnect* xpc = nsXPConnect::XPConnect();
  3714     rv = xpc->GetCurrentJSStack(aStack);
  3715     return rv;
  3718 NS_IMETHODIMP
  3719 nsXPCComponents::GetManager(nsIComponentManager * *aManager)
  3721     MOZ_ASSERT(aManager, "bad param");
  3722     return NS_GetComponentManager(aManager);
  3725 NS_IMETHODIMP
  3726 nsXPCComponents::GetLastResult(JSContext *aCx, MutableHandleValue aOut)
  3728     XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
  3729     if (!xpcc)
  3730         return NS_ERROR_FAILURE;
  3731     nsresult res = xpcc->GetLastResult();
  3732     aOut.setNumber(static_cast<uint32_t>(res));
  3733     return NS_OK;
  3736 NS_IMETHODIMP
  3737 nsXPCComponents::GetReturnCode(JSContext *aCx, MutableHandleValue aOut)
  3739     XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
  3740     if (!xpcc)
  3741         return NS_ERROR_FAILURE;
  3742     nsresult res = xpcc->GetPendingResult();
  3743     aOut.setNumber(static_cast<uint32_t>(res));
  3744     return NS_OK;
  3747 NS_IMETHODIMP
  3748 nsXPCComponents::SetReturnCode(JSContext *aCx, HandleValue aCode)
  3750     XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
  3751     if (!xpcc)
  3752         return NS_ERROR_FAILURE;
  3753     nsresult rv;
  3754     if (!ToUint32(aCx, aCode, (uint32_t*)&rv))
  3755         return NS_ERROR_FAILURE;
  3756     xpcc->SetPendingResult(rv);
  3757     xpcc->SetLastResult(rv);
  3758     return NS_OK;
  3761 // static
  3762 /* void reportError (); */
  3763 NS_IMETHODIMP nsXPCComponents::ReportError(HandleValue error, JSContext *cx)
  3765     NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
  3767     nsCOMPtr<nsIXPCComponents_Utils> utils;
  3768     nsresult rv = GetUtils(getter_AddRefs(utils));
  3769     if (NS_FAILED(rv))
  3770         return rv;
  3772     return utils->ReportError(error, cx);
  3775 /**********************************************/
  3777 class ComponentsSH : public nsIXPCScriptable
  3779 public:
  3780     ComponentsSH(unsigned dummy)
  3784     NS_DECL_ISUPPORTS
  3785     NS_DECL_NSIXPCSCRIPTABLE
  3786     // The NS_IMETHODIMP isn't really accurate here, but NS_CALLBACK requires
  3787     // the referent to be declared __stdcall on Windows, and this is the only
  3788     // macro that does that.
  3789     static NS_IMETHODIMP Get(uint32_t aLangId, nsISupports **helper)
  3791         *helper = &singleton;
  3792         return NS_OK;
  3795 private:
  3796     static ComponentsSH singleton;
  3797 };
  3799 ComponentsSH ComponentsSH::singleton(0);
  3801 // Singleton refcounting.
  3802 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::AddRef(void) { return 1; }
  3803 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::Release(void) { return 1; }
  3805 NS_INTERFACE_MAP_BEGIN(ComponentsSH)
  3806   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
  3807   NS_INTERFACE_MAP_ENTRY(nsISupports)
  3808 NS_INTERFACE_MAP_END
  3810 #define NSXPCCOMPONENTSBASE_CID \
  3811 { 0xc62998e5, 0x95f1, 0x4058, \
  3812   { 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 } }
  3814 #define NSXPCCOMPONENTS_CID \
  3815 { 0x3649f405, 0xf0ec, 0x4c28, \
  3816     { 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 } }
  3818 NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID)
  3819 NS_IMPL_ISUPPORTS_CI(nsXPCComponentsBase, nsIXPCComponentsBase)
  3821 NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTS_CID)
  3822 // Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like
  3823 // if it existed.
  3824 NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase)
  3825 NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase)
  3826 NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
  3827     NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
  3828     NS_IMPL_QUERY_CLASSINFO(nsXPCComponents)
  3829 NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase)
  3830 NS_IMPL_CI_INTERFACE_GETTER(nsXPCComponents, nsIXPCComponents)
  3832 // The nsIXPCScriptable map declaration that will generate stubs for us
  3833 #define XPC_MAP_CLASSNAME           ComponentsSH
  3834 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents"
  3835 #define                             XPC_MAP_WANT_PRECREATE
  3836 #include "xpc_map_end.h" /* This will #undef the above */
  3838 NS_IMETHODIMP
  3839 ComponentsSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj)
  3841   nsXPCComponentsBase *self = static_cast<nsXPCComponentsBase*>(nativeObj);
  3842   // this should never happen
  3843   if (!self->GetScope()) {
  3844       NS_WARNING("mScope must not be null when nsXPCComponents::PreCreate is called");
  3845       return NS_ERROR_FAILURE;
  3847   *parentObj = self->GetScope()->GetGlobalJSObject();
  3848   return NS_OK;

mercurial