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