tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

XPCComponents.cpp (81032B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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/. */
      6 
      7 /* The "Components" xpcom objects for JavaScript. */
      8 
      9 #include "xpcprivate.h"
     10 #include "xpc_make_class.h"
     11 #include "XPCJSWeakReference.h"
     12 #include "AccessCheck.h"
     13 #include "WrapperFactory.h"
     14 #include "nsJSUtils.h"
     15 #include "mozJSModuleLoader.h"
     16 #include "nsContentUtils.h"
     17 #include "nsCycleCollector.h"
     18 #include "jsfriendapi.h"
     19 #include "js/Array.h"  // JS::IsArrayObject
     20 #include "js/CallAndConstruct.h"  // JS::IsCallable, JS_CallFunctionName, JS_CallFunctionValue
     21 #include "js/CharacterEncoding.h"
     22 #include "js/friend/WindowProxy.h"  // js::ToWindowProxyIfWindow
     23 #include "js/Object.h"              // JS::GetClass, JS::GetCompartment
     24 #include "js/PropertyAndElement.h"  // JS_DefineProperty, JS_DefinePropertyById, JS_Enumerate, JS_GetProperty, JS_GetPropertyById, JS_HasProperty, JS_SetProperty, JS_SetPropertyById
     25 #include "js/SavedFrameAPI.h"
     26 #include "js/StructuredClone.h"
     27 #include "mozilla/AppShutdown.h"
     28 #include "mozilla/Attributes.h"
     29 #include "mozilla/LoadContext.h"
     30 #include "mozilla/Preferences.h"
     31 #include "nsJSEnvironment.h"
     32 #include "mozilla/BasePrincipal.h"
     33 #include "mozilla/TimeStamp.h"
     34 #include "mozilla/ResultExtensions.h"
     35 #include "mozilla/Try.h"
     36 #include "mozilla/URLPreloader.h"
     37 #include "mozilla/dom/DOMException.h"
     38 #include "mozilla/dom/DOMExceptionBinding.h"
     39 #include "mozilla/dom/Exceptions.h"
     40 #include "mozilla/dom/BindingUtils.h"
     41 #include "mozilla/dom/RemoteObjectProxy.h"
     42 #include "mozilla/dom/StructuredCloneTags.h"
     43 #include "mozilla/dom/WindowBinding.h"
     44 #include "nsZipArchive.h"
     45 #include "nsWindowMemoryReporter.h"
     46 #include "nsICycleCollectorListener.h"
     47 #include "nsIException.h"
     48 #include "nsIScriptError.h"
     49 #include "nsPIDOMWindow.h"
     50 #include "nsGlobalWindowInner.h"
     51 #include "nsScriptError.h"
     52 #include "GeckoProfiler.h"
     53 #include "ProfilerControl.h"
     54 #include "mozilla/EditorSpellCheck.h"
     55 #include "nsCommandLine.h"
     56 #include "nsCommandParams.h"
     57 #include "nsPersistentProperties.h"
     58 #include "nsIDocumentEncoder.h"
     59 
     60 using namespace mozilla;
     61 using namespace JS;
     62 using namespace js;
     63 using namespace xpc;
     64 using mozilla::dom::Exception;
     65 
     66 /***************************************************************************/
     67 // stuff used by all
     68 
     69 nsresult xpc::ThrowAndFail(nsresult errNum, JSContext* cx, bool* retval) {
     70  XPCThrower::Throw(errNum, cx);
     71  *retval = false;
     72  return NS_OK;
     73 }
     74 
     75 static bool JSValIsInterfaceOfType(JSContext* cx, HandleValue v, REFNSIID iid) {
     76  nsCOMPtr<nsIXPConnectWrappedNative> wn;
     77  nsCOMPtr<nsISupports> iface;
     78 
     79  if (v.isPrimitive()) {
     80    return false;
     81  }
     82 
     83  nsIXPConnect* xpc = nsIXPConnect::XPConnect();
     84  RootedObject obj(cx, &v.toObject());
     85  return NS_SUCCEEDED(
     86             xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) &&
     87         wn &&
     88         NS_SUCCEEDED(
     89             wn->Native()->QueryInterface(iid, getter_AddRefs(iface))) &&
     90         iface;
     91 }
     92 
     93 /***************************************************************************/
     94 /***************************************************************************/
     95 /***************************************************************************/
     96 
     97 class nsXPCComponents_Interfaces final : public nsIXPCComponents_Interfaces,
     98                                         public nsIXPCScriptable,
     99                                         public nsIClassInfo {
    100 public:
    101  // all the interface method declarations...
    102  NS_DECL_ISUPPORTS
    103  NS_DECL_NSIXPCCOMPONENTS_INTERFACES
    104  NS_DECL_NSIXPCSCRIPTABLE
    105  NS_DECL_NSICLASSINFO
    106 
    107 public:
    108  nsXPCComponents_Interfaces();
    109 
    110 private:
    111  virtual ~nsXPCComponents_Interfaces();
    112 };
    113 
    114 NS_IMETHODIMP
    115 nsXPCComponents_Interfaces::GetInterfaces(nsTArray<nsIID>& aArray) {
    116  aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Interfaces),
    117                           NS_GET_IID(nsIXPCScriptable)};
    118  return NS_OK;
    119 }
    120 
    121 NS_IMETHODIMP
    122 nsXPCComponents_Interfaces::GetScriptableHelper(nsIXPCScriptable** retval) {
    123  *retval = nullptr;
    124  return NS_OK;
    125 }
    126 
    127 NS_IMETHODIMP
    128 nsXPCComponents_Interfaces::GetContractID(nsACString& aContractID) {
    129  aContractID.SetIsVoid(true);
    130  return NS_ERROR_NOT_AVAILABLE;
    131 }
    132 
    133 NS_IMETHODIMP
    134 nsXPCComponents_Interfaces::GetClassDescription(nsACString& aClassDescription) {
    135  aClassDescription.AssignLiteral("XPCComponents_Interfaces");
    136  return NS_OK;
    137 }
    138 
    139 NS_IMETHODIMP
    140 nsXPCComponents_Interfaces::GetClassID(nsCID** aClassID) {
    141  *aClassID = nullptr;
    142  return NS_OK;
    143 }
    144 
    145 NS_IMETHODIMP
    146 nsXPCComponents_Interfaces::GetFlags(uint32_t* aFlags) {
    147  *aFlags = 0;
    148  return NS_OK;
    149 }
    150 
    151 NS_IMETHODIMP
    152 nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
    153  return NS_ERROR_NOT_AVAILABLE;
    154 }
    155 
    156 nsXPCComponents_Interfaces::nsXPCComponents_Interfaces() = default;
    157 
    158 nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces() {
    159  // empty
    160 }
    161 
    162 NS_IMPL_ISUPPORTS(nsXPCComponents_Interfaces, nsIXPCComponents_Interfaces,
    163                  nsIXPCScriptable, nsIClassInfo);
    164 
    165 // The nsIXPCScriptable map declaration that will generate stubs for us...
    166 #define XPC_MAP_CLASSNAME nsXPCComponents_Interfaces
    167 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Interfaces"
    168 #define XPC_MAP_FLAGS                                               \
    169  (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
    170   XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
    171 #include "xpc_map_end.h" /* This will #undef the above */
    172 
    173 NS_IMETHODIMP
    174 nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
    175                                         JSContext* cx, JSObject* obj,
    176                                         JS::MutableHandleIdVector properties,
    177                                         bool enumerableOnly, bool* _retval) {
    178  if (!properties.reserve(nsXPTInterfaceInfo::InterfaceCount())) {
    179    *_retval = false;
    180    return NS_OK;
    181  }
    182 
    183  for (uint32_t index = 0; index < nsXPTInterfaceInfo::InterfaceCount();
    184       index++) {
    185    const nsXPTInterfaceInfo* interface = nsXPTInterfaceInfo::ByIndex(index);
    186    if (!interface) {
    187      continue;
    188    }
    189 
    190    const char* name = interface->Name();
    191    if (!name) {
    192      continue;
    193    }
    194 
    195    RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
    196    if (!idstr) {
    197      *_retval = false;
    198      return NS_OK;
    199    }
    200 
    201    RootedId id(cx);
    202    if (!JS_StringToId(cx, idstr, &id)) {
    203      *_retval = false;
    204      return NS_OK;
    205    }
    206 
    207    properties.infallibleAppend(id);
    208  }
    209 
    210  return NS_OK;
    211 }
    212 
    213 NS_IMETHODIMP
    214 nsXPCComponents_Interfaces::Resolve(nsIXPConnectWrappedNative* wrapper,
    215                                    JSContext* cx, JSObject* objArg, jsid idArg,
    216                                    bool* resolvedp, bool* _retval) {
    217  RootedObject obj(cx, objArg);
    218  RootedId id(cx, idArg);
    219 
    220  if (!id.isString()) {
    221    return NS_OK;
    222  }
    223 
    224  RootedString str(cx, id.toString());
    225  JS::UniqueChars name = JS_EncodeStringToLatin1(cx, str);
    226 
    227  // we only allow interfaces by name here
    228  if (name && name[0] != '{') {
    229    const nsXPTInterfaceInfo* info = nsXPTInterfaceInfo::ByName(name.get());
    230    if (!info) {
    231      return NS_OK;
    232    }
    233 
    234    RootedValue iidv(cx);
    235    if (xpc::IfaceID2JSValue(cx, *info, &iidv)) {
    236      *resolvedp = true;
    237      *_retval = JS_DefinePropertyById(cx, obj, id, iidv,
    238                                       JSPROP_ENUMERATE | JSPROP_READONLY |
    239                                           JSPROP_PERMANENT | JSPROP_RESOLVING);
    240    }
    241  }
    242  return NS_OK;
    243 }
    244 
    245 /***************************************************************************/
    246 /***************************************************************************/
    247 /***************************************************************************/
    248 
    249 class nsXPCComponents_Classes final : public nsIXPCComponents_Classes,
    250                                      public nsIXPCScriptable,
    251                                      public nsIClassInfo {
    252 public:
    253  // all the interface method declarations...
    254  NS_DECL_ISUPPORTS
    255  NS_DECL_NSIXPCCOMPONENTS_CLASSES
    256  NS_DECL_NSIXPCSCRIPTABLE
    257  NS_DECL_NSICLASSINFO
    258 
    259 public:
    260  nsXPCComponents_Classes();
    261 
    262 private:
    263  virtual ~nsXPCComponents_Classes();
    264 };
    265 
    266 /***************************************************************************/
    267 NS_IMETHODIMP
    268 nsXPCComponents_Classes::GetInterfaces(nsTArray<nsIID>& aArray) {
    269  aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Classes),
    270                           NS_GET_IID(nsIXPCScriptable)};
    271  return NS_OK;
    272 }
    273 
    274 NS_IMETHODIMP
    275 nsXPCComponents_Classes::GetScriptableHelper(nsIXPCScriptable** retval) {
    276  *retval = nullptr;
    277  return NS_OK;
    278 }
    279 
    280 NS_IMETHODIMP
    281 nsXPCComponents_Classes::GetContractID(nsACString& aContractID) {
    282  aContractID.SetIsVoid(true);
    283  return NS_ERROR_NOT_AVAILABLE;
    284 }
    285 
    286 NS_IMETHODIMP
    287 nsXPCComponents_Classes::GetClassDescription(nsACString& aClassDescription) {
    288  aClassDescription.AssignLiteral("XPCComponents_Classes");
    289  return NS_OK;
    290 }
    291 
    292 NS_IMETHODIMP
    293 nsXPCComponents_Classes::GetClassID(nsCID** aClassID) {
    294  *aClassID = nullptr;
    295  return NS_OK;
    296 }
    297 
    298 NS_IMETHODIMP
    299 nsXPCComponents_Classes::GetFlags(uint32_t* aFlags) {
    300  *aFlags = 0;
    301  return NS_OK;
    302 }
    303 
    304 NS_IMETHODIMP
    305 nsXPCComponents_Classes::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
    306  return NS_ERROR_NOT_AVAILABLE;
    307 }
    308 
    309 nsXPCComponents_Classes::nsXPCComponents_Classes() = default;
    310 
    311 nsXPCComponents_Classes::~nsXPCComponents_Classes() {
    312  // empty
    313 }
    314 
    315 NS_IMPL_ISUPPORTS(nsXPCComponents_Classes, nsIXPCComponents_Classes,
    316                  nsIXPCScriptable, nsIClassInfo)
    317 
    318 // The nsIXPCScriptable map declaration that will generate stubs for us...
    319 #define XPC_MAP_CLASSNAME nsXPCComponents_Classes
    320 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Classes"
    321 #define XPC_MAP_FLAGS                                               \
    322  (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
    323   XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
    324 #include "xpc_map_end.h" /* This will #undef the above */
    325 
    326 NS_IMETHODIMP
    327 nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
    328                                      JSContext* cx, JSObject* obj,
    329                                      JS::MutableHandleIdVector properties,
    330                                      bool enumerableOnly, bool* _retval) {
    331  nsCOMPtr<nsIComponentRegistrar> compMgr;
    332  if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) ||
    333      !compMgr) {
    334    return NS_ERROR_UNEXPECTED;
    335  }
    336 
    337  nsTArray<nsCString> contractIDs;
    338  if (NS_FAILED(compMgr->GetContractIDs(contractIDs))) {
    339    return NS_ERROR_UNEXPECTED;
    340  }
    341 
    342  for (const auto& name : contractIDs) {
    343    RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
    344    if (!idstr) {
    345      *_retval = false;
    346      return NS_OK;
    347    }
    348 
    349    RootedId id(cx);
    350    if (!JS_StringToId(cx, idstr, &id)) {
    351      *_retval = false;
    352      return NS_OK;
    353    }
    354 
    355    if (!properties.append(id)) {
    356      *_retval = false;
    357      return NS_OK;
    358    }
    359  }
    360 
    361  return NS_OK;
    362 }
    363 
    364 NS_IMETHODIMP
    365 nsXPCComponents_Classes::Resolve(nsIXPConnectWrappedNative* wrapper,
    366                                 JSContext* cx, JSObject* objArg, jsid idArg,
    367                                 bool* resolvedp, bool* _retval)
    368 
    369 {
    370  RootedId id(cx, idArg);
    371  RootedObject obj(cx, objArg);
    372 
    373  RootedValue cidv(cx);
    374  if (id.isString() && xpc::ContractID2JSValue(cx, id.toString(), &cidv)) {
    375    *resolvedp = true;
    376    *_retval = JS_DefinePropertyById(cx, obj, id, cidv,
    377                                     JSPROP_ENUMERATE | JSPROP_READONLY |
    378                                         JSPROP_PERMANENT | JSPROP_RESOLVING);
    379  }
    380  return NS_OK;
    381 }
    382 
    383 /***************************************************************************/
    384 /***************************************************************************/
    385 /***************************************************************************/
    386 
    387 // Currently the possible results do not change at runtime, so they are only
    388 // cached once (unlike ContractIDs, CLSIDs, and IIDs)
    389 
    390 class nsXPCComponents_Results final : public nsIXPCComponents_Results,
    391                                      public nsIXPCScriptable,
    392                                      public nsIClassInfo {
    393 public:
    394  // all the interface method declarations...
    395  NS_DECL_ISUPPORTS
    396  NS_DECL_NSIXPCCOMPONENTS_RESULTS
    397  NS_DECL_NSIXPCSCRIPTABLE
    398  NS_DECL_NSICLASSINFO
    399 
    400 public:
    401  nsXPCComponents_Results();
    402 
    403 private:
    404  virtual ~nsXPCComponents_Results();
    405 };
    406 
    407 /***************************************************************************/
    408 NS_IMETHODIMP
    409 nsXPCComponents_Results::GetInterfaces(nsTArray<nsIID>& aArray) {
    410  aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Results),
    411                           NS_GET_IID(nsIXPCScriptable)};
    412  return NS_OK;
    413 }
    414 
    415 NS_IMETHODIMP
    416 nsXPCComponents_Results::GetScriptableHelper(nsIXPCScriptable** retval) {
    417  *retval = nullptr;
    418  return NS_OK;
    419 }
    420 
    421 NS_IMETHODIMP
    422 nsXPCComponents_Results::GetContractID(nsACString& aContractID) {
    423  aContractID.SetIsVoid(true);
    424  return NS_ERROR_NOT_AVAILABLE;
    425 }
    426 
    427 NS_IMETHODIMP
    428 nsXPCComponents_Results::GetClassDescription(nsACString& aClassDescription) {
    429  aClassDescription.AssignLiteral("XPCComponents_Results");
    430  return NS_OK;
    431 }
    432 
    433 NS_IMETHODIMP
    434 nsXPCComponents_Results::GetClassID(nsCID** aClassID) {
    435  *aClassID = nullptr;
    436  return NS_OK;
    437 }
    438 
    439 NS_IMETHODIMP
    440 nsXPCComponents_Results::GetFlags(uint32_t* aFlags) {
    441  *aFlags = 0;
    442  return NS_OK;
    443 }
    444 
    445 NS_IMETHODIMP
    446 nsXPCComponents_Results::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
    447  return NS_ERROR_NOT_AVAILABLE;
    448 }
    449 
    450 nsXPCComponents_Results::nsXPCComponents_Results() = default;
    451 
    452 nsXPCComponents_Results::~nsXPCComponents_Results() {
    453  // empty
    454 }
    455 
    456 NS_IMPL_ISUPPORTS(nsXPCComponents_Results, nsIXPCComponents_Results,
    457                  nsIXPCScriptable, nsIClassInfo)
    458 
    459 // The nsIXPCScriptable map declaration that will generate stubs for us...
    460 #define XPC_MAP_CLASSNAME nsXPCComponents_Results
    461 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Results"
    462 #define XPC_MAP_FLAGS                                               \
    463  (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
    464   XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
    465 #include "xpc_map_end.h" /* This will #undef the above */
    466 
    467 NS_IMETHODIMP
    468 nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
    469                                      JSContext* cx, JSObject* obj,
    470                                      JS::MutableHandleIdVector properties,
    471                                      bool enumerableOnly, bool* _retval) {
    472  const char* name;
    473  const void* iter = nullptr;
    474  while (nsXPCException::IterateNSResults(nullptr, &name, nullptr, &iter)) {
    475    RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
    476    if (!idstr) {
    477      *_retval = false;
    478      return NS_OK;
    479    }
    480 
    481    RootedId id(cx);
    482    if (!JS_StringToId(cx, idstr, &id)) {
    483      *_retval = false;
    484      return NS_OK;
    485    }
    486 
    487    if (!properties.append(id)) {
    488      *_retval = false;
    489      return NS_OK;
    490    }
    491  }
    492 
    493  return NS_OK;
    494 }
    495 
    496 NS_IMETHODIMP
    497 nsXPCComponents_Results::Resolve(nsIXPConnectWrappedNative* wrapper,
    498                                 JSContext* cx, JSObject* objArg, jsid idArg,
    499                                 bool* resolvedp, bool* _retval) {
    500  RootedObject obj(cx, objArg);
    501  RootedId id(cx, idArg);
    502  if (!id.isString()) {
    503    return NS_OK;
    504  }
    505 
    506  JS::UniqueChars name = JS_EncodeStringToLatin1(cx, id.toString());
    507  if (name) {
    508    const char* rv_name;
    509    const void* iter = nullptr;
    510    nsresult rv;
    511    while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) {
    512      if (!strcmp(name.get(), rv_name)) {
    513        *resolvedp = true;
    514        if (!JS_DefinePropertyById(cx, obj, id, (uint32_t)rv,
    515                                   JSPROP_ENUMERATE | JSPROP_READONLY |
    516                                       JSPROP_PERMANENT | JSPROP_RESOLVING)) {
    517          return NS_ERROR_UNEXPECTED;
    518        }
    519      }
    520    }
    521  }
    522  return NS_OK;
    523 }
    524 
    525 /***************************************************************************/
    526 // JavaScript Constructor for nsIJSID objects (Components.ID)
    527 
    528 class nsXPCComponents_ID final : public nsIXPCComponents_ID,
    529                                 public nsIXPCScriptable,
    530                                 public nsIClassInfo {
    531 public:
    532  // all the interface method declarations...
    533  NS_DECL_ISUPPORTS
    534  NS_DECL_NSIXPCCOMPONENTS_ID
    535  NS_DECL_NSIXPCSCRIPTABLE
    536  NS_DECL_NSICLASSINFO
    537 
    538 public:
    539  nsXPCComponents_ID();
    540 
    541 private:
    542  virtual ~nsXPCComponents_ID();
    543  static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
    544                                  JSContext* cx, HandleObject obj,
    545                                  const CallArgs& args, bool* _retval);
    546 };
    547 
    548 /***************************************************************************/
    549 NS_IMETHODIMP
    550 nsXPCComponents_ID::GetInterfaces(nsTArray<nsIID>& aArray) {
    551  aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_ID),
    552                           NS_GET_IID(nsIXPCScriptable)};
    553  return NS_OK;
    554 }
    555 
    556 NS_IMETHODIMP
    557 nsXPCComponents_ID::GetScriptableHelper(nsIXPCScriptable** retval) {
    558  *retval = nullptr;
    559  return NS_OK;
    560 }
    561 
    562 NS_IMETHODIMP
    563 nsXPCComponents_ID::GetContractID(nsACString& aContractID) {
    564  aContractID.SetIsVoid(true);
    565  return NS_ERROR_NOT_AVAILABLE;
    566 }
    567 
    568 NS_IMETHODIMP
    569 nsXPCComponents_ID::GetClassDescription(nsACString& aClassDescription) {
    570  aClassDescription.AssignLiteral("XPCComponents_ID");
    571  return NS_OK;
    572 }
    573 
    574 NS_IMETHODIMP
    575 nsXPCComponents_ID::GetClassID(nsCID** aClassID) {
    576  *aClassID = nullptr;
    577  return NS_OK;
    578 }
    579 
    580 NS_IMETHODIMP
    581 nsXPCComponents_ID::GetFlags(uint32_t* aFlags) {
    582  *aFlags = 0;
    583  return NS_OK;
    584 }
    585 
    586 NS_IMETHODIMP
    587 nsXPCComponents_ID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
    588  return NS_ERROR_NOT_AVAILABLE;
    589 }
    590 
    591 nsXPCComponents_ID::nsXPCComponents_ID() = default;
    592 
    593 nsXPCComponents_ID::~nsXPCComponents_ID() {
    594  // empty
    595 }
    596 
    597 NS_IMPL_ISUPPORTS(nsXPCComponents_ID, nsIXPCComponents_ID, nsIXPCScriptable,
    598                  nsIClassInfo)
    599 
    600 // The nsIXPCScriptable map declaration that will generate stubs for us...
    601 #define XPC_MAP_CLASSNAME nsXPCComponents_ID
    602 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ID"
    603 #define XPC_MAP_FLAGS                                         \
    604  (XPC_SCRIPTABLE_WANT_CALL | XPC_SCRIPTABLE_WANT_CONSTRUCT | \
    605   XPC_SCRIPTABLE_WANT_HASINSTANCE |                          \
    606   XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
    607 #include "xpc_map_end.h" /* This will #undef the above */
    608 
    609 NS_IMETHODIMP
    610 nsXPCComponents_ID::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
    611                         JSObject* objArg, const CallArgs& args,
    612                         bool* _retval) {
    613  RootedObject obj(cx, objArg);
    614  return CallOrConstruct(wrapper, cx, obj, args, _retval);
    615 }
    616 
    617 NS_IMETHODIMP
    618 nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
    619                              JSObject* objArg, const CallArgs& args,
    620                              bool* _retval) {
    621  RootedObject obj(cx, objArg);
    622  return CallOrConstruct(wrapper, cx, obj, args, _retval);
    623 }
    624 
    625 // static
    626 nsresult nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
    627                                             JSContext* cx, HandleObject obj,
    628                                             const CallArgs& args,
    629                                             bool* _retval) {
    630  // make sure we have at least one arg
    631 
    632  if (args.length() < 1) {
    633    return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
    634  }
    635 
    636  // Prevent non-chrome code from creating ID objects.
    637  if (!nsContentUtils::IsCallerChrome()) {
    638    return ThrowAndFail(NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED, cx, _retval);
    639  }
    640 
    641  // convert the first argument into a string and see if it looks like an id
    642 
    643  JSString* jsstr = ToString(cx, args[0]);
    644  if (!jsstr) {
    645    return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
    646  }
    647 
    648  JS::UniqueChars bytes = JS_EncodeStringToLatin1(cx, jsstr);
    649  if (!bytes) {
    650    return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
    651  }
    652 
    653  nsID id;
    654  if (!id.Parse(bytes.get())) {
    655    return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
    656  }
    657 
    658  // make the new object and return it.
    659 
    660  if (!xpc::ID2JSValue(cx, id, args.rval())) {
    661    return NS_ERROR_UNEXPECTED;
    662  }
    663  return NS_OK;
    664 }
    665 
    666 NS_IMETHODIMP
    667 nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative* wrapper,
    668                                JSContext* cx, JSObject* obj, HandleValue val,
    669                                bool* bp, bool* _retval) {
    670  if (bp) {
    671    *bp = xpc::JSValue2ID(cx, val).isSome();
    672  }
    673  return NS_OK;
    674 }
    675 
    676 /***************************************************************************/
    677 // JavaScript Constructor for Exception objects (Components.Exception)
    678 
    679 class nsXPCComponents_Exception final : public nsIXPCComponents_Exception,
    680                                        public nsIXPCScriptable,
    681                                        public nsIClassInfo {
    682 public:
    683  // all the interface method declarations...
    684  NS_DECL_ISUPPORTS
    685  NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
    686  NS_DECL_NSIXPCSCRIPTABLE
    687  NS_DECL_NSICLASSINFO
    688 
    689 public:
    690  nsXPCComponents_Exception();
    691 
    692 private:
    693  virtual ~nsXPCComponents_Exception();
    694  static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
    695                                  JSContext* cx, HandleObject obj,
    696                                  const CallArgs& args, bool* _retval);
    697 };
    698 
    699 /***************************************************************************/
    700 NS_IMETHODIMP
    701 nsXPCComponents_Exception::GetInterfaces(nsTArray<nsIID>& aArray) {
    702  aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Exception),
    703                           NS_GET_IID(nsIXPCScriptable)};
    704  return NS_OK;
    705 }
    706 
    707 NS_IMETHODIMP
    708 nsXPCComponents_Exception::GetScriptableHelper(nsIXPCScriptable** retval) {
    709  *retval = nullptr;
    710  return NS_OK;
    711 }
    712 
    713 NS_IMETHODIMP
    714 nsXPCComponents_Exception::GetContractID(nsACString& aContractID) {
    715  aContractID.SetIsVoid(true);
    716  return NS_ERROR_NOT_AVAILABLE;
    717 }
    718 
    719 NS_IMETHODIMP
    720 nsXPCComponents_Exception::GetClassDescription(nsACString& aClassDescription) {
    721  aClassDescription.AssignLiteral("XPCComponents_Exception");
    722  return NS_OK;
    723 }
    724 
    725 NS_IMETHODIMP
    726 nsXPCComponents_Exception::GetClassID(nsCID** aClassID) {
    727  *aClassID = nullptr;
    728  return NS_OK;
    729 }
    730 
    731 NS_IMETHODIMP
    732 nsXPCComponents_Exception::GetFlags(uint32_t* aFlags) {
    733  *aFlags = 0;
    734  return NS_OK;
    735 }
    736 
    737 NS_IMETHODIMP
    738 nsXPCComponents_Exception::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
    739  return NS_ERROR_NOT_AVAILABLE;
    740 }
    741 
    742 nsXPCComponents_Exception::nsXPCComponents_Exception() = default;
    743 
    744 nsXPCComponents_Exception::~nsXPCComponents_Exception() {
    745  // empty
    746 }
    747 
    748 NS_IMPL_ISUPPORTS(nsXPCComponents_Exception, nsIXPCComponents_Exception,
    749                  nsIXPCScriptable, nsIClassInfo)
    750 
    751 // The nsIXPCScriptable map declaration that will generate stubs for us...
    752 #define XPC_MAP_CLASSNAME nsXPCComponents_Exception
    753 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Exception"
    754 #define XPC_MAP_FLAGS                                         \
    755  (XPC_SCRIPTABLE_WANT_CALL | XPC_SCRIPTABLE_WANT_CONSTRUCT | \
    756   XPC_SCRIPTABLE_WANT_HASINSTANCE |                          \
    757   XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
    758 #include "xpc_map_end.h" /* This will #undef the above */
    759 
    760 NS_IMETHODIMP
    761 nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative* wrapper,
    762                                JSContext* cx, JSObject* objArg,
    763                                const CallArgs& args, bool* _retval) {
    764  RootedObject obj(cx, objArg);
    765  return CallOrConstruct(wrapper, cx, obj, args, _retval);
    766 }
    767 
    768 NS_IMETHODIMP
    769 nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative* wrapper,
    770                                     JSContext* cx, JSObject* objArg,
    771                                     const CallArgs& args, bool* _retval) {
    772  RootedObject obj(cx, objArg);
    773  return CallOrConstruct(wrapper, cx, obj, args, _retval);
    774 }
    775 
    776 struct MOZ_STACK_CLASS ExceptionArgParser {
    777  ExceptionArgParser(JSContext* context, nsIXPConnect* xpconnect)
    778      : eMsg("exception"),
    779        eResult(NS_ERROR_FAILURE),
    780        cx(context),
    781        xpc(xpconnect) {}
    782 
    783  // Public exception parameter values. During construction, these are
    784  // initialized to the appropriate defaults.
    785  const char* eMsg;
    786  nsresult eResult;
    787  nsCOMPtr<nsIStackFrame> eStack;
    788  nsCOMPtr<nsISupports> eData;
    789 
    790  // Parse the constructor arguments into the above |eFoo| parameter values.
    791  bool parse(const CallArgs& args) {
    792    /*
    793     * The Components.Exception takes a series of arguments, all of them
    794     * optional:
    795     *
    796     * Argument 0: Exception message (defaults to 'exception').
    797     * Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options
    798     *             object (see below).
    799     * Argument 2: Stack (defaults to the current stack, which we trigger
    800     *                    by leaving this nullptr in the parser).
    801     * Argument 3: Optional user data (defaults to nullptr).
    802     *
    803     * To dig our way out of this clunky API, we now support passing an
    804     * options object as the second parameter (as opposed to a result code).
    805     * If this is the case, all subsequent arguments are ignored, and the
    806     * following properties are parsed out of the object (using the
    807     * associated default if the property does not exist):
    808     *
    809     *   result:    Result code (see argument 1).
    810     *   stack:     Call stack (see argument 2).
    811     *   data:      User data (see argument 3).
    812     */
    813    if (args.length() > 0 && !parseMessage(args[0])) {
    814      return false;
    815    }
    816    if (args.length() > 1) {
    817      if (args[1].isObject()) {
    818        RootedObject obj(cx, &args[1].toObject());
    819        return parseOptionsObject(obj);
    820      }
    821      if (!parseResult(args[1])) {
    822        return false;
    823      }
    824    }
    825    if (args.length() > 2) {
    826      if (!parseStack(args[2])) {
    827        return false;
    828      }
    829    }
    830    if (args.length() > 3) {
    831      if (!parseData(args[3])) {
    832        return false;
    833      }
    834    }
    835    return true;
    836  }
    837 
    838 protected:
    839  /*
    840   * Parsing helpers.
    841   */
    842 
    843  bool parseMessage(HandleValue v) {
    844    JSString* str = ToString(cx, v);
    845    if (!str) {
    846      return false;
    847    }
    848    messageBytes = JS_EncodeStringToLatin1(cx, str);
    849    eMsg = messageBytes.get();
    850    return !!eMsg;
    851  }
    852 
    853  bool parseResult(HandleValue v) {
    854    return JS::ToUint32(cx, v, (uint32_t*)&eResult);
    855  }
    856 
    857  bool parseStack(HandleValue v) {
    858    if (!v.isObject()) {
    859      // eStack has already been initialized to null, which is what we want
    860      // for any non-object values (including null).
    861      return true;
    862    }
    863 
    864    RootedObject stackObj(cx, &v.toObject());
    865    return NS_SUCCEEDED(xpc->WrapJS(cx, stackObj, NS_GET_IID(nsIStackFrame),
    866                                    getter_AddRefs(eStack)));
    867  }
    868 
    869  bool parseData(HandleValue v) {
    870    if (!v.isObject()) {
    871      // eData has already been initialized to null, which is what we want
    872      // for any non-object values (including null).
    873      return true;
    874    }
    875 
    876    RootedObject obj(cx, &v.toObject());
    877    return NS_SUCCEEDED(
    878        xpc->WrapJS(cx, obj, NS_GET_IID(nsISupports), getter_AddRefs(eData)));
    879  }
    880 
    881  bool parseOptionsObject(HandleObject obj) {
    882    RootedValue v(cx);
    883 
    884    if (!getOption(obj, "result", &v) || (!v.isUndefined() && !parseResult(v)))
    885      return false;
    886 
    887    if (!getOption(obj, "stack", &v) || (!v.isUndefined() && !parseStack(v)))
    888      return false;
    889 
    890    if (!getOption(obj, "data", &v) || (!v.isUndefined() && !parseData(v)))
    891      return false;
    892 
    893    return true;
    894  }
    895 
    896  bool getOption(HandleObject obj, const char* name, MutableHandleValue rv) {
    897    // Look for the property.
    898    bool found;
    899    if (!JS_HasProperty(cx, obj, name, &found)) {
    900      return false;
    901    }
    902 
    903    // If it wasn't found, indicate with undefined.
    904    if (!found) {
    905      rv.setUndefined();
    906      return true;
    907    }
    908 
    909    // Get the property.
    910    return JS_GetProperty(cx, obj, name, rv);
    911  }
    912 
    913  /*
    914   * Internal data members.
    915   */
    916 
    917  // If there's a non-default exception string, hold onto the allocated bytes.
    918  JS::UniqueChars messageBytes;
    919 
    920  // Various bits and pieces that are helpful to have around.
    921  JSContext* cx;
    922  nsIXPConnect* xpc;
    923 };
    924 
    925 // static
    926 nsresult nsXPCComponents_Exception::CallOrConstruct(
    927    nsIXPConnectWrappedNative* wrapper, JSContext* cx, HandleObject obj,
    928    const CallArgs& args, bool* _retval) {
    929  nsIXPConnect* xpc = nsIXPConnect::XPConnect();
    930 
    931  MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsCallerChrome());
    932 
    933  // Parse the arguments to the Exception constructor.
    934  ExceptionArgParser parser(cx, xpc);
    935  if (!parser.parse(args)) {
    936    return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
    937  }
    938 
    939  RefPtr<Exception> e = new Exception(nsCString(parser.eMsg), parser.eResult,
    940                                      ""_ns, parser.eStack, parser.eData);
    941 
    942  RootedObject newObj(cx);
    943  if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIException),
    944                                newObj.address())) ||
    945      !newObj) {
    946    return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
    947  }
    948 
    949  args.rval().setObject(*newObj);
    950  return NS_OK;
    951 }
    952 
    953 NS_IMETHODIMP
    954 nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative* wrapper,
    955                                       JSContext* cx, JSObject* obj,
    956                                       HandleValue val, bool* bp,
    957                                       bool* _retval) {
    958  using namespace mozilla::dom;
    959 
    960  if (bp) {
    961    *bp = (val.isObject() && IS_INSTANCE_OF(Exception, &val.toObject())) ||
    962          JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIException));
    963  }
    964  return NS_OK;
    965 }
    966 
    967 /*******************************************************/
    968 // JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
    969 
    970 class nsXPCComponents_Constructor final : public nsIXPCComponents_Constructor,
    971                                          public nsIXPCScriptable,
    972                                          public nsIClassInfo {
    973 public:
    974  // all the interface method declarations...
    975  NS_DECL_ISUPPORTS
    976  NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
    977  NS_DECL_NSIXPCSCRIPTABLE
    978  NS_DECL_NSICLASSINFO
    979 
    980 public:
    981  nsXPCComponents_Constructor();
    982 
    983 private:
    984  virtual ~nsXPCComponents_Constructor();
    985  static bool InnerConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
    986  static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
    987                                  JSContext* cx, HandleObject obj,
    988                                  const CallArgs& args, bool* _retval);
    989 };
    990 
    991 /***************************************************************************/
    992 NS_IMETHODIMP
    993 nsXPCComponents_Constructor::GetInterfaces(nsTArray<nsIID>& aArray) {
    994  aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Constructor),
    995                           NS_GET_IID(nsIXPCScriptable)};
    996  return NS_OK;
    997 }
    998 
    999 NS_IMETHODIMP
   1000 nsXPCComponents_Constructor::GetScriptableHelper(nsIXPCScriptable** retval) {
   1001  *retval = nullptr;
   1002  return NS_OK;
   1003 }
   1004 
   1005 NS_IMETHODIMP
   1006 nsXPCComponents_Constructor::GetContractID(nsACString& aContractID) {
   1007  aContractID.SetIsVoid(true);
   1008  return NS_ERROR_NOT_AVAILABLE;
   1009 }
   1010 
   1011 NS_IMETHODIMP
   1012 nsXPCComponents_Constructor::GetClassDescription(
   1013    nsACString& aClassDescription) {
   1014  aClassDescription.AssignLiteral("XPCComponents_Constructor");
   1015  return NS_OK;
   1016 }
   1017 
   1018 NS_IMETHODIMP
   1019 nsXPCComponents_Constructor::GetClassID(nsCID** aClassID) {
   1020  *aClassID = nullptr;
   1021  return NS_OK;
   1022 }
   1023 
   1024 NS_IMETHODIMP
   1025 nsXPCComponents_Constructor::GetFlags(uint32_t* aFlags) {
   1026  *aFlags = 0;
   1027  return NS_OK;
   1028 }
   1029 
   1030 NS_IMETHODIMP
   1031 nsXPCComponents_Constructor::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
   1032  return NS_ERROR_NOT_AVAILABLE;
   1033 }
   1034 
   1035 nsXPCComponents_Constructor::nsXPCComponents_Constructor() = default;
   1036 
   1037 nsXPCComponents_Constructor::~nsXPCComponents_Constructor() {
   1038  // empty
   1039 }
   1040 
   1041 NS_IMPL_ISUPPORTS(nsXPCComponents_Constructor, nsIXPCComponents_Constructor,
   1042                  nsIXPCScriptable, nsIClassInfo)
   1043 
   1044 // The nsIXPCScriptable map declaration that will generate stubs for us...
   1045 #define XPC_MAP_CLASSNAME nsXPCComponents_Constructor
   1046 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Constructor"
   1047 #define XPC_MAP_FLAGS                                         \
   1048  (XPC_SCRIPTABLE_WANT_CALL | XPC_SCRIPTABLE_WANT_CONSTRUCT | \
   1049   XPC_SCRIPTABLE_WANT_HASINSTANCE |                          \
   1050   XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
   1051 #include "xpc_map_end.h" /* This will #undef the above */
   1052 
   1053 // static
   1054 bool nsXPCComponents_Constructor::InnerConstructor(JSContext* cx, unsigned argc,
   1055                                                   JS::Value* vp) {
   1056  CallArgs args = CallArgsFromVp(argc, vp);
   1057  RootedObject callee(cx, &args.callee());
   1058 
   1059  // Fetch the property name ids, so we can look them up.
   1060  XPCJSRuntime* runtime = XPCJSRuntime::Get();
   1061  HandleId classIDProp = runtime->GetStringID(XPCJSContext::IDX_CLASS_ID);
   1062  HandleId interfaceIDProp =
   1063      runtime->GetStringID(XPCJSContext::IDX_INTERFACE_ID);
   1064  HandleId initializerProp =
   1065      runtime->GetStringID(XPCJSContext::IDX_INITIALIZER);
   1066 
   1067  // Get properties ('classID', 'interfaceID', and 'initializer') off the
   1068  // constructor object.
   1069  RootedValue classIDv(cx);
   1070  RootedValue interfaceID(cx);
   1071  RootedValue initializer(cx);
   1072  if (!JS_GetPropertyById(cx, callee, classIDProp, &classIDv) ||
   1073      !JS_GetPropertyById(cx, callee, interfaceIDProp, &interfaceID) ||
   1074      !JS_GetPropertyById(cx, callee, initializerProp, &initializer)) {
   1075    return false;
   1076  }
   1077  if (!classIDv.isObject() || !interfaceID.isObject()) {
   1078    XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
   1079    return false;
   1080  }
   1081 
   1082  // Call 'createInstance' on the 'classID' object to create the object.
   1083  RootedValue instancev(cx);
   1084  RootedObject classID(cx, &classIDv.toObject());
   1085  if (!JS_CallFunctionName(cx, classID, "createInstance",
   1086                           HandleValueArray(interfaceID), &instancev)) {
   1087    return false;
   1088  }
   1089  if (!instancev.isObject()) {
   1090    XPCThrower::Throw(NS_ERROR_FAILURE, cx);
   1091    return false;
   1092  }
   1093 
   1094  // Call the method 'initializer' on the instance, passing in our parameters.
   1095  if (!initializer.isUndefined()) {
   1096    RootedValue dummy(cx);
   1097    RootedValue initfunc(cx);
   1098    RootedId initid(cx);
   1099    RootedObject instance(cx, &instancev.toObject());
   1100    if (!JS_ValueToId(cx, initializer, &initid) ||
   1101        !JS_GetPropertyById(cx, instance, initid, &initfunc) ||
   1102        !JS_CallFunctionValue(cx, instance, initfunc, args, &dummy)) {
   1103      return false;
   1104    }
   1105  }
   1106 
   1107  args.rval().set(instancev);
   1108  return true;
   1109 }
   1110 
   1111 NS_IMETHODIMP
   1112 nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative* wrapper,
   1113                                  JSContext* cx, JSObject* objArg,
   1114                                  const CallArgs& args, bool* _retval) {
   1115  RootedObject obj(cx, objArg);
   1116  return CallOrConstruct(wrapper, cx, obj, args, _retval);
   1117 }
   1118 
   1119 NS_IMETHODIMP
   1120 nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative* wrapper,
   1121                                       JSContext* cx, JSObject* objArg,
   1122                                       const CallArgs& args, bool* _retval) {
   1123  RootedObject obj(cx, objArg);
   1124  return CallOrConstruct(wrapper, cx, obj, args, _retval);
   1125 }
   1126 
   1127 // static
   1128 nsresult nsXPCComponents_Constructor::CallOrConstruct(
   1129    nsIXPConnectWrappedNative* wrapper, JSContext* cx, HandleObject obj,
   1130    const CallArgs& args, bool* _retval) {
   1131  // make sure we have at least one arg
   1132 
   1133  if (args.length() < 1) {
   1134    return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
   1135  }
   1136 
   1137  // Fetch the property name ids, so we can look them up.
   1138  XPCJSRuntime* runtime = XPCJSRuntime::Get();
   1139  HandleId classIDProp = runtime->GetStringID(XPCJSContext::IDX_CLASS_ID);
   1140  HandleId interfaceIDProp =
   1141      runtime->GetStringID(XPCJSContext::IDX_INTERFACE_ID);
   1142  HandleId initializerProp =
   1143      runtime->GetStringID(XPCJSContext::IDX_INITIALIZER);
   1144 
   1145  // get the various other object pointers we need
   1146 
   1147  nsIXPConnect* xpc = nsIXPConnect::XPConnect();
   1148  XPCWrappedNativeScope* scope = ObjectScope(obj);
   1149  nsCOMPtr<nsIXPCComponents> comp;
   1150 
   1151  if (!xpc || !scope || !(comp = scope->GetComponents())) {
   1152    return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
   1153  }
   1154 
   1155  // Prevent non-chrome code from creating constructor objects.
   1156  if (!nsContentUtils::IsCallerChrome()) {
   1157    return ThrowAndFail(NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED, cx, _retval);
   1158  }
   1159 
   1160  JSFunction* ctorfn = JS_NewFunction(cx, InnerConstructor, 0,
   1161                                      JSFUN_CONSTRUCTOR, "XPCOM_Constructor");
   1162  if (!ctorfn) {
   1163    return ThrowAndFail(NS_ERROR_OUT_OF_MEMORY, cx, _retval);
   1164  }
   1165 
   1166  JS::RootedObject ctor(cx, JS_GetFunctionObject(ctorfn));
   1167 
   1168  if (args.length() >= 3) {
   1169    // args[2] is an initializer function or property name
   1170    RootedString str(cx, ToString(cx, args[2]));
   1171    if (!JS_DefinePropertyById(
   1172            cx, ctor, initializerProp, str,
   1173            JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
   1174      return ThrowAndFail(NS_ERROR_FAILURE, cx, _retval);
   1175    }
   1176  }
   1177 
   1178  RootedString ifaceName(cx);
   1179  if (args.length() >= 2) {
   1180    ifaceName = ToString(cx, args[1]);
   1181  } else {
   1182    ifaceName = JS_NewStringCopyZ(cx, "nsISupports");
   1183  }
   1184 
   1185  if (!ifaceName) {
   1186    return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
   1187  }
   1188 
   1189  // a new scope to avoid warnings about shadowed names
   1190  {
   1191    nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
   1192    RootedObject ifacesObj(cx);
   1193 
   1194    // we do the lookup by asking the Components.interfaces object
   1195    // for the property with this name - i.e. we let its caching of these
   1196    // nsIJSIID objects work for us.
   1197 
   1198    if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
   1199        NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
   1200                                  NS_GET_IID(nsIXPCComponents_Interfaces),
   1201                                  ifacesObj.address())) ||
   1202        !ifacesObj) {
   1203      return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
   1204    }
   1205 
   1206    RootedId id(cx);
   1207    if (!JS_StringToId(cx, ifaceName, &id)) {
   1208      return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
   1209    }
   1210 
   1211    RootedValue val(cx);
   1212    if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive()) {
   1213      return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
   1214    }
   1215 
   1216    if (!JS_DefinePropertyById(
   1217            cx, ctor, interfaceIDProp, val,
   1218            JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
   1219      return ThrowAndFail(NS_ERROR_FAILURE, cx, _retval);
   1220    }
   1221  }
   1222 
   1223  // a new scope to avoid warnings about shadowed names
   1224  {
   1225    // argv[0] is a contractid name string
   1226 
   1227    // we do the lookup by asking the Components.classes object
   1228    // for the property with this name - i.e. we let its caching of these
   1229    // nsIJSCID objects work for us.
   1230 
   1231    nsCOMPtr<nsIXPCComponents_Classes> classes;
   1232    RootedObject classesObj(cx);
   1233 
   1234    if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
   1235        NS_FAILED(xpc->WrapNative(cx, obj, classes,
   1236                                  NS_GET_IID(nsIXPCComponents_Classes),
   1237                                  classesObj.address())) ||
   1238        !classesObj) {
   1239      return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
   1240    }
   1241 
   1242    RootedString str(cx, ToString(cx, args[0]));
   1243    RootedId id(cx);
   1244    if (!str || !JS_StringToId(cx, str, &id)) {
   1245      return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
   1246    }
   1247 
   1248    RootedValue val(cx);
   1249    if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive()) {
   1250      return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
   1251    }
   1252 
   1253    if (!JS_DefinePropertyById(
   1254            cx, ctor, classIDProp, val,
   1255            JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
   1256      return ThrowAndFail(NS_ERROR_FAILURE, cx, _retval);
   1257    }
   1258  }
   1259 
   1260  args.rval().setObject(*ctor);
   1261  return NS_OK;
   1262 }
   1263 
   1264 NS_IMETHODIMP
   1265 nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative* wrapper,
   1266                                         JSContext* cx, JSObject* obj,
   1267                                         HandleValue val, bool* isa,
   1268                                         bool* _retval) {
   1269  *isa =
   1270      val.isObject() && JS_IsNativeFunction(&val.toObject(), InnerConstructor);
   1271  return NS_OK;
   1272 }
   1273 
   1274 class nsXPCComponents_Utils final : public nsIXPCComponents_Utils,
   1275                                    public nsIXPCScriptable {
   1276 public:
   1277  // all the interface method declarations...
   1278  NS_DECL_ISUPPORTS
   1279  NS_DECL_NSIXPCSCRIPTABLE
   1280  NS_DECL_NSIXPCCOMPONENTS_UTILS
   1281 
   1282 public:
   1283  nsXPCComponents_Utils() = default;
   1284 
   1285 private:
   1286  virtual ~nsXPCComponents_Utils() = default;
   1287  nsCOMPtr<nsIXPCComponents_utils_Sandbox> mSandbox;
   1288 };
   1289 
   1290 NS_IMPL_ISUPPORTS(nsXPCComponents_Utils, nsIXPCComponents_Utils,
   1291                  nsIXPCScriptable)
   1292 
   1293 // The nsIXPCScriptable map declaration that will generate stubs for us...
   1294 #define XPC_MAP_CLASSNAME nsXPCComponents_Utils
   1295 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Utils"
   1296 #define XPC_MAP_FLAGS XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE
   1297 #include "xpc_map_end.h" /* This will #undef the above */
   1298 
   1299 NS_IMETHODIMP
   1300 nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox** aSandbox) {
   1301  NS_ENSURE_ARG_POINTER(aSandbox);
   1302  if (!mSandbox) {
   1303    mSandbox = NewSandboxConstructor();
   1304  }
   1305 
   1306  nsCOMPtr<nsIXPCComponents_utils_Sandbox> rval = mSandbox;
   1307  rval.forget(aSandbox);
   1308  return NS_OK;
   1309 }
   1310 
   1311 NS_IMETHODIMP
   1312 nsXPCComponents_Utils::PrintStderr(const nsACString& message) {
   1313  printf_stderr("%s", PromiseFlatUTF8String(message).get());
   1314  return NS_OK;
   1315 }
   1316 
   1317 NS_IMETHODIMP
   1318 nsXPCComponents_Utils::ReportError(HandleValue error, HandleValue stack,
   1319                                   JSContext* cx) {
   1320  // This function shall never fail! Silently eat any failure conditions.
   1321 
   1322  nsCOMPtr<nsIConsoleService> console(
   1323      do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   1324  if (!console) {
   1325    return NS_OK;
   1326  }
   1327 
   1328  nsGlobalWindowInner* win = CurrentWindowOrNull(cx);
   1329  const uint64_t innerWindowID = win ? win->WindowID() : 0;
   1330 
   1331  Rooted<Maybe<Value>> exception(cx, Some(error));
   1332  if (!innerWindowID) {
   1333    // Leak mitigation: nsConsoleService::ClearMessagesForWindowID needs
   1334    // a WindowID for cleanup and exception values could hold arbitrary
   1335    // objects alive.
   1336    exception = Nothing();
   1337  }
   1338 
   1339  nsCOMPtr<nsIScriptError> scripterr;
   1340  RootedObject errorObj(cx, error.isObject() ? &error.toObject() : nullptr);
   1341  if (errorObj) {
   1342    JS::RootedObject stackVal(cx);
   1343    JS::RootedObject stackGlobal(cx);
   1344    FindExceptionStackForConsoleReport(win, error, nullptr, &stackVal,
   1345                                       &stackGlobal);
   1346    if (stackVal) {
   1347      scripterr = CreateScriptError(win, exception, stackVal, stackGlobal);
   1348    }
   1349  }
   1350 
   1351  nsCString fileName;
   1352  uint32_t lineNo = 0;
   1353 
   1354  if (!scripterr) {
   1355    RootedObject stackObj(cx);
   1356    RootedObject stackGlobal(cx);
   1357    if (stack.isObject()) {
   1358      if (!JS::IsMaybeWrappedSavedFrame(&stack.toObject())) {
   1359        return NS_ERROR_INVALID_ARG;
   1360      }
   1361 
   1362      // |stack| might be a wrapper, but it must be same-compartment with
   1363      // the current global.
   1364      stackObj = &stack.toObject();
   1365      stackGlobal = JS::CurrentGlobalOrNull(cx);
   1366      js::AssertSameCompartment(stackObj, stackGlobal);
   1367 
   1368      JSPrincipals* principals =
   1369          JS::GetRealmPrincipals(js::GetContextRealm(cx));
   1370 
   1371      if (GetSavedFrameLine(cx, principals, stackObj, &lineNo) !=
   1372          SavedFrameResult::Ok) {
   1373        JS_ClearPendingException(cx);
   1374      }
   1375 
   1376      RootedString source(cx);
   1377      nsAutoJSCString str;
   1378      if (GetSavedFrameSource(cx, principals, stackObj, &source) ==
   1379              SavedFrameResult::Ok &&
   1380          str.init(cx, source)) {
   1381        fileName = str;
   1382      } else {
   1383        JS_ClearPendingException(cx);
   1384      }
   1385    } else {
   1386      nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
   1387      if (frame) {
   1388        frame->GetFilename(cx, fileName);
   1389        lineNo = frame->GetLineNumber(cx);
   1390        JS::Rooted<JS::Value> stack(cx);
   1391        nsresult rv = frame->GetNativeSavedFrame(&stack);
   1392        if (NS_SUCCEEDED(rv) && stack.isObject()) {
   1393          stackObj = &stack.toObject();
   1394          MOZ_ASSERT(JS::IsUnwrappedSavedFrame(stackObj));
   1395          stackGlobal = JS::GetNonCCWObjectGlobal(stackObj);
   1396        }
   1397      }
   1398    }
   1399 
   1400    if (stackObj) {
   1401      scripterr = CreateScriptError(win, exception, stackObj, stackGlobal);
   1402    }
   1403  }
   1404 
   1405  if (!scripterr) {
   1406    scripterr = CreateScriptError(win, exception, nullptr, nullptr);
   1407  }
   1408 
   1409  JSErrorReport* err = errorObj ? JS_ErrorFromException(cx, errorObj) : nullptr;
   1410  if (err) {
   1411    // It's a proper JS Error
   1412    uint32_t flags = err->isWarning() ? nsIScriptError::warningFlag
   1413                                      : nsIScriptError::errorFlag;
   1414    nsresult rv = scripterr->InitWithWindowID(
   1415        err->message() ? NS_ConvertUTF8toUTF16(err->message().c_str())
   1416                       : EmptyString(),
   1417        nsDependentCString(err->filename ? err->filename.c_str() : ""),
   1418        err->lineno, err->column.oneOriginValue(), flags,
   1419        "XPConnect JavaScript", innerWindowID, innerWindowID == 0);
   1420    NS_ENSURE_SUCCESS(rv, NS_OK);
   1421 
   1422    console->LogMessage(scripterr);
   1423    return NS_OK;
   1424  }
   1425 
   1426  // It's not a JS Error object, so we synthesize as best we're able.
   1427  RootedString msgstr(cx, ToString(cx, error));
   1428  if (!msgstr) {
   1429    return NS_OK;
   1430  }
   1431 
   1432  nsAutoJSString msg;
   1433  if (!msg.init(cx, msgstr)) {
   1434    return NS_OK;
   1435  }
   1436 
   1437  nsresult rv = scripterr->InitWithWindowID(msg, fileName, lineNo, 0, 0,
   1438                                            "XPConnect JavaScript",
   1439                                            innerWindowID, innerWindowID == 0);
   1440  NS_ENSURE_SUCCESS(rv, NS_OK);
   1441 
   1442  console->LogMessage(scripterr);
   1443  return NS_OK;
   1444 }
   1445 
   1446 NS_IMETHODIMP
   1447 nsXPCComponents_Utils::EvalInSandbox(
   1448    const nsAString& source, HandleValue sandboxVal, HandleValue version,
   1449    const nsACString& filenameArg, int32_t lineNumber,
   1450    bool enforceFilenameRestrictions, JSContext* cx, uint8_t optionalArgc,
   1451    MutableHandleValue retval) {
   1452  RootedObject sandbox(cx);
   1453  if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox) {
   1454    return NS_ERROR_INVALID_ARG;
   1455  }
   1456 
   1457  // Optional third argument: JS version, as a string, is unused.
   1458 
   1459  // Optional fourth and fifth arguments: filename and line number.
   1460  int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1;
   1461  nsCString filename;
   1462  if (!filenameArg.IsVoid()) {
   1463    filename.Assign(filenameArg);
   1464  } else {
   1465    // Get the current source info.
   1466    if (nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack()) {
   1467      frame->GetFilename(cx, filename);
   1468      lineNo = frame->GetLineNumber(cx);
   1469    }
   1470  }
   1471  enforceFilenameRestrictions =
   1472      (optionalArgc >= 4) ? enforceFilenameRestrictions : true;
   1473 
   1474  return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo,
   1475                            enforceFilenameRestrictions, retval);
   1476 }
   1477 
   1478 NS_IMETHODIMP
   1479 nsXPCComponents_Utils::GetUAWidgetScope(nsIPrincipal* principal, JSContext* cx,
   1480                                        MutableHandleValue rval) {
   1481  rval.set(UndefinedValue());
   1482 
   1483  JSObject* scope = xpc::GetUAWidgetScope(cx, principal);
   1484 
   1485  rval.set(JS::ObjectValue(*scope));
   1486 
   1487  return NS_OK;
   1488 }
   1489 
   1490 NS_IMETHODIMP
   1491 nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal, JSContext* cx,
   1492                                          MutableHandleValue rval) {
   1493  if (!sandboxVal.isObject()) {
   1494    return NS_ERROR_INVALID_ARG;
   1495  }
   1496 
   1497  RootedObject sandbox(cx, &sandboxVal.toObject());
   1498  // We only care about sandboxes here, so CheckedUnwrapStatic is fine.
   1499  sandbox = js::CheckedUnwrapStatic(sandbox);
   1500  if (!sandbox || !xpc::IsSandbox(sandbox)) {
   1501    return NS_ERROR_INVALID_ARG;
   1502  }
   1503 
   1504  return xpc::GetSandboxMetadata(cx, sandbox, rval);
   1505 }
   1506 
   1507 NS_IMETHODIMP
   1508 nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal,
   1509                                          HandleValue metadataVal,
   1510                                          JSContext* cx) {
   1511  if (!sandboxVal.isObject()) {
   1512    return NS_ERROR_INVALID_ARG;
   1513  }
   1514 
   1515  RootedObject sandbox(cx, &sandboxVal.toObject());
   1516  // We only care about sandboxes here, so CheckedUnwrapStatic is fine.
   1517  sandbox = js::CheckedUnwrapStatic(sandbox);
   1518  if (!sandbox || !xpc::IsSandbox(sandbox)) {
   1519    return NS_ERROR_INVALID_ARG;
   1520  }
   1521 
   1522  nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadataVal);
   1523  NS_ENSURE_SUCCESS(rv, rv);
   1524 
   1525  return NS_OK;
   1526 }
   1527 
   1528 NS_IMETHODIMP
   1529 nsXPCComponents_Utils::SetSandboxLocaleOverride(HandleValue sandboxVal,
   1530                                                const char* locale,
   1531                                                JSContext* cx) {
   1532  if (!sandboxVal.isObject()) {
   1533    return NS_ERROR_INVALID_ARG;
   1534  }
   1535 
   1536  RootedObject sandbox(cx, &sandboxVal.toObject());
   1537  // We only care about sandboxes here, so CheckedUnwrapStatic is fine.
   1538  sandbox = js::CheckedUnwrapStatic(sandbox);
   1539  if (!sandbox || !xpc::IsSandbox(sandbox)) {
   1540    return NS_ERROR_INVALID_ARG;
   1541  }
   1542 
   1543  nsresult rv = xpc::SetSandboxLocaleOverride(cx, sandbox, locale);
   1544  NS_ENSURE_SUCCESS(rv, rv);
   1545 
   1546  return NS_OK;
   1547 }
   1548 
   1549 NS_IMETHODIMP
   1550 nsXPCComponents_Utils::SetSandboxTimezoneOverride(HandleValue sandboxVal,
   1551                                                  const char* timezone,
   1552                                                  JSContext* cx) {
   1553  if (!sandboxVal.isObject()) {
   1554    return NS_ERROR_INVALID_ARG;
   1555  }
   1556 
   1557  RootedObject sandbox(cx, &sandboxVal.toObject());
   1558  // We only care about sandboxes here, so CheckedUnwrapStatic is fine.
   1559  sandbox = js::CheckedUnwrapStatic(sandbox);
   1560  if (!sandbox || !xpc::IsSandbox(sandbox)) {
   1561    return NS_ERROR_INVALID_ARG;
   1562  }
   1563 
   1564  nsresult rv = xpc::SetSandboxTimezoneOverride(cx, sandbox, timezone);
   1565  NS_ENSURE_SUCCESS(rv, rv);
   1566 
   1567  return NS_OK;
   1568 }
   1569 
   1570 NS_IMETHODIMP
   1571 nsXPCComponents_Utils::IsESModuleLoaded(const nsACString& aResourceURI,
   1572                                        bool* retval) {
   1573  RefPtr moduleloader = mozJSModuleLoader::Get();
   1574  MOZ_ASSERT(moduleloader);
   1575  return moduleloader->IsESModuleLoaded(aResourceURI, retval);
   1576 }
   1577 
   1578 NS_IMETHODIMP
   1579 nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
   1580                                              JSContext* cx) {
   1581  // Ensure we're working in the scripted caller's realm. This is not guaranteed
   1582  // to be the current realm because we switch realms when calling cross-realm
   1583  // functions.
   1584  RootedObject global(cx, JS::GetScriptedCallerGlobal(cx));
   1585  MOZ_ASSERT(global);
   1586  js::AssertSameCompartment(cx, global);
   1587  JSAutoRealm ar(cx, global);
   1588 
   1589  // Don't allow doing this if the global is a Window.
   1590  nsGlobalWindowInner* win;
   1591  if (NS_SUCCEEDED(UNWRAP_NON_WRAPPER_OBJECT(Window, global, win))) {
   1592    return NS_ERROR_NOT_AVAILABLE;
   1593  }
   1594 
   1595  GlobalProperties options;
   1596  NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
   1597 
   1598  RootedObject propertyList(cx, &aPropertyList.toObject());
   1599  bool isArray;
   1600  if (NS_WARN_IF(!JS::IsArrayObject(cx, propertyList, &isArray))) {
   1601    return NS_ERROR_FAILURE;
   1602  }
   1603  if (NS_WARN_IF(!isArray)) {
   1604    return NS_ERROR_INVALID_ARG;
   1605  }
   1606 
   1607  if (!options.Parse(cx, propertyList) ||
   1608      !options.DefineInXPCComponents(cx, global)) {
   1609    return NS_ERROR_FAILURE;
   1610  }
   1611 
   1612  return NS_OK;
   1613 }
   1614 
   1615 NS_IMETHODIMP
   1616 nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext* cx,
   1617                                        xpcIJSWeakReference** _retval) {
   1618  RefPtr<xpcJSWeakReference> ref = new xpcJSWeakReference();
   1619  nsresult rv = ref->Init(cx, object);
   1620  NS_ENSURE_SUCCESS(rv, rv);
   1621  ref.forget(_retval);
   1622  return NS_OK;
   1623 }
   1624 
   1625 NS_IMETHODIMP
   1626 nsXPCComponents_Utils::ForceGC(JSContext* aCx) {
   1627  PrepareForFullGC(aCx);
   1628  NonIncrementalGC(aCx, GCOptions::Normal, GCReason::COMPONENT_UTILS);
   1629  return NS_OK;
   1630 }
   1631 
   1632 NS_IMETHODIMP
   1633 nsXPCComponents_Utils::ForceCC(nsICycleCollectorListener* listener) {
   1634  nsJSContext::CycleCollectNow(CCReason::API, listener);
   1635  return NS_OK;
   1636 }
   1637 
   1638 NS_IMETHODIMP
   1639 nsXPCComponents_Utils::CreateCCLogger(nsICycleCollectorListener** aListener) {
   1640  NS_ENSURE_ARG_POINTER(aListener);
   1641  nsCOMPtr<nsICycleCollectorListener> logger = nsCycleCollector_createLogger();
   1642  logger.forget(aListener);
   1643  return NS_OK;
   1644 }
   1645 
   1646 NS_IMETHODIMP
   1647 nsXPCComponents_Utils::FinishCC() {
   1648  nsCycleCollector_finishAnyCurrentCollection();
   1649  return NS_OK;
   1650 }
   1651 
   1652 NS_IMETHODIMP
   1653 nsXPCComponents_Utils::CcSlice(int64_t budget) {
   1654  nsJSContext::RunCycleCollectorWorkSlice(budget);
   1655  return NS_OK;
   1656 }
   1657 
   1658 NS_IMETHODIMP
   1659 nsXPCComponents_Utils::GetMaxCCSliceTimeSinceClear(int32_t* out) {
   1660  *out = nsJSContext::GetMaxCCSliceTimeSinceClear();
   1661  return NS_OK;
   1662 }
   1663 
   1664 NS_IMETHODIMP
   1665 nsXPCComponents_Utils::ClearMaxCCTime() {
   1666  nsJSContext::ClearMaxCCSliceTime();
   1667  return NS_OK;
   1668 }
   1669 
   1670 NS_IMETHODIMP
   1671 nsXPCComponents_Utils::ForceShrinkingGC(JSContext* aCx) {
   1672  PrepareForFullGC(aCx);
   1673  NonIncrementalGC(aCx, GCOptions::Shrink, GCReason::COMPONENT_UTILS);
   1674  return NS_OK;
   1675 }
   1676 
   1677 class PreciseGCRunnable : public Runnable {
   1678 public:
   1679  PreciseGCRunnable(nsIScheduledGCCallback* aCallback, bool aShrinking)
   1680      : mozilla::Runnable("PreciseGCRunnable"),
   1681        mCallback(aCallback),
   1682        mShrinking(aShrinking) {}
   1683 
   1684  NS_IMETHOD Run() override {
   1685    nsJSContext::GarbageCollectNow(
   1686        GCReason::COMPONENT_UTILS,
   1687        mShrinking ? nsJSContext::ShrinkingGC : nsJSContext::NonShrinkingGC);
   1688 
   1689    mCallback->Callback();
   1690    return NS_OK;
   1691  }
   1692 
   1693 private:
   1694  nsCOMPtr<nsIScheduledGCCallback> mCallback;
   1695  bool mShrinking;
   1696 };
   1697 
   1698 NS_IMETHODIMP
   1699 nsXPCComponents_Utils::SchedulePreciseGC(nsIScheduledGCCallback* aCallback) {
   1700  RefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, false);
   1701  return NS_DispatchToMainThread(event);
   1702 }
   1703 
   1704 NS_IMETHODIMP
   1705 nsXPCComponents_Utils::SchedulePreciseShrinkingGC(
   1706    nsIScheduledGCCallback* aCallback) {
   1707  RefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, true);
   1708  return NS_DispatchToMainThread(event);
   1709 }
   1710 
   1711 NS_IMETHODIMP
   1712 nsXPCComponents_Utils::UnlinkGhostWindows() {
   1713 #ifdef DEBUG
   1714  nsWindowMemoryReporter::UnlinkGhostWindows();
   1715 
   1716  if (XRE_IsParentProcess()) {
   1717    nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
   1718    if (obsvc) {
   1719      obsvc->NotifyObservers(nullptr, "child-ghost-request", nullptr);
   1720    }
   1721  }
   1722 
   1723  return NS_OK;
   1724 #else
   1725  return NS_ERROR_NOT_IMPLEMENTED;
   1726 #endif
   1727 }
   1728 
   1729 #ifdef NS_FREE_PERMANENT_DATA
   1730 struct IntentionallyLeakedObject {
   1731  MOZ_COUNTED_DEFAULT_CTOR(IntentionallyLeakedObject)
   1732 
   1733  MOZ_COUNTED_DTOR(IntentionallyLeakedObject)
   1734 };
   1735 #endif
   1736 
   1737 NS_IMETHODIMP
   1738 nsXPCComponents_Utils::IntentionallyLeak() {
   1739 #ifdef NS_FREE_PERMANENT_DATA
   1740  (void)new IntentionallyLeakedObject();
   1741  return NS_OK;
   1742 #else
   1743  return NS_ERROR_NOT_IMPLEMENTED;
   1744 #endif
   1745 }
   1746 
   1747 NS_IMETHODIMP
   1748 nsXPCComponents_Utils::GetJSTestingFunctions(JSContext* cx,
   1749                                             MutableHandleValue retval) {
   1750  JSObject* obj = js::GetTestingFunctions(cx);
   1751  if (!obj) {
   1752    return NS_ERROR_XPC_JAVASCRIPT_ERROR;
   1753  }
   1754  retval.setObject(*obj);
   1755  return NS_OK;
   1756 }
   1757 
   1758 NS_IMETHODIMP
   1759 nsXPCComponents_Utils::GetFunctionSourceLocation(HandleValue funcValue,
   1760                                                 JSContext* cx,
   1761                                                 MutableHandleValue retval) {
   1762  NS_ENSURE_TRUE(funcValue.isObject(), NS_ERROR_INVALID_ARG);
   1763 
   1764  nsAutoString filename;
   1765  uint32_t lineNumber;
   1766  {
   1767    RootedObject funcObj(cx, UncheckedUnwrap(&funcValue.toObject()));
   1768    JSAutoRealm ar(cx, funcObj);
   1769 
   1770    Rooted<JSFunction*> func(cx, JS_GetObjectFunction(funcObj));
   1771    NS_ENSURE_TRUE(func, NS_ERROR_INVALID_ARG);
   1772 
   1773    RootedScript script(cx, JS_GetFunctionScript(cx, func));
   1774    NS_ENSURE_TRUE(script, NS_ERROR_FAILURE);
   1775 
   1776    AppendUTF8toUTF16(nsDependentCString(JS_GetScriptFilename(script)),
   1777                      filename);
   1778    lineNumber = JS_GetScriptBaseLineNumber(cx, script) + 1;
   1779  }
   1780 
   1781  RootedObject res(cx, JS_NewPlainObject(cx));
   1782  NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY);
   1783 
   1784  RootedValue filenameVal(cx);
   1785  if (!xpc::NonVoidStringToJsval(cx, filename, &filenameVal) ||
   1786      !JS_DefineProperty(cx, res, "filename", filenameVal, JSPROP_ENUMERATE)) {
   1787    return NS_ERROR_OUT_OF_MEMORY;
   1788  }
   1789 
   1790  if (!JS_DefineProperty(cx, res, "lineNumber", lineNumber, JSPROP_ENUMERATE)) {
   1791    return NS_ERROR_OUT_OF_MEMORY;
   1792  }
   1793 
   1794  retval.setObject(*res);
   1795  return NS_OK;
   1796 }
   1797 
   1798 NS_IMETHODIMP
   1799 nsXPCComponents_Utils::CallFunctionWithAsyncStack(HandleValue function,
   1800                                                  nsIStackFrame* stack,
   1801                                                  const nsAString& asyncCause,
   1802                                                  JSContext* cx,
   1803                                                  MutableHandleValue retval) {
   1804  nsresult rv;
   1805 
   1806  if (!stack || asyncCause.IsEmpty()) {
   1807    return NS_ERROR_INVALID_ARG;
   1808  }
   1809 
   1810  JS::Rooted<JS::Value> asyncStack(cx);
   1811  rv = stack->GetNativeSavedFrame(&asyncStack);
   1812  if (NS_FAILED(rv)) {
   1813    return rv;
   1814  }
   1815  if (!asyncStack.isObject()) {
   1816    JS_ReportErrorASCII(cx, "Must use a native JavaScript stack frame");
   1817    return NS_ERROR_INVALID_ARG;
   1818  }
   1819 
   1820  JS::Rooted<JSObject*> asyncStackObj(cx, &asyncStack.toObject());
   1821 
   1822  NS_ConvertUTF16toUTF8 utf8Cause(asyncCause);
   1823  JS::AutoSetAsyncStackForNewCalls sas(
   1824      cx, asyncStackObj, utf8Cause.get(),
   1825      JS::AutoSetAsyncStackForNewCalls::AsyncCallKind::EXPLICIT);
   1826 
   1827  if (!JS_CallFunctionValue(cx, nullptr, function,
   1828                            JS::HandleValueArray::empty(), retval)) {
   1829    return NS_ERROR_XPC_JAVASCRIPT_ERROR;
   1830  }
   1831 
   1832  return NS_OK;
   1833 }
   1834 
   1835 NS_IMETHODIMP
   1836 nsXPCComponents_Utils::GetGlobalForObject(HandleValue object, JSContext* cx,
   1837                                          MutableHandleValue retval) {
   1838  // First argument must be an object.
   1839  if (object.isPrimitive()) {
   1840    return NS_ERROR_XPC_BAD_CONVERT_JS;
   1841  }
   1842 
   1843  // When getting the global for a cross-compartment wrapper, we really want
   1844  // a wrapper for the foreign global. So we need to unwrap before getting the
   1845  // global and then wrap the result.
   1846  Rooted<JSObject*> obj(cx, &object.toObject());
   1847  obj = JS::GetNonCCWObjectGlobal(js::UncheckedUnwrap(obj));
   1848 
   1849  if (!JS_WrapObject(cx, &obj)) {
   1850    return NS_ERROR_FAILURE;
   1851  }
   1852 
   1853  // Get the WindowProxy if necessary.
   1854  obj = js::ToWindowProxyIfWindow(obj);
   1855 
   1856  retval.setObject(*obj);
   1857  return NS_OK;
   1858 }
   1859 
   1860 NS_IMETHODIMP
   1861 nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext* cx, bool* rval) {
   1862  if (!vobj.isObject()) {
   1863    *rval = false;
   1864    return NS_OK;
   1865  }
   1866 
   1867  RootedObject obj(cx, &vobj.toObject());
   1868  // We need to do a dynamic unwrap, because we apparently want to treat
   1869  // "failure to unwrap" differently from "not a proxy" (throw for the former,
   1870  // return false for the latter).
   1871  obj = js::CheckedUnwrapDynamic(obj, cx, /* stopAtWindowProxy = */ false);
   1872  NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
   1873 
   1874  *rval = js::IsScriptedProxy(obj);
   1875  return NS_OK;
   1876 }
   1877 
   1878 NS_IMETHODIMP
   1879 nsXPCComponents_Utils::ExportFunction(HandleValue vfunction, HandleValue vscope,
   1880                                      HandleValue voptions, JSContext* cx,
   1881                                      MutableHandleValue rval) {
   1882  if (!xpc::ExportFunction(cx, vfunction, vscope, voptions, rval)) {
   1883    return NS_ERROR_FAILURE;
   1884  }
   1885  return NS_OK;
   1886 }
   1887 
   1888 NS_IMETHODIMP
   1889 nsXPCComponents_Utils::CreateObjectIn(HandleValue vobj, HandleValue voptions,
   1890                                      JSContext* cx, MutableHandleValue rval) {
   1891  RootedObject optionsObject(
   1892      cx, voptions.isObject() ? &voptions.toObject() : nullptr);
   1893  CreateObjectInOptions options(cx, optionsObject);
   1894  if (voptions.isObject() && !options.Parse()) {
   1895    return NS_ERROR_FAILURE;
   1896  }
   1897 
   1898  if (!xpc::CreateObjectIn(cx, vobj, options, rval)) {
   1899    return NS_ERROR_FAILURE;
   1900  }
   1901  return NS_OK;
   1902 }
   1903 
   1904 NS_IMETHODIMP
   1905 nsXPCComponents_Utils::MakeObjectPropsNormal(HandleValue vobj, JSContext* cx) {
   1906  if (!cx) {
   1907    return NS_ERROR_FAILURE;
   1908  }
   1909 
   1910  // first argument must be an object
   1911  if (vobj.isPrimitive()) {
   1912    return NS_ERROR_XPC_BAD_CONVERT_JS;
   1913  }
   1914 
   1915  RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
   1916  JSAutoRealm ar(cx, obj);
   1917  Rooted<IdVector> ida(cx, IdVector(cx));
   1918  if (!JS_Enumerate(cx, obj, &ida)) {
   1919    return NS_ERROR_FAILURE;
   1920  }
   1921 
   1922  RootedId id(cx);
   1923  RootedValue v(cx);
   1924  for (size_t i = 0; i < ida.length(); ++i) {
   1925    id = ida[i];
   1926 
   1927    if (!JS_GetPropertyById(cx, obj, id, &v)) {
   1928      return NS_ERROR_FAILURE;
   1929    }
   1930 
   1931    if (v.isPrimitive()) {
   1932      continue;
   1933    }
   1934 
   1935    RootedObject propobj(cx, &v.toObject());
   1936    // TODO Deal with non-functions.
   1937    if (!js::IsWrapper(propobj) || !JS::IsCallable(propobj)) {
   1938      continue;
   1939    }
   1940 
   1941    FunctionForwarderOptions forwarderOptions;
   1942    if (!NewFunctionForwarder(cx, id, propobj, forwarderOptions, &v) ||
   1943        !JS_SetPropertyById(cx, obj, id, v))
   1944      return NS_ERROR_FAILURE;
   1945  }
   1946 
   1947  return NS_OK;
   1948 }
   1949 
   1950 NS_IMETHODIMP
   1951 nsXPCComponents_Utils::IsDeadWrapper(HandleValue obj, bool* out) {
   1952  *out = false;
   1953  if (obj.isPrimitive()) {
   1954    return NS_ERROR_INVALID_ARG;
   1955  }
   1956 
   1957  // We should never have cross-compartment wrappers for dead wrappers.
   1958  MOZ_ASSERT_IF(js::IsCrossCompartmentWrapper(&obj.toObject()),
   1959                !JS_IsDeadWrapper(js::UncheckedUnwrap(&obj.toObject())));
   1960 
   1961  *out = JS_IsDeadWrapper(&obj.toObject());
   1962  return NS_OK;
   1963 }
   1964 
   1965 NS_IMETHODIMP
   1966 nsXPCComponents_Utils::IsRemoteProxy(HandleValue val, bool* out) {
   1967  if (val.isObject()) {
   1968    *out = dom::IsRemoteObjectProxy(UncheckedUnwrap(&val.toObject()));
   1969    ;
   1970  } else {
   1971    *out = false;
   1972  }
   1973  return NS_OK;
   1974 }
   1975 
   1976 NS_IMETHODIMP
   1977 nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext* cx) {
   1978  // Determine the compartment of the given object, if any.
   1979  JS::Compartment* c =
   1980      vobj.isObject()
   1981          ? JS::GetCompartment(js::UncheckedUnwrap(&vobj.toObject()))
   1982          : nullptr;
   1983 
   1984  // If no compartment was given, recompute all.
   1985  if (!c) {
   1986    js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments());
   1987    // Otherwise, recompute wrappers for the given compartment.
   1988  } else {
   1989    js::RecomputeWrappers(cx, js::SingleCompartment(c),
   1990                          js::AllCompartments()) &&
   1991        js::RecomputeWrappers(cx, js::AllCompartments(),
   1992                              js::SingleCompartment(c));
   1993  }
   1994 
   1995  return NS_OK;
   1996 }
   1997 
   1998 NS_IMETHODIMP
   1999 nsXPCComponents_Utils::SetWantXrays(HandleValue vscope, JSContext* cx) {
   2000  if (!vscope.isObject()) {
   2001    return NS_ERROR_INVALID_ARG;
   2002  }
   2003  JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
   2004  MOZ_RELEASE_ASSERT(!AccessCheck::isChrome(scopeObj),
   2005                     "Don't call setWantXrays on system-principal scopes");
   2006  JS::Compartment* compartment = JS::GetCompartment(scopeObj);
   2007  CompartmentPrivate::Get(scopeObj)->wantXrays = true;
   2008  bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
   2009                                  js::AllCompartments());
   2010  NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
   2011  return NS_OK;
   2012 }
   2013 
   2014 NS_IMETHODIMP
   2015 nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
   2016                                JSContext* cx) {
   2017  RootedValue runnable(cx, runnableArg);
   2018  // Enter the given realm, if any, and rewrap runnable.
   2019  Maybe<JSAutoRealm> ar;
   2020  if (scope.isObject()) {
   2021    JSObject* scopeObj = js::UncheckedUnwrap(&scope.toObject());
   2022    if (!scopeObj) {
   2023      return NS_ERROR_FAILURE;
   2024    }
   2025    ar.emplace(cx, scopeObj);
   2026    if (!JS_WrapValue(cx, &runnable)) {
   2027      return NS_ERROR_FAILURE;
   2028    }
   2029  }
   2030 
   2031  // Get an XPCWrappedJS for |runnable|.
   2032  if (!runnable.isObject()) {
   2033    return NS_ERROR_INVALID_ARG;
   2034  }
   2035 
   2036  RootedObject runnableObj(cx, &runnable.toObject());
   2037  nsCOMPtr<nsIRunnable> run;
   2038  nsresult rv = nsXPConnect::XPConnect()->WrapJS(
   2039      cx, runnableObj, NS_GET_IID(nsIRunnable), getter_AddRefs(run));
   2040  NS_ENSURE_SUCCESS(rv, rv);
   2041  MOZ_ASSERT(run);
   2042 
   2043  // Dispatch.
   2044  return NS_DispatchToMainThread(run);
   2045 }
   2046 
   2047 NS_IMETHODIMP
   2048 nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx) {
   2049 #ifdef JS_GC_ZEAL
   2050  JS::SetGCZeal(cx, uint8_t(aValue), JS::BrowserDefaultGCZealFrequency);
   2051 #endif
   2052  return NS_OK;
   2053 }
   2054 
   2055 NS_IMETHODIMP
   2056 nsXPCComponents_Utils::GetIsInAutomation(bool* aResult) {
   2057  NS_ENSURE_ARG_POINTER(aResult);
   2058 
   2059  *aResult = xpc::IsInAutomation();
   2060  return NS_OK;
   2061 }
   2062 
   2063 NS_IMETHODIMP
   2064 nsXPCComponents_Utils::ExitIfInAutomation() {
   2065  NS_ENSURE_TRUE(xpc::IsInAutomation(), NS_ERROR_FAILURE);
   2066 
   2067  profiler_shutdown(IsFastShutdown::Yes);
   2068 
   2069  mozilla::AppShutdown::DoImmediateExit();
   2070  return NS_OK;
   2071 }
   2072 
   2073 NS_IMETHODIMP
   2074 nsXPCComponents_Utils::CrashIfNotInAutomation() {
   2075  xpc::CrashIfNotInAutomation();
   2076  return NS_OK;
   2077 }
   2078 
   2079 NS_IMETHODIMP
   2080 nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext* cx) {
   2081  AUTO_PROFILER_LABEL("nsXPCComponents_Utils::NukeSandbox", OTHER);
   2082  NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG);
   2083  JSObject* wrapper = &obj.toObject();
   2084  NS_ENSURE_TRUE(IsWrapper(wrapper), NS_ERROR_INVALID_ARG);
   2085  RootedObject sb(cx, UncheckedUnwrap(wrapper));
   2086  NS_ENSURE_TRUE(IsSandbox(sb), NS_ERROR_INVALID_ARG);
   2087 
   2088  xpc::NukeAllWrappersForRealm(cx, GetNonCCWObjectRealm(sb));
   2089 
   2090  return NS_OK;
   2091 }
   2092 
   2093 NS_IMETHODIMP
   2094 nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
   2095                                            JSContext* cx) {
   2096  NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
   2097  RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
   2098                                          /* stopAtWindowProxy = */ false));
   2099  NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
   2100  if (xpc::GetObjectPrincipal(global)->IsSystemPrincipal()) {
   2101    JS_ReportErrorASCII(cx, "Script may not be disabled for system globals");
   2102    return NS_ERROR_FAILURE;
   2103  }
   2104  Scriptability::Get(global).Block();
   2105  return NS_OK;
   2106 }
   2107 
   2108 NS_IMETHODIMP
   2109 nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
   2110                                              JSContext* cx) {
   2111  NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
   2112  RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
   2113                                          /* stopAtWindowProxy = */ false));
   2114  NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
   2115  if (xpc::GetObjectPrincipal(global)->IsSystemPrincipal()) {
   2116    JS_ReportErrorASCII(cx, "Script may not be disabled for system globals");
   2117    return NS_ERROR_FAILURE;
   2118  }
   2119  Scriptability::Get(global).Unblock();
   2120  return NS_OK;
   2121 }
   2122 
   2123 NS_IMETHODIMP
   2124 nsXPCComponents_Utils::IsOpaqueWrapper(HandleValue obj, bool* aRetval) {
   2125  *aRetval =
   2126      obj.isObject() && xpc::WrapperFactory::IsOpaqueWrapper(&obj.toObject());
   2127  return NS_OK;
   2128 }
   2129 
   2130 NS_IMETHODIMP
   2131 nsXPCComponents_Utils::IsXrayWrapper(HandleValue obj, bool* aRetval) {
   2132  *aRetval =
   2133      obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
   2134  return NS_OK;
   2135 }
   2136 
   2137 NS_IMETHODIMP
   2138 nsXPCComponents_Utils::WaiveXrays(HandleValue aVal, JSContext* aCx,
   2139                                  MutableHandleValue aRetval) {
   2140  RootedValue value(aCx, aVal);
   2141  if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value)) {
   2142    return NS_ERROR_FAILURE;
   2143  }
   2144  aRetval.set(value);
   2145  return NS_OK;
   2146 }
   2147 
   2148 NS_IMETHODIMP
   2149 nsXPCComponents_Utils::UnwaiveXrays(HandleValue aVal, JSContext* aCx,
   2150                                    MutableHandleValue aRetval) {
   2151  if (!aVal.isObject()) {
   2152    aRetval.set(aVal);
   2153    return NS_OK;
   2154  }
   2155 
   2156  RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject()));
   2157  if (!JS_WrapObject(aCx, &obj)) {
   2158    return NS_ERROR_FAILURE;
   2159  }
   2160  aRetval.setObject(*obj);
   2161  return NS_OK;
   2162 }
   2163 
   2164 NS_IMETHODIMP
   2165 nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap,
   2166                                    JSContext* aCx, char** aRv) {
   2167  if (!aObj.isObject()) {
   2168    return NS_ERROR_INVALID_ARG;
   2169  }
   2170  RootedObject obj(aCx, &aObj.toObject());
   2171  if (aUnwrap) {
   2172    obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
   2173  }
   2174  *aRv = NS_xstrdup(JS::GetClass(obj)->name);
   2175  return NS_OK;
   2176 }
   2177 
   2178 NS_IMETHODIMP
   2179 nsXPCComponents_Utils::GetIncumbentGlobal(HandleValue aCallback, JSContext* aCx,
   2180                                          MutableHandleValue aOut) {
   2181  nsCOMPtr<nsIGlobalObject> global = mozilla::dom::GetIncumbentGlobal();
   2182  RootedValue globalVal(aCx);
   2183 
   2184  if (!global) {
   2185    globalVal = NullValue();
   2186  } else {
   2187    // Note: We rely on the wrap call for outerization.
   2188    globalVal = ObjectValue(*global->GetGlobalJSObject());
   2189    if (!JS_WrapValue(aCx, &globalVal)) {
   2190      return NS_ERROR_FAILURE;
   2191    }
   2192  }
   2193 
   2194  // Invoke the callback, if passed.
   2195  if (aCallback.isObject()) {
   2196    RootedValue ignored(aCx);
   2197    if (!JS_CallFunctionValue(aCx, nullptr, aCallback,
   2198                              JS::HandleValueArray(globalVal), &ignored)) {
   2199      return NS_ERROR_FAILURE;
   2200    }
   2201  }
   2202 
   2203  aOut.set(globalVal);
   2204  return NS_OK;
   2205 }
   2206 
   2207 NS_IMETHODIMP
   2208 nsXPCComponents_Utils::GetDebugName(HandleValue aObj, JSContext* aCx,
   2209                                    nsACString& aOut) {
   2210  if (!aObj.isObject()) {
   2211    return NS_ERROR_INVALID_ARG;
   2212  }
   2213 
   2214  RootedObject obj(aCx, &aObj.toObject());
   2215  aOut = xpc::GetFunctionName(aCx, obj);
   2216  return NS_OK;
   2217 }
   2218 
   2219 NS_IMETHODIMP
   2220 nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory,
   2221                                            PRTime* aOut) {
   2222  WatchdogTimestampCategory category;
   2223  if (aCategory.EqualsLiteral("ContextStateChange")) {
   2224    category = TimestampContextStateChange;
   2225  } else if (aCategory.EqualsLiteral("WatchdogWakeup")) {
   2226    category = TimestampWatchdogWakeup;
   2227  } else if (aCategory.EqualsLiteral("WatchdogHibernateStart")) {
   2228    category = TimestampWatchdogHibernateStart;
   2229  } else if (aCategory.EqualsLiteral("WatchdogHibernateStop")) {
   2230    category = TimestampWatchdogHibernateStop;
   2231  } else {
   2232    return NS_ERROR_INVALID_ARG;
   2233  }
   2234  *aOut = XPCJSContext::Get()->GetWatchdogTimestamp(category);
   2235  return NS_OK;
   2236 }
   2237 
   2238 NS_IMETHODIMP
   2239 nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext* cx,
   2240                                                 MutableHandleValue rval) {
   2241  RootedObject obj(cx, JS_NewPlainObject(cx));
   2242  if (!obj) {
   2243    return NS_ERROR_OUT_OF_MEMORY;
   2244  }
   2245 
   2246  // No JS engine telemetry in use at the moment.
   2247 
   2248  rval.setObject(*obj);
   2249  return NS_OK;
   2250 }
   2251 
   2252 bool xpc::CloneInto(JSContext* aCx, HandleValue aValue, HandleValue aScope,
   2253                    HandleValue aOptions, MutableHandleValue aCloned) {
   2254  if (!aScope.isObject()) {
   2255    return false;
   2256  }
   2257 
   2258  RootedObject scope(aCx, &aScope.toObject());
   2259  // The scope could be a Window, so we need to CheckedUnwrapDynamic.
   2260  scope = js::CheckedUnwrapDynamic(scope, aCx);
   2261  if (!scope) {
   2262    JS_ReportErrorASCII(aCx, "Permission denied to clone object into scope");
   2263    return false;
   2264  }
   2265 
   2266  if (!aOptions.isUndefined() && !aOptions.isObject()) {
   2267    JS_ReportErrorASCII(aCx, "Invalid argument");
   2268    return false;
   2269  }
   2270 
   2271  RootedObject optionsObject(
   2272      aCx, aOptions.isObject() ? &aOptions.toObject() : nullptr);
   2273  StackScopedCloneOptions options(aCx, optionsObject);
   2274  if (aOptions.isObject() && !options.Parse()) {
   2275    return false;
   2276  }
   2277 
   2278  js::AssertSameCompartment(aCx, aValue);
   2279  RootedObject sourceScope(aCx, JS::CurrentGlobalOrNull(aCx));
   2280 
   2281  {
   2282    JSAutoRealm ar(aCx, scope);
   2283    aCloned.set(aValue);
   2284    if (!StackScopedClone(aCx, options, sourceScope, aCloned)) {
   2285      return false;
   2286    }
   2287  }
   2288 
   2289  return JS_WrapValue(aCx, aCloned);
   2290 }
   2291 
   2292 NS_IMETHODIMP
   2293 nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope,
   2294                                 HandleValue aOptions, JSContext* aCx,
   2295                                 MutableHandleValue aCloned) {
   2296  return xpc::CloneInto(aCx, aValue, aScope, aOptions, aCloned)
   2297             ? NS_OK
   2298             : NS_ERROR_FAILURE;
   2299 }
   2300 
   2301 NS_IMETHODIMP
   2302 nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal** aResult) {
   2303  // This API may only be when the Entry Settings Object corresponds to a
   2304  // JS-implemented WebIDL call. In all other cases, the value will be null,
   2305  // and we throw.
   2306  nsCOMPtr<nsIPrincipal> callerPrin = mozilla::dom::GetWebIDLCallerPrincipal();
   2307  if (!callerPrin) {
   2308    return NS_ERROR_NOT_AVAILABLE;
   2309  }
   2310  callerPrin.forget(aResult);
   2311  return NS_OK;
   2312 }
   2313 
   2314 NS_IMETHODIMP
   2315 nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext* cx,
   2316                                          nsIPrincipal** result) {
   2317  if (!val.isObject()) {
   2318    return NS_ERROR_INVALID_ARG;
   2319  }
   2320  RootedObject obj(cx, &val.toObject());
   2321  // We need to be able to unwrap to WindowProxy or Location here, so
   2322  // use CheckedUnwrapDynamic.
   2323  obj = js::CheckedUnwrapDynamic(obj, cx);
   2324  MOZ_ASSERT(obj);
   2325 
   2326  nsCOMPtr<nsIPrincipal> prin = nsContentUtils::ObjectPrincipal(obj);
   2327  prin.forget(result);
   2328  return NS_OK;
   2329 }
   2330 
   2331 NS_IMETHODIMP
   2332 nsXPCComponents_Utils::GetRealmLocation(HandleValue val, JSContext* cx,
   2333                                        nsACString& result) {
   2334  if (!val.isObject()) {
   2335    return NS_ERROR_INVALID_ARG;
   2336  }
   2337  RootedObject obj(cx, &val.toObject());
   2338  // We need to be able to unwrap to WindowProxy or Location here, so
   2339  // use CheckedUnwrapDynamic.
   2340  obj = js::CheckedUnwrapDynamic(obj, cx);
   2341  MOZ_ASSERT(obj);
   2342 
   2343  result = xpc::RealmPrivate::Get(obj)->GetLocation();
   2344  return NS_OK;
   2345 }
   2346 
   2347 NS_IMETHODIMP
   2348 nsXPCComponents_Utils::ReadUTF8File(nsIFile* aFile, nsACString& aResult) {
   2349  NS_ENSURE_TRUE(aFile, NS_ERROR_INVALID_ARG);
   2350 
   2351  aResult = MOZ_TRY(URLPreloader::ReadFile(aFile));
   2352  return NS_OK;
   2353 }
   2354 
   2355 NS_IMETHODIMP
   2356 nsXPCComponents_Utils::ReadUTF8URI(nsIURI* aURI, nsACString& aResult) {
   2357  NS_ENSURE_TRUE(aURI, NS_ERROR_INVALID_ARG);
   2358 
   2359  aResult = MOZ_TRY(URLPreloader::ReadURI(aURI));
   2360  return NS_OK;
   2361 }
   2362 
   2363 NS_IMETHODIMP
   2364 nsXPCComponents_Utils::CreateSpellChecker(nsIEditorSpellCheck** aSpellChecker) {
   2365  NS_ENSURE_ARG_POINTER(aSpellChecker);
   2366  nsCOMPtr<nsIEditorSpellCheck> spellChecker = new mozilla::EditorSpellCheck();
   2367  spellChecker.forget(aSpellChecker);
   2368  return NS_OK;
   2369 }
   2370 
   2371 NS_IMETHODIMP
   2372 nsXPCComponents_Utils::CreateCommandLine(const nsTArray<nsCString>& aArgs,
   2373                                         nsIFile* aWorkingDir, uint32_t aState,
   2374                                         nsISupports** aCommandLine) {
   2375  NS_ENSURE_ARG_MAX(aState, nsICommandLine::STATE_REMOTE_EXPLICIT);
   2376  NS_ENSURE_ARG_POINTER(aCommandLine);
   2377 
   2378  nsCOMPtr<nsISupports> commandLine = new nsCommandLine();
   2379  nsCOMPtr<nsICommandLineRunner> runner = do_QueryInterface(commandLine);
   2380 
   2381  nsTArray<const char*> fakeArgv(aArgs.Length() + 2);
   2382 
   2383  // Prepend a dummy argument for the program name, which will be ignored.
   2384  fakeArgv.AppendElement(nullptr);
   2385  for (const nsCString& arg : aArgs) {
   2386    fakeArgv.AppendElement(arg.get());
   2387  }
   2388  // Append a null terminator.
   2389  fakeArgv.AppendElement(nullptr);
   2390 
   2391  nsresult rv = runner->Init(fakeArgv.Length() - 1, fakeArgv.Elements(),
   2392                             aWorkingDir, aState);
   2393  NS_ENSURE_SUCCESS(rv, rv);
   2394 
   2395  commandLine.forget(aCommandLine);
   2396  return NS_OK;
   2397 }
   2398 
   2399 NS_IMETHODIMP
   2400 nsXPCComponents_Utils::CreateCommandParams(nsICommandParams** aCommandParams) {
   2401  NS_ENSURE_ARG_POINTER(aCommandParams);
   2402  nsCOMPtr<nsICommandParams> commandParams = new nsCommandParams();
   2403  commandParams.forget(aCommandParams);
   2404  return NS_OK;
   2405 }
   2406 
   2407 NS_IMETHODIMP
   2408 nsXPCComponents_Utils::CreateLoadContext(nsILoadContext** aLoadContext) {
   2409  NS_ENSURE_ARG_POINTER(aLoadContext);
   2410  nsCOMPtr<nsILoadContext> loadContext = ::CreateLoadContext();
   2411  loadContext.forget(aLoadContext);
   2412  return NS_OK;
   2413 }
   2414 
   2415 NS_IMETHODIMP
   2416 nsXPCComponents_Utils::CreatePrivateLoadContext(nsILoadContext** aLoadContext) {
   2417  NS_ENSURE_ARG_POINTER(aLoadContext);
   2418  nsCOMPtr<nsILoadContext> loadContext = ::CreatePrivateLoadContext();
   2419  loadContext.forget(aLoadContext);
   2420  return NS_OK;
   2421 }
   2422 
   2423 NS_IMETHODIMP
   2424 nsXPCComponents_Utils::CreatePersistentProperties(
   2425    nsIPersistentProperties** aPersistentProperties) {
   2426  NS_ENSURE_ARG_POINTER(aPersistentProperties);
   2427  nsCOMPtr<nsIPersistentProperties> props = new nsPersistentProperties();
   2428  props.forget(aPersistentProperties);
   2429  return NS_OK;
   2430 }
   2431 
   2432 NS_IMETHODIMP
   2433 nsXPCComponents_Utils::CreateDocumentEncoder(
   2434    const char* aContentType, nsIDocumentEncoder** aDocumentEncoder) {
   2435  NS_ENSURE_ARG_POINTER(aDocumentEncoder);
   2436  nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder(aContentType);
   2437  encoder.forget(aDocumentEncoder);
   2438  return NS_OK;
   2439 }
   2440 
   2441 NS_IMETHODIMP
   2442 nsXPCComponents_Utils::CreateHTMLCopyEncoder(
   2443    nsIDocumentEncoder** aDocumentEncoder) {
   2444  NS_ENSURE_ARG_POINTER(aDocumentEncoder);
   2445  nsCOMPtr<nsIDocumentEncoder> encoder = do_createHTMLCopyEncoder();
   2446  encoder.forget(aDocumentEncoder);
   2447  return NS_OK;
   2448 }
   2449 
   2450 NS_IMETHODIMP
   2451 nsXPCComponents_Utils::GetLoadedESModules(
   2452    nsTArray<nsCString>& aLoadedESModules) {
   2453  return mozJSModuleLoader::Get()->GetLoadedESModules(aLoadedESModules);
   2454 }
   2455 
   2456 NS_IMETHODIMP
   2457 nsXPCComponents_Utils::GetModuleImportStack(const nsACString& aLocation,
   2458                                            nsACString& aRetval) {
   2459  nsresult rv =
   2460      mozJSModuleLoader::Get()->GetModuleImportStack(aLocation, aRetval);
   2461  // Fallback the query to the DevTools loader if not found in the shared loader
   2462  if (rv == NS_ERROR_FAILURE && mozJSModuleLoader::GetDevToolsLoader()) {
   2463    return mozJSModuleLoader::GetDevToolsLoader()->GetModuleImportStack(
   2464        aLocation, aRetval);
   2465  }
   2466  return rv;
   2467 }
   2468 
   2469 /***************************************************************************/
   2470 /***************************************************************************/
   2471 /***************************************************************************/
   2472 
   2473 nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
   2474    : mScope(aScope) {
   2475  MOZ_ASSERT(aScope, "aScope must not be null");
   2476 }
   2477 
   2478 nsXPCComponents::~nsXPCComponents() = default;
   2479 
   2480 void nsXPCComponents::ClearMembers() {
   2481  mInterfaces = nullptr;
   2482  mResults = nullptr;
   2483  mClasses = nullptr;
   2484  mID = nullptr;
   2485  mException = nullptr;
   2486  mConstructor = nullptr;
   2487  mUtils = nullptr;
   2488 }
   2489 
   2490 /*******************************************/
   2491 #define XPC_IMPL_GET_OBJ_METHOD(_class, _n)                      \
   2492  NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n** a##_n) { \
   2493    NS_ENSURE_ARG_POINTER(a##_n);                                \
   2494    if (!m##_n) m##_n = new nsXPCComponents_##_n();              \
   2495    RefPtr<nsXPCComponents_##_n> ret = m##_n;                    \
   2496    ret.forget(a##_n);                                           \
   2497    return NS_OK;                                                \
   2498  }
   2499 
   2500 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Interfaces)
   2501 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes)
   2502 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Results)
   2503 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID)
   2504 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception)
   2505 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor)
   2506 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils)
   2507 
   2508 #undef XPC_IMPL_GET_OBJ_METHOD
   2509 /*******************************************/
   2510 
   2511 NS_IMETHODIMP
   2512 nsXPCComponents::IsSuccessCode(nsresult result, bool* out) {
   2513  *out = NS_SUCCEEDED(result);
   2514  return NS_OK;
   2515 }
   2516 
   2517 NS_IMETHODIMP
   2518 nsXPCComponents::GetStack(nsIStackFrame** aStack) {
   2519  nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
   2520  frame.forget(aStack);
   2521  return NS_OK;
   2522 }
   2523 
   2524 NS_IMETHODIMP
   2525 nsXPCComponents::GetManager(nsIComponentManager** aManager) {
   2526  MOZ_ASSERT(aManager, "bad param");
   2527  return NS_GetComponentManager(aManager);
   2528 }
   2529 
   2530 NS_IMETHODIMP
   2531 nsXPCComponents::GetReturnCode(JSContext* aCx, MutableHandleValue aOut) {
   2532  nsresult res = XPCJSContext::Get()->GetPendingResult();
   2533  aOut.setNumber(static_cast<uint32_t>(res));
   2534  return NS_OK;
   2535 }
   2536 
   2537 NS_IMETHODIMP
   2538 nsXPCComponents::SetReturnCode(JSContext* aCx, HandleValue aCode) {
   2539  nsresult rv;
   2540  if (!ToUint32(aCx, aCode, (uint32_t*)&rv)) {
   2541    return NS_ERROR_FAILURE;
   2542  }
   2543  XPCJSContext::Get()->SetPendingResult(rv);
   2544  return NS_OK;
   2545 }
   2546 
   2547 /**********************************************/
   2548 
   2549 class ComponentsSH : public nsIXPCScriptable {
   2550 public:
   2551  explicit constexpr ComponentsSH(unsigned dummy) {}
   2552 
   2553  // We don't actually inherit any ref counting infrastructure, but we don't
   2554  // need an nsAutoRefCnt member, so the _INHERITED macro is a hack to avoid
   2555  // having one.
   2556  NS_DECL_ISUPPORTS_INHERITED
   2557  NS_DECL_NSIXPCSCRIPTABLE
   2558  static nsresult Get(nsIXPCScriptable** helper) {
   2559    *helper = &singleton;
   2560    return NS_OK;
   2561  }
   2562 
   2563 private:
   2564  static ComponentsSH singleton;
   2565 };
   2566 
   2567 ComponentsSH ComponentsSH::singleton(0);
   2568 
   2569 // Singleton refcounting.
   2570 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::AddRef(void) { return 1; }
   2571 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::Release(void) {
   2572  return 1;
   2573 }
   2574 
   2575 NS_IMPL_QUERY_INTERFACE(ComponentsSH, nsIXPCScriptable)
   2576 
   2577 #define NSXPCCOMPONENTS_CID \
   2578  {0x3649f405, 0xf0ec, 0x4c28, {0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81}}
   2579 
   2580 NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, 0, NSXPCCOMPONENTS_CID)
   2581 NS_IMPL_ISUPPORTS_CI(nsXPCComponents, nsIXPCComponents)
   2582 
   2583 // The nsIXPCScriptable map declaration that will generate stubs for us
   2584 #define XPC_MAP_CLASSNAME ComponentsSH
   2585 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents"
   2586 #define XPC_MAP_FLAGS XPC_SCRIPTABLE_WANT_PRECREATE
   2587 #include "xpc_map_end.h" /* This will #undef the above */
   2588 
   2589 NS_IMETHODIMP
   2590 ComponentsSH::PreCreate(nsISupports* nativeObj, JSContext* cx,
   2591                        JSObject* globalObj, JSObject** parentObj) {
   2592  nsXPCComponents* self = static_cast<nsXPCComponents*>(nativeObj);
   2593  // this should never happen
   2594  if (!self->GetScope()) {
   2595    NS_WARNING(
   2596        "mScope must not be null when nsXPCComponents::PreCreate is called");
   2597    return NS_ERROR_FAILURE;
   2598  }
   2599  *parentObj = self->GetScope()->GetGlobalForWrappedNatives();
   2600  return NS_OK;
   2601 }