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 }