1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 /* The "Components" xpcom objects for JavaScript. */
8
9 #include "xpcprivate.h"
10 #include "xpc_make_class.h"
11 #include "XPCJSWeakReference.h"
12 #include "WrapperFactory.h"
13 #include "nsJSUtils.h"
14 #include "mozJSComponentLoader.h"
15 #include "nsContentUtils.h"
16 #include "nsCycleCollector.h"
17 #include "jsfriendapi.h"
18 #include "js/StructuredClone.h"
19 #include "mozilla/Attributes.h"
20 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
21 #include "mozilla/Preferences.h"
22 #include "nsJSEnvironment.h"
23 #include "mozilla/TimeStamp.h"
24 #include "mozilla/ResultExtensions.h"
25 #include "mozilla/URLPreloader.h"
26 #include "mozilla/XPTInterfaceInfoManager.h"
27 #include "mozilla/dom/DOMException.h"
28 #include "mozilla/dom/DOMExceptionBinding.h"
29 #include "mozilla/dom/BindingUtils.h"
30 #include "mozilla/dom/StructuredCloneTags.h"
31 #include "mozilla/dom/WindowBinding.h"
32 #include "mozilla/Scheduler.h"
33 #include "nsZipArchive.h"
34 #include "nsIDOMFileList.h"
35 #include "nsWindowMemoryReporter.h"
36 #include "nsDOMClassInfo.h"
37 #include "ShimInterfaceInfo.h"
38 #include "nsIException.h"
39 #include "nsIScriptError.h"
40 #include "nsISimpleEnumerator.h"
41 #include "nsPIDOMWindow.h"
42 #include "nsGlobalWindow.h"
43 #include "nsScriptError.h"
44 #include "GeckoProfiler.h"
45
46 using namespace mozilla;
47 using namespace JS;
48 using namespace js;
49 using namespace xpc;
50 using mozilla::dom::Exception;
51
52 /***************************************************************************/
53 // stuff used by all
54
ThrowAndFail(nsresult errNum,JSContext * cx,bool * retval)55 nsresult xpc::ThrowAndFail(nsresult errNum, JSContext* cx, bool* retval) {
56 XPCThrower::Throw(errNum, cx);
57 *retval = false;
58 return NS_OK;
59 }
60
JSValIsInterfaceOfType(JSContext * cx,HandleValue v,REFNSIID iid)61 static bool JSValIsInterfaceOfType(JSContext* cx, HandleValue v, REFNSIID iid) {
62 nsCOMPtr<nsIXPConnectWrappedNative> wn;
63 nsCOMPtr<nsISupports> iface;
64
65 if (v.isPrimitive()) return false;
66
67 nsXPConnect* xpc = nsXPConnect::XPConnect();
68 RootedObject obj(cx, &v.toObject());
69 return NS_SUCCEEDED(
70 xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) &&
71 wn &&
72 NS_SUCCEEDED(
73 wn->Native()->QueryInterface(iid, getter_AddRefs(iface))) &&
74 iface;
75 }
76
CloneAllAccess()77 char* xpc::CloneAllAccess() { return moz_xstrdup("AllAccess"); }
78
CheckAccessList(const char16_t * wideName,const char * const list[])79 char* xpc::CheckAccessList(const char16_t* wideName, const char* const list[]) {
80 nsAutoCString asciiName;
81 CopyUTF16toUTF8(nsDependentString(wideName), asciiName);
82
83 for (const char* const* p = list; *p; p++)
84 if (!strcmp(*p, asciiName.get())) return CloneAllAccess();
85
86 return nullptr;
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 nsCOMArray<nsIInterfaceInfo> mInterfaces;
110 };
111
112 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)113 nsXPCComponents_Interfaces::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
114 *aCount = 2;
115 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
116 *aArray = array;
117
118 array[0] = NS_GET_IID(nsIXPCComponents_Interfaces).Clone();
119 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
120 return NS_OK;
121 }
122
123 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)124 nsXPCComponents_Interfaces::GetScriptableHelper(nsIXPCScriptable** retval) {
125 *retval = nullptr;
126 return NS_OK;
127 }
128
129 NS_IMETHODIMP
GetContractID(nsACString & aContractID)130 nsXPCComponents_Interfaces::GetContractID(nsACString& aContractID) {
131 aContractID.SetIsVoid(true);
132 return NS_ERROR_NOT_AVAILABLE;
133 }
134
135 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)136 nsXPCComponents_Interfaces::GetClassDescription(nsACString& aClassDescription) {
137 aClassDescription.AssignLiteral("XPCComponents_Interfaces");
138 return NS_OK;
139 }
140
141 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)142 nsXPCComponents_Interfaces::GetClassID(nsCID** aClassID) {
143 *aClassID = nullptr;
144 return NS_OK;
145 }
146
147 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)148 nsXPCComponents_Interfaces::GetFlags(uint32_t* aFlags) {
149 // Mark ourselves as a DOM object so that instances may be created in
150 // unprivileged scopes.
151 *aFlags = nsIClassInfo::DOM_OBJECT;
152 return NS_OK;
153 }
154
155 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)156 nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
157 return NS_ERROR_NOT_AVAILABLE;
158 }
159
nsXPCComponents_Interfaces()160 nsXPCComponents_Interfaces::nsXPCComponents_Interfaces() {}
161
~nsXPCComponents_Interfaces()162 nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces() {
163 // empty
164 }
165
166 NS_IMPL_ISUPPORTS(nsXPCComponents_Interfaces, nsIXPCComponents_Interfaces,
167 nsIXPCScriptable, nsIClassInfo);
168
169 // The nsIXPCScriptable map declaration that will generate stubs for us...
170 #define XPC_MAP_CLASSNAME nsXPCComponents_Interfaces
171 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Interfaces"
172 #define XPC_MAP_FLAGS \
173 (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
174 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
175 #include "xpc_map_end.h" /* This will #undef the above */
176
177 NS_IMETHODIMP
NewEnumerate(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * obj,JS::AutoIdVector & properties,bool * _retval)178 nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
179 JSContext* cx, JSObject* obj,
180 JS::AutoIdVector& properties,
181 bool* _retval) {
182 // Lazily init the list of interfaces when someone tries to
183 // enumerate them.
184 if (mInterfaces.IsEmpty()) {
185 XPTInterfaceInfoManager::GetSingleton()->GetScriptableInterfaces(
186 mInterfaces);
187 }
188
189 if (!properties.reserve(mInterfaces.Length())) {
190 *_retval = false;
191 return NS_OK;
192 }
193
194 for (uint32_t index = 0; index < mInterfaces.Length(); index++) {
195 nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(index);
196 if (!interface) continue;
197
198 const char* name;
199 if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) {
200 RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
201 if (!idstr) {
202 *_retval = false;
203 return NS_OK;
204 }
205
206 RootedId id(cx);
207 if (!JS_StringToId(cx, idstr, &id)) {
208 *_retval = false;
209 return NS_OK;
210 }
211
212 properties.infallibleAppend(id);
213 }
214 }
215
216 return NS_OK;
217 }
218
219 NS_IMETHODIMP
Resolve(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,jsid idArg,bool * resolvedp,bool * _retval)220 nsXPCComponents_Interfaces::Resolve(nsIXPConnectWrappedNative* wrapper,
221 JSContext* cx, JSObject* objArg, jsid idArg,
222 bool* resolvedp, bool* _retval) {
223 RootedObject obj(cx, objArg);
224 RootedId id(cx, idArg);
225
226 if (!JSID_IS_STRING(id)) return NS_OK;
227
228 JSAutoByteString name;
229 RootedString str(cx, JSID_TO_STRING(id));
230
231 // we only allow interfaces by name here
232 if (name.encodeLatin1(cx, str) && name.ptr()[0] != '{') {
233 nsCOMPtr<nsIInterfaceInfo> info =
234 ShimInterfaceInfo::MaybeConstruct(name.ptr(), cx);
235 if (!info) {
236 XPTInterfaceInfoManager::GetSingleton()->GetInfoForName(
237 name.ptr(), getter_AddRefs(info));
238 }
239 if (!info) return NS_OK;
240
241 nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
242
243 if (nsid) {
244 nsXPConnect* xpc = nsXPConnect::XPConnect();
245 RootedObject idobj(cx);
246 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, static_cast<nsIJSIID*>(nsid),
247 NS_GET_IID(nsIJSIID),
248 idobj.address()))) {
249 if (idobj) {
250 *resolvedp = true;
251 *_retval =
252 JS_DefinePropertyById(cx, obj, id, idobj,
253 JSPROP_ENUMERATE | JSPROP_READONLY |
254 JSPROP_PERMANENT | JSPROP_RESOLVING);
255 }
256 }
257 }
258 }
259 return NS_OK;
260 }
261
262 /***************************************************************************/
263 /***************************************************************************/
264 /***************************************************************************/
265
266 class nsXPCComponents_InterfacesByID final
267 : public nsIXPCComponents_InterfacesByID,
268 public nsIXPCScriptable,
269 public nsIClassInfo {
270 public:
271 // all the interface method declarations...
272 NS_DECL_ISUPPORTS
273 NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID
274 NS_DECL_NSIXPCSCRIPTABLE
275 NS_DECL_NSICLASSINFO
276
277 public:
278 nsXPCComponents_InterfacesByID();
279
280 private:
281 virtual ~nsXPCComponents_InterfacesByID();
282
283 nsCOMArray<nsIInterfaceInfo> mInterfaces;
284 };
285
286 /***************************************************************************/
287 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)288 nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t* aCount,
289 nsIID*** aArray) {
290 *aCount = 2;
291 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
292 *aArray = array;
293
294 array[0] = NS_GET_IID(nsIXPCComponents_InterfacesByID).Clone();
295 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
296 return NS_OK;
297 }
298
299 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)300 nsXPCComponents_InterfacesByID::GetScriptableHelper(nsIXPCScriptable** retval) {
301 *retval = nullptr;
302 return NS_OK;
303 }
304
305 NS_IMETHODIMP
GetContractID(nsACString & aContractID)306 nsXPCComponents_InterfacesByID::GetContractID(nsACString& aContractID) {
307 aContractID.SetIsVoid(true);
308 return NS_ERROR_NOT_AVAILABLE;
309 }
310
311 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)312 nsXPCComponents_InterfacesByID::GetClassDescription(
313 nsACString& aClassDescription) {
314 aClassDescription.AssignLiteral("XPCComponents_InterfacesByID");
315 return NS_OK;
316 }
317
318 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)319 nsXPCComponents_InterfacesByID::GetClassID(nsCID** aClassID) {
320 *aClassID = nullptr;
321 return NS_OK;
322 }
323
324 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)325 nsXPCComponents_InterfacesByID::GetFlags(uint32_t* aFlags) {
326 // Mark ourselves as a DOM object so that instances may be created in
327 // unprivileged scopes.
328 *aFlags = nsIClassInfo::DOM_OBJECT;
329 return NS_OK;
330 }
331
332 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)333 nsXPCComponents_InterfacesByID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
334 return NS_ERROR_NOT_AVAILABLE;
335 }
336
nsXPCComponents_InterfacesByID()337 nsXPCComponents_InterfacesByID::nsXPCComponents_InterfacesByID() {}
338
~nsXPCComponents_InterfacesByID()339 nsXPCComponents_InterfacesByID::~nsXPCComponents_InterfacesByID() {
340 // empty
341 }
342
NS_IMPL_ISUPPORTS(nsXPCComponents_InterfacesByID,nsIXPCComponents_InterfacesByID,nsIXPCScriptable,nsIClassInfo)343 NS_IMPL_ISUPPORTS(nsXPCComponents_InterfacesByID,
344 nsIXPCComponents_InterfacesByID, nsIXPCScriptable,
345 nsIClassInfo)
346
347 // The nsIXPCScriptable map declaration that will generate stubs for us...
348 #define XPC_MAP_CLASSNAME nsXPCComponents_InterfacesByID
349 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_InterfacesByID"
350 #define XPC_MAP_FLAGS \
351 (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
352 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
353 #include "xpc_map_end.h" /* This will #undef the above */
354
355 NS_IMETHODIMP
356 nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
357 JSContext* cx, JSObject* obj,
358 JS::AutoIdVector& properties,
359 bool* _retval) {
360 if (mInterfaces.IsEmpty()) {
361 XPTInterfaceInfoManager::GetSingleton()->GetScriptableInterfaces(
362 mInterfaces);
363 }
364
365 if (!properties.reserve(mInterfaces.Length())) {
366 *_retval = false;
367 return NS_OK;
368 }
369
370 for (uint32_t index = 0; index < mInterfaces.Length(); index++) {
371 nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(index);
372 if (!interface) continue;
373
374 nsIID const* iid;
375 if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
376 char idstr[NSID_LENGTH];
377 iid->ToProvidedString(idstr);
378 RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr));
379 if (!jsstr) {
380 *_retval = false;
381 return NS_OK;
382 }
383
384 RootedId id(cx);
385 if (!JS_StringToId(cx, jsstr, &id)) {
386 *_retval = false;
387 return NS_OK;
388 }
389
390 properties.infallibleAppend(id);
391 }
392 }
393
394 return NS_OK;
395 }
396
397 NS_IMETHODIMP
Resolve(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,jsid idArg,bool * resolvedp,bool * _retval)398 nsXPCComponents_InterfacesByID::Resolve(nsIXPConnectWrappedNative* wrapper,
399 JSContext* cx, JSObject* objArg,
400 jsid idArg, bool* resolvedp,
401 bool* _retval) {
402 RootedObject obj(cx, objArg);
403 RootedId id(cx, idArg);
404
405 if (!JSID_IS_STRING(id)) return NS_OK;
406
407 RootedString str(cx, JSID_TO_STRING(id));
408 if (38 != JS_GetStringLength(str)) return NS_OK;
409
410 JSAutoByteString utf8str;
411 if (utf8str.encodeUtf8(cx, str)) {
412 nsID iid;
413 if (!iid.Parse(utf8str.ptr())) return NS_OK;
414
415 nsCOMPtr<nsIInterfaceInfo> info;
416 XPTInterfaceInfoManager::GetSingleton()->GetInfoForIID(
417 &iid, getter_AddRefs(info));
418 if (!info) return NS_OK;
419
420 nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
421
422 if (!nsid) return NS_ERROR_OUT_OF_MEMORY;
423
424 nsXPConnect* xpc = nsXPConnect::XPConnect();
425 RootedObject idobj(cx);
426 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, static_cast<nsIJSIID*>(nsid),
427 NS_GET_IID(nsIJSIID), idobj.address()))) {
428 if (idobj) {
429 *resolvedp = true;
430 *_retval =
431 JS_DefinePropertyById(cx, obj, id, idobj,
432 JSPROP_ENUMERATE | JSPROP_READONLY |
433 JSPROP_PERMANENT | JSPROP_RESOLVING);
434 }
435 }
436 }
437 return NS_OK;
438 }
439
440 /***************************************************************************/
441 /***************************************************************************/
442 /***************************************************************************/
443
444 class nsXPCComponents_Classes final : public nsIXPCComponents_Classes,
445 public nsIXPCScriptable,
446 public nsIClassInfo {
447 public:
448 // all the interface method declarations...
449 NS_DECL_ISUPPORTS
450 NS_DECL_NSIXPCCOMPONENTS_CLASSES
451 NS_DECL_NSIXPCSCRIPTABLE
452 NS_DECL_NSICLASSINFO
453
454 public:
455 nsXPCComponents_Classes();
456
457 private:
458 virtual ~nsXPCComponents_Classes();
459 };
460
461 /***************************************************************************/
462 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)463 nsXPCComponents_Classes::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
464 *aCount = 2;
465 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
466 *aArray = array;
467
468 array[0] = NS_GET_IID(nsIXPCComponents_Classes).Clone();
469 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
470 return NS_OK;
471 }
472
473 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)474 nsXPCComponents_Classes::GetScriptableHelper(nsIXPCScriptable** retval) {
475 *retval = nullptr;
476 return NS_OK;
477 }
478
479 NS_IMETHODIMP
GetContractID(nsACString & aContractID)480 nsXPCComponents_Classes::GetContractID(nsACString& aContractID) {
481 aContractID.SetIsVoid(true);
482 return NS_ERROR_NOT_AVAILABLE;
483 }
484
485 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)486 nsXPCComponents_Classes::GetClassDescription(nsACString& aClassDescription) {
487 aClassDescription.AssignLiteral("XPCComponents_Classes");
488 return NS_OK;
489 }
490
491 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)492 nsXPCComponents_Classes::GetClassID(nsCID** aClassID) {
493 *aClassID = nullptr;
494 return NS_OK;
495 }
496
497 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)498 nsXPCComponents_Classes::GetFlags(uint32_t* aFlags) {
499 *aFlags = 0;
500 return NS_OK;
501 }
502
503 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)504 nsXPCComponents_Classes::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
505 return NS_ERROR_NOT_AVAILABLE;
506 }
507
nsXPCComponents_Classes()508 nsXPCComponents_Classes::nsXPCComponents_Classes() {}
509
~nsXPCComponents_Classes()510 nsXPCComponents_Classes::~nsXPCComponents_Classes() {
511 // empty
512 }
513
NS_IMPL_ISUPPORTS(nsXPCComponents_Classes,nsIXPCComponents_Classes,nsIXPCScriptable,nsIClassInfo)514 NS_IMPL_ISUPPORTS(nsXPCComponents_Classes, nsIXPCComponents_Classes,
515 nsIXPCScriptable, nsIClassInfo)
516
517 // The nsIXPCScriptable map declaration that will generate stubs for us...
518 #define XPC_MAP_CLASSNAME nsXPCComponents_Classes
519 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Classes"
520 #define XPC_MAP_FLAGS \
521 (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
522 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
523 #include "xpc_map_end.h" /* This will #undef the above */
524
525 NS_IMETHODIMP
526 nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
527 JSContext* cx, JSObject* obj,
528 JS::AutoIdVector& properties,
529 bool* _retval) {
530 nsCOMPtr<nsIComponentRegistrar> compMgr;
531 if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr)
532 return NS_ERROR_UNEXPECTED;
533
534 nsCOMPtr<nsISimpleEnumerator> e;
535 if (NS_FAILED(compMgr->EnumerateContractIDs(getter_AddRefs(e))) || !e)
536 return NS_ERROR_UNEXPECTED;
537
538 bool hasMore;
539 nsCOMPtr<nsISupports> isup;
540 while (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
541 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
542 nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
543 if (!holder) continue;
544
545 nsAutoCString name;
546 if (NS_SUCCEEDED(holder->GetData(name))) {
547 RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
548 if (!idstr) {
549 *_retval = false;
550 return NS_OK;
551 }
552
553 RootedId id(cx);
554 if (!JS_StringToId(cx, idstr, &id)) {
555 *_retval = false;
556 return NS_OK;
557 }
558
559 if (!properties.append(id)) {
560 *_retval = false;
561 return NS_OK;
562 }
563 }
564 }
565
566 return NS_OK;
567 }
568
569 NS_IMETHODIMP
Resolve(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,jsid idArg,bool * resolvedp,bool * _retval)570 nsXPCComponents_Classes::Resolve(nsIXPConnectWrappedNative* wrapper,
571 JSContext* cx, JSObject* objArg, jsid idArg,
572 bool* resolvedp, bool* _retval)
573
574 {
575 RootedId id(cx, idArg);
576 RootedObject obj(cx, objArg);
577
578 JSAutoByteString name;
579 if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id)) &&
580 name.ptr()[0] != '{') { // we only allow contractids here
581 nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
582 if (nsid) {
583 nsXPConnect* xpc = nsXPConnect::XPConnect();
584 RootedObject idobj(cx);
585 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, static_cast<nsIJSCID*>(nsid),
586 NS_GET_IID(nsIJSCID),
587 idobj.address()))) {
588 if (idobj) {
589 *resolvedp = true;
590 *_retval =
591 JS_DefinePropertyById(cx, obj, id, idobj,
592 JSPROP_ENUMERATE | JSPROP_READONLY |
593 JSPROP_PERMANENT | JSPROP_RESOLVING);
594 }
595 }
596 }
597 }
598 return NS_OK;
599 }
600
601 NS_IMETHODIMP
Initialize(nsIJSCID * cid,const char * str)602 nsXPCComponents_Classes::Initialize(nsIJSCID* cid, const char* str) {
603 return cid->Initialize(str);
604 }
605
606 /***************************************************************************/
607 /***************************************************************************/
608 /***************************************************************************/
609
610 class nsXPCComponents_ClassesByID final : public nsIXPCComponents_ClassesByID,
611 public nsIXPCScriptable,
612 public nsIClassInfo {
613 public:
614 // all the interface method declarations...
615 NS_DECL_ISUPPORTS
616 NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID
617 NS_DECL_NSIXPCSCRIPTABLE
618 NS_DECL_NSICLASSINFO
619
620 public:
621 nsXPCComponents_ClassesByID();
622
623 private:
624 virtual ~nsXPCComponents_ClassesByID();
625 };
626
627 /***************************************************************************/
628 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)629 nsXPCComponents_ClassesByID::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
630 *aCount = 2;
631 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
632 *aArray = array;
633
634 array[0] = NS_GET_IID(nsIXPCComponents_ClassesByID).Clone();
635 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
636 return NS_OK;
637 }
638
639 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)640 nsXPCComponents_ClassesByID::GetScriptableHelper(nsIXPCScriptable** retval) {
641 *retval = nullptr;
642 return NS_OK;
643 }
644
645 NS_IMETHODIMP
GetContractID(nsACString & aContractID)646 nsXPCComponents_ClassesByID::GetContractID(nsACString& aContractID) {
647 aContractID.SetIsVoid(true);
648 return NS_ERROR_NOT_AVAILABLE;
649 }
650
651 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)652 nsXPCComponents_ClassesByID::GetClassDescription(
653 nsACString& aClassDescription) {
654 aClassDescription.AssignLiteral("XPCComponents_ClassesByID");
655 return NS_OK;
656 }
657
658 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)659 nsXPCComponents_ClassesByID::GetClassID(nsCID** aClassID) {
660 *aClassID = nullptr;
661 return NS_OK;
662 }
663
664 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)665 nsXPCComponents_ClassesByID::GetFlags(uint32_t* aFlags) {
666 *aFlags = 0;
667 return NS_OK;
668 }
669
670 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)671 nsXPCComponents_ClassesByID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
672 return NS_ERROR_NOT_AVAILABLE;
673 }
674
nsXPCComponents_ClassesByID()675 nsXPCComponents_ClassesByID::nsXPCComponents_ClassesByID() {}
676
~nsXPCComponents_ClassesByID()677 nsXPCComponents_ClassesByID::~nsXPCComponents_ClassesByID() {
678 // empty
679 }
680
NS_IMPL_ISUPPORTS(nsXPCComponents_ClassesByID,nsIXPCComponents_ClassesByID,nsIXPCScriptable,nsIClassInfo)681 NS_IMPL_ISUPPORTS(nsXPCComponents_ClassesByID, nsIXPCComponents_ClassesByID,
682 nsIXPCScriptable, nsIClassInfo)
683
684 // The nsIXPCScriptable map declaration that will generate stubs for us...
685 #define XPC_MAP_CLASSNAME nsXPCComponents_ClassesByID
686 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ClassesByID"
687 #define XPC_MAP_FLAGS \
688 (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
689 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
690 #include "xpc_map_end.h" /* This will #undef the above */
691
692 NS_IMETHODIMP
693 nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
694 JSContext* cx, JSObject* obj,
695 JS::AutoIdVector& properties,
696 bool* _retval) {
697 nsCOMPtr<nsIComponentRegistrar> compMgr;
698 if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr)
699 return NS_ERROR_UNEXPECTED;
700
701 nsISimpleEnumerator* e;
702 if (NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e) return NS_ERROR_UNEXPECTED;
703
704 bool hasMore;
705 nsCOMPtr<nsISupports> isup;
706 while (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
707 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
708 nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
709 if (!holder) continue;
710
711 char* name;
712 if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
713 RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
714 if (!idstr) {
715 *_retval = false;
716 return NS_OK;
717 }
718
719 RootedId id(cx);
720 if (!JS_StringToId(cx, idstr, &id)) {
721 *_retval = false;
722 return NS_OK;
723 }
724
725 if (!properties.append(id)) {
726 *_retval = false;
727 return NS_OK;
728 }
729 }
730 }
731
732 return NS_OK;
733 }
734
IsRegisteredCLSID(const char * str)735 static bool IsRegisteredCLSID(const char* str) {
736 bool registered;
737 nsID id;
738
739 if (!id.Parse(str)) return false;
740
741 nsCOMPtr<nsIComponentRegistrar> compMgr;
742 if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) ||
743 !compMgr || NS_FAILED(compMgr->IsCIDRegistered(id, ®istered)))
744 return false;
745
746 return registered;
747 }
748
749 NS_IMETHODIMP
Resolve(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,jsid idArg,bool * resolvedp,bool * _retval)750 nsXPCComponents_ClassesByID::Resolve(nsIXPConnectWrappedNative* wrapper,
751 JSContext* cx, JSObject* objArg,
752 jsid idArg, bool* resolvedp,
753 bool* _retval) {
754 RootedObject obj(cx, objArg);
755 RootedId id(cx, idArg);
756
757 if (!JSID_IS_STRING(id)) return NS_OK;
758
759 JSAutoByteString name;
760 RootedString str(cx, JSID_TO_STRING(id));
761 if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' &&
762 IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
763 {
764 nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
765 if (nsid) {
766 nsXPConnect* xpc = nsXPConnect::XPConnect();
767 RootedObject idobj(cx);
768 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj, static_cast<nsIJSCID*>(nsid),
769 NS_GET_IID(nsIJSCID),
770 idobj.address()))) {
771 if (idobj) {
772 *resolvedp = true;
773 *_retval =
774 JS_DefinePropertyById(cx, obj, id, idobj,
775 JSPROP_ENUMERATE | JSPROP_READONLY |
776 JSPROP_PERMANENT | JSPROP_RESOLVING);
777 }
778 }
779 }
780 }
781 return NS_OK;
782 }
783
784 /***************************************************************************/
785
786 // Currently the possible results do not change at runtime, so they are only
787 // cached once (unlike ContractIDs, CLSIDs, and IIDs)
788
789 class nsXPCComponents_Results final : public nsIXPCComponents_Results,
790 public nsIXPCScriptable,
791 public nsIClassInfo {
792 public:
793 // all the interface method declarations...
794 NS_DECL_ISUPPORTS
795 NS_DECL_NSIXPCCOMPONENTS_RESULTS
796 NS_DECL_NSIXPCSCRIPTABLE
797 NS_DECL_NSICLASSINFO
798
799 public:
800 nsXPCComponents_Results();
801
802 private:
803 virtual ~nsXPCComponents_Results();
804 };
805
806 /***************************************************************************/
807 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)808 nsXPCComponents_Results::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
809 *aCount = 2;
810 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
811 *aArray = array;
812
813 array[0] = NS_GET_IID(nsIXPCComponents_Results).Clone();
814 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
815 return NS_OK;
816 }
817
818 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)819 nsXPCComponents_Results::GetScriptableHelper(nsIXPCScriptable** retval) {
820 *retval = nullptr;
821 return NS_OK;
822 }
823
824 NS_IMETHODIMP
GetContractID(nsACString & aContractID)825 nsXPCComponents_Results::GetContractID(nsACString& aContractID) {
826 aContractID.SetIsVoid(true);
827 return NS_ERROR_NOT_AVAILABLE;
828 }
829
830 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)831 nsXPCComponents_Results::GetClassDescription(nsACString& aClassDescription) {
832 aClassDescription.AssignLiteral("XPCComponents_Results");
833 return NS_OK;
834 }
835
836 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)837 nsXPCComponents_Results::GetClassID(nsCID** aClassID) {
838 *aClassID = nullptr;
839 return NS_OK;
840 }
841
842 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)843 nsXPCComponents_Results::GetFlags(uint32_t* aFlags) {
844 // Mark ourselves as a DOM object so that instances may be created in
845 // unprivileged scopes.
846 *aFlags = nsIClassInfo::DOM_OBJECT;
847 return NS_OK;
848 }
849
850 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)851 nsXPCComponents_Results::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
852 return NS_ERROR_NOT_AVAILABLE;
853 }
854
nsXPCComponents_Results()855 nsXPCComponents_Results::nsXPCComponents_Results() {}
856
~nsXPCComponents_Results()857 nsXPCComponents_Results::~nsXPCComponents_Results() {
858 // empty
859 }
860
NS_IMPL_ISUPPORTS(nsXPCComponents_Results,nsIXPCComponents_Results,nsIXPCScriptable,nsIClassInfo)861 NS_IMPL_ISUPPORTS(nsXPCComponents_Results, nsIXPCComponents_Results,
862 nsIXPCScriptable, nsIClassInfo)
863
864 // The nsIXPCScriptable map declaration that will generate stubs for us...
865 #define XPC_MAP_CLASSNAME nsXPCComponents_Results
866 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Results"
867 #define XPC_MAP_FLAGS \
868 (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
869 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
870 #include "xpc_map_end.h" /* This will #undef the above */
871
872 NS_IMETHODIMP
873 nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative* wrapper,
874 JSContext* cx, JSObject* obj,
875 JS::AutoIdVector& properties,
876 bool* _retval) {
877 const char* name;
878 const void* iter = nullptr;
879 while (nsXPCException::IterateNSResults(nullptr, &name, nullptr, &iter)) {
880 RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
881 if (!idstr) {
882 *_retval = false;
883 return NS_OK;
884 }
885
886 RootedId id(cx);
887 if (!JS_StringToId(cx, idstr, &id)) {
888 *_retval = false;
889 return NS_OK;
890 }
891
892 if (!properties.append(id)) {
893 *_retval = false;
894 return NS_OK;
895 }
896 }
897
898 return NS_OK;
899 }
900
901 NS_IMETHODIMP
Resolve(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,jsid idArg,bool * resolvedp,bool * _retval)902 nsXPCComponents_Results::Resolve(nsIXPConnectWrappedNative* wrapper,
903 JSContext* cx, JSObject* objArg, jsid idArg,
904 bool* resolvedp, bool* _retval) {
905 RootedObject obj(cx, objArg);
906 RootedId id(cx, idArg);
907 JSAutoByteString name;
908
909 if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) {
910 const char* rv_name;
911 const void* iter = nullptr;
912 nsresult rv;
913 while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) {
914 if (!strcmp(name.ptr(), rv_name)) {
915 *resolvedp = true;
916 if (!JS_DefinePropertyById(cx, obj, id, (uint32_t)rv,
917 JSPROP_ENUMERATE | JSPROP_READONLY |
918 JSPROP_PERMANENT | JSPROP_RESOLVING)) {
919 return NS_ERROR_UNEXPECTED;
920 }
921 }
922 }
923 }
924 return NS_OK;
925 }
926
927 /***************************************************************************/
928 // JavaScript Constructor for nsIJSID objects (Components.ID)
929
930 class nsXPCComponents_ID final : public nsIXPCComponents_ID,
931 public nsIXPCScriptable,
932 public nsIClassInfo {
933 public:
934 // all the interface method declarations...
935 NS_DECL_ISUPPORTS
936 NS_DECL_NSIXPCCOMPONENTS_ID
937 NS_DECL_NSIXPCSCRIPTABLE
938 NS_DECL_NSICLASSINFO
939
940 public:
941 nsXPCComponents_ID();
942
943 private:
944 virtual ~nsXPCComponents_ID();
945 static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
946 JSContext* cx, HandleObject obj,
947 const CallArgs& args, bool* _retval);
948 };
949
950 /***************************************************************************/
951 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)952 nsXPCComponents_ID::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
953 *aCount = 2;
954 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
955 *aArray = array;
956
957 array[0] = NS_GET_IID(nsIXPCComponents_ID).Clone();
958 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
959 return NS_OK;
960 }
961
962 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)963 nsXPCComponents_ID::GetScriptableHelper(nsIXPCScriptable** retval) {
964 *retval = nullptr;
965 return NS_OK;
966 }
967
968 NS_IMETHODIMP
GetContractID(nsACString & aContractID)969 nsXPCComponents_ID::GetContractID(nsACString& aContractID) {
970 aContractID.SetIsVoid(true);
971 return NS_ERROR_NOT_AVAILABLE;
972 }
973
974 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)975 nsXPCComponents_ID::GetClassDescription(nsACString& aClassDescription) {
976 aClassDescription.AssignLiteral("XPCComponents_ID");
977 return NS_OK;
978 }
979
980 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)981 nsXPCComponents_ID::GetClassID(nsCID** aClassID) {
982 *aClassID = nullptr;
983 return NS_OK;
984 }
985
986 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)987 nsXPCComponents_ID::GetFlags(uint32_t* aFlags) {
988 *aFlags = 0;
989 return NS_OK;
990 }
991
992 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)993 nsXPCComponents_ID::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
994 return NS_ERROR_NOT_AVAILABLE;
995 }
996
nsXPCComponents_ID()997 nsXPCComponents_ID::nsXPCComponents_ID() {}
998
~nsXPCComponents_ID()999 nsXPCComponents_ID::~nsXPCComponents_ID() {
1000 // empty
1001 }
1002
NS_IMPL_ISUPPORTS(nsXPCComponents_ID,nsIXPCComponents_ID,nsIXPCScriptable,nsIClassInfo)1003 NS_IMPL_ISUPPORTS(nsXPCComponents_ID, nsIXPCComponents_ID, nsIXPCScriptable,
1004 nsIClassInfo)
1005
1006 // The nsIXPCScriptable map declaration that will generate stubs for us...
1007 #define XPC_MAP_CLASSNAME nsXPCComponents_ID
1008 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ID"
1009 #define XPC_MAP_FLAGS \
1010 (XPC_SCRIPTABLE_WANT_CALL | XPC_SCRIPTABLE_WANT_CONSTRUCT | \
1011 XPC_SCRIPTABLE_WANT_HASINSTANCE | \
1012 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
1013 #include "xpc_map_end.h" /* This will #undef the above */
1014
1015 NS_IMETHODIMP
1016 nsXPCComponents_ID::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
1017 JSObject* objArg, const CallArgs& args,
1018 bool* _retval) {
1019 RootedObject obj(cx, objArg);
1020 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1021 }
1022
1023 NS_IMETHODIMP
Construct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,const CallArgs & args,bool * _retval)1024 nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
1025 JSObject* objArg, const CallArgs& args,
1026 bool* _retval) {
1027 RootedObject obj(cx, objArg);
1028 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1029 }
1030
1031 // static
CallOrConstruct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,HandleObject obj,const CallArgs & args,bool * _retval)1032 nsresult nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
1033 JSContext* cx, HandleObject obj,
1034 const CallArgs& args,
1035 bool* _retval) {
1036 // make sure we have at least one arg
1037
1038 if (args.length() < 1)
1039 return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
1040
1041 // Do the security check if necessary
1042
1043 if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(
1044 cx, nsJSID::GetCID()))) {
1045 // the security manager vetoed. It should have set an exception.
1046 *_retval = false;
1047 return NS_OK;
1048 }
1049
1050 // convert the first argument into a string and see if it looks like an id
1051
1052 JSString* jsstr;
1053 JSAutoByteString bytes;
1054 nsID id;
1055
1056 if (!(jsstr = ToString(cx, args[0])) || !bytes.encodeLatin1(cx, jsstr) ||
1057 !id.Parse(bytes.ptr())) {
1058 return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
1059 }
1060
1061 // make the new object and return it.
1062
1063 JSObject* newobj = xpc_NewIDObject(cx, obj, id);
1064 if (!newobj) return NS_ERROR_UNEXPECTED;
1065
1066 args.rval().setObject(*newobj);
1067 return NS_OK;
1068 }
1069
1070 NS_IMETHODIMP
HasInstance(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * obj,HandleValue val,bool * bp,bool * _retval)1071 nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative* wrapper,
1072 JSContext* cx, JSObject* obj, HandleValue val,
1073 bool* bp, bool* _retval) {
1074 if (bp) *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIJSID));
1075 return NS_OK;
1076 }
1077
1078 /***************************************************************************/
1079 // JavaScript Constructor for Exception objects (Components.Exception)
1080
1081 class nsXPCComponents_Exception final : public nsIXPCComponents_Exception,
1082 public nsIXPCScriptable,
1083 public nsIClassInfo {
1084 public:
1085 // all the interface method declarations...
1086 NS_DECL_ISUPPORTS
1087 NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
1088 NS_DECL_NSIXPCSCRIPTABLE
1089 NS_DECL_NSICLASSINFO
1090
1091 public:
1092 nsXPCComponents_Exception();
1093
1094 private:
1095 virtual ~nsXPCComponents_Exception();
1096 static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
1097 JSContext* cx, HandleObject obj,
1098 const CallArgs& args, bool* _retval);
1099 };
1100
1101 /***************************************************************************/
1102 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)1103 nsXPCComponents_Exception::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
1104 *aCount = 2;
1105 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
1106 *aArray = array;
1107
1108 array[0] = NS_GET_IID(nsIXPCComponents_Exception).Clone();
1109 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
1110 return NS_OK;
1111 }
1112
1113 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)1114 nsXPCComponents_Exception::GetScriptableHelper(nsIXPCScriptable** retval) {
1115 *retval = nullptr;
1116 return NS_OK;
1117 }
1118
1119 NS_IMETHODIMP
GetContractID(nsACString & aContractID)1120 nsXPCComponents_Exception::GetContractID(nsACString& aContractID) {
1121 aContractID.SetIsVoid(true);
1122 return NS_ERROR_NOT_AVAILABLE;
1123 }
1124
1125 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)1126 nsXPCComponents_Exception::GetClassDescription(nsACString& aClassDescription) {
1127 aClassDescription.AssignLiteral("XPCComponents_Exception");
1128 return NS_OK;
1129 }
1130
1131 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)1132 nsXPCComponents_Exception::GetClassID(nsCID** aClassID) {
1133 *aClassID = nullptr;
1134 return NS_OK;
1135 }
1136
1137 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)1138 nsXPCComponents_Exception::GetFlags(uint32_t* aFlags) {
1139 *aFlags = 0;
1140 return NS_OK;
1141 }
1142
1143 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)1144 nsXPCComponents_Exception::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
1145 return NS_ERROR_NOT_AVAILABLE;
1146 }
1147
nsXPCComponents_Exception()1148 nsXPCComponents_Exception::nsXPCComponents_Exception() {}
1149
~nsXPCComponents_Exception()1150 nsXPCComponents_Exception::~nsXPCComponents_Exception() {
1151 // empty
1152 }
1153
NS_IMPL_ISUPPORTS(nsXPCComponents_Exception,nsIXPCComponents_Exception,nsIXPCScriptable,nsIClassInfo)1154 NS_IMPL_ISUPPORTS(nsXPCComponents_Exception, nsIXPCComponents_Exception,
1155 nsIXPCScriptable, nsIClassInfo)
1156
1157 // The nsIXPCScriptable map declaration that will generate stubs for us...
1158 #define XPC_MAP_CLASSNAME nsXPCComponents_Exception
1159 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Exception"
1160 #define XPC_MAP_FLAGS \
1161 (XPC_SCRIPTABLE_WANT_CALL | XPC_SCRIPTABLE_WANT_CONSTRUCT | \
1162 XPC_SCRIPTABLE_WANT_HASINSTANCE | \
1163 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
1164 #include "xpc_map_end.h" /* This will #undef the above */
1165
1166 NS_IMETHODIMP
1167 nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative* wrapper,
1168 JSContext* cx, JSObject* objArg,
1169 const CallArgs& args, bool* _retval) {
1170 RootedObject obj(cx, objArg);
1171 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1172 }
1173
1174 NS_IMETHODIMP
Construct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,const CallArgs & args,bool * _retval)1175 nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative* wrapper,
1176 JSContext* cx, JSObject* objArg,
1177 const CallArgs& args, bool* _retval) {
1178 RootedObject obj(cx, objArg);
1179 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1180 }
1181
1182 struct MOZ_STACK_CLASS ExceptionArgParser {
ExceptionArgParserExceptionArgParser1183 ExceptionArgParser(JSContext* context, nsXPConnect* xpconnect)
1184 : eMsg("exception"),
1185 eResult(NS_ERROR_FAILURE),
1186 cx(context),
1187 xpc(xpconnect) {}
1188
1189 // Public exception parameter values. During construction, these are
1190 // initialized to the appropriate defaults.
1191 const char* eMsg;
1192 nsresult eResult;
1193 nsCOMPtr<nsIStackFrame> eStack;
1194 nsCOMPtr<nsISupports> eData;
1195
1196 // Parse the constructor arguments into the above |eFoo| parameter values.
parseExceptionArgParser1197 bool parse(const CallArgs& args) {
1198 /*
1199 * The Components.Exception takes a series of arguments, all of them
1200 * optional:
1201 *
1202 * Argument 0: Exception message (defaults to 'exception').
1203 * Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options
1204 * object (see below).
1205 * Argument 2: Stack (defaults to the current stack, which we trigger
1206 * by leaving this nullptr in the parser).
1207 * Argument 3: Optional user data (defaults to nullptr).
1208 *
1209 * To dig our way out of this clunky API, we now support passing an
1210 * options object as the second parameter (as opposed to a result code).
1211 * If this is the case, all subsequent arguments are ignored, and the
1212 * following properties are parsed out of the object (using the
1213 * associated default if the property does not exist):
1214 *
1215 * result: Result code (see argument 1).
1216 * stack: Call stack (see argument 2).
1217 * data: User data (see argument 3).
1218 */
1219 if (args.length() > 0 && !parseMessage(args[0])) return false;
1220 if (args.length() > 1) {
1221 if (args[1].isObject()) {
1222 RootedObject obj(cx, &args[1].toObject());
1223 return parseOptionsObject(obj);
1224 }
1225 if (!parseResult(args[1])) return false;
1226 }
1227 if (args.length() > 2) {
1228 if (!parseStack(args[2])) return false;
1229 }
1230 if (args.length() > 3) {
1231 if (!parseData(args[3])) return false;
1232 }
1233 return true;
1234 }
1235
1236 protected:
1237 /*
1238 * Parsing helpers.
1239 */
1240
parseMessageExceptionArgParser1241 bool parseMessage(HandleValue v) {
1242 JSString* str = ToString(cx, v);
1243 if (!str) return false;
1244 eMsg = messageBytes.encodeLatin1(cx, str);
1245 return !!eMsg;
1246 }
1247
parseResultExceptionArgParser1248 bool parseResult(HandleValue v) {
1249 return JS::ToUint32(cx, v, (uint32_t*)&eResult);
1250 }
1251
parseStackExceptionArgParser1252 bool parseStack(HandleValue v) {
1253 if (!v.isObject()) {
1254 // eStack has already been initialized to null, which is what we want
1255 // for any non-object values (including null).
1256 return true;
1257 }
1258
1259 return NS_SUCCEEDED(xpc->WrapJS(
1260 cx, &v.toObject(), NS_GET_IID(nsIStackFrame), getter_AddRefs(eStack)));
1261 }
1262
parseDataExceptionArgParser1263 bool parseData(HandleValue v) {
1264 if (!v.isObject()) {
1265 // eData has already been initialized to null, which is what we want
1266 // for any non-object values (including null).
1267 return true;
1268 }
1269
1270 return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(), NS_GET_IID(nsISupports),
1271 getter_AddRefs(eData)));
1272 }
1273
parseOptionsObjectExceptionArgParser1274 bool parseOptionsObject(HandleObject obj) {
1275 RootedValue v(cx);
1276
1277 if (!getOption(obj, "result", &v) || (!v.isUndefined() && !parseResult(v)))
1278 return false;
1279
1280 if (!getOption(obj, "stack", &v) || (!v.isUndefined() && !parseStack(v)))
1281 return false;
1282
1283 if (!getOption(obj, "data", &v) || (!v.isUndefined() && !parseData(v)))
1284 return false;
1285
1286 return true;
1287 }
1288
getOptionExceptionArgParser1289 bool getOption(HandleObject obj, const char* name, MutableHandleValue rv) {
1290 // Look for the property.
1291 bool found;
1292 if (!JS_HasProperty(cx, obj, name, &found)) return false;
1293
1294 // If it wasn't found, indicate with undefined.
1295 if (!found) {
1296 rv.setUndefined();
1297 return true;
1298 }
1299
1300 // Get the property.
1301 return JS_GetProperty(cx, obj, name, rv);
1302 }
1303
1304 /*
1305 * Internal data members.
1306 */
1307
1308 // If there's a non-default exception string, hold onto the allocated bytes.
1309 JSAutoByteString messageBytes;
1310
1311 // Various bits and pieces that are helpful to have around.
1312 JSContext* cx;
1313 nsXPConnect* xpc;
1314 };
1315
1316 // static
CallOrConstruct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,HandleObject obj,const CallArgs & args,bool * _retval)1317 nsresult nsXPCComponents_Exception::CallOrConstruct(
1318 nsIXPConnectWrappedNative* wrapper, JSContext* cx, HandleObject obj,
1319 const CallArgs& args, bool* _retval) {
1320 nsXPConnect* xpc = nsXPConnect::XPConnect();
1321
1322 MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsCallerChrome());
1323
1324 // Parse the arguments to the Exception constructor.
1325 ExceptionArgParser parser(cx, xpc);
1326 if (!parser.parse(args))
1327 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
1328
1329 RefPtr<Exception> e =
1330 new Exception(nsCString(parser.eMsg), parser.eResult, EmptyCString(),
1331 parser.eStack, parser.eData);
1332
1333 RootedObject newObj(cx);
1334 if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIException),
1335 newObj.address())) ||
1336 !newObj) {
1337 return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
1338 }
1339
1340 args.rval().setObject(*newObj);
1341 return NS_OK;
1342 }
1343
1344 NS_IMETHODIMP
HasInstance(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * obj,HandleValue val,bool * bp,bool * _retval)1345 nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative* wrapper,
1346 JSContext* cx, JSObject* obj,
1347 HandleValue val, bool* bp,
1348 bool* _retval) {
1349 using namespace mozilla::dom;
1350
1351 if (bp) {
1352 *bp = (val.isObject() && IS_INSTANCE_OF(Exception, &val.toObject())) ||
1353 JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIException));
1354 }
1355 return NS_OK;
1356 }
1357
1358 /***************************************************************************/
1359 // This class is for the thing returned by "new Component.Constructor".
1360
1361 // XXXjband we use this CID for security check, but security system can't see
1362 // it since it has no registed factory. Security really kicks in when we try
1363 // to build a wrapper around an instance.
1364
1365 // {B4A95150-E25A-11d3-8F61-0010A4E73D9A}
1366 #define NS_XPCCONSTRUCTOR_CID \
1367 { \
1368 0xb4a95150, 0xe25a, 0x11d3, { \
1369 0x8f, 0x61, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a \
1370 } \
1371 }
1372
1373 class nsXPCConstructor : public nsIXPCConstructor,
1374 public nsIXPCScriptable,
1375 public nsIClassInfo {
1376 public:
1377 NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID)
1378 public:
1379 // all the interface method declarations...
1380 NS_DECL_ISUPPORTS
1381 NS_DECL_NSIXPCCONSTRUCTOR
1382 NS_DECL_NSIXPCSCRIPTABLE
1383 NS_DECL_NSICLASSINFO
1384
1385 public:
1386 nsXPCConstructor() = delete;
1387 nsXPCConstructor(nsIJSCID* aClassID, nsIJSIID* aInterfaceID,
1388 const char* aInitializer);
1389
1390 private:
1391 virtual ~nsXPCConstructor();
1392 nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
1393 HandleObject obj, const CallArgs& args,
1394 bool* _retval);
1395
1396 private:
1397 RefPtr<nsIJSCID> mClassID;
1398 RefPtr<nsIJSIID> mInterfaceID;
1399 char* mInitializer;
1400 };
1401
1402 /***************************************************************************/
1403 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)1404 nsXPCConstructor::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
1405 *aCount = 2;
1406 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
1407 *aArray = array;
1408
1409 array[0] = NS_GET_IID(nsIXPCConstructor).Clone();
1410 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
1411 return NS_OK;
1412 }
1413
1414 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)1415 nsXPCConstructor::GetScriptableHelper(nsIXPCScriptable** retval) {
1416 *retval = nullptr;
1417 return NS_OK;
1418 }
1419
1420 NS_IMETHODIMP
GetContractID(nsACString & aContractID)1421 nsXPCConstructor::GetContractID(nsACString& aContractID) {
1422 aContractID.SetIsVoid(true);
1423 return NS_ERROR_NOT_AVAILABLE;
1424 }
1425
1426 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)1427 nsXPCConstructor::GetClassDescription(nsACString& aClassDescription) {
1428 aClassDescription.AssignLiteral("XPCConstructor");
1429 return NS_OK;
1430 }
1431
1432 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)1433 nsXPCConstructor::GetClassID(nsCID** aClassID) {
1434 *aClassID = nullptr;
1435 return NS_OK;
1436 }
1437
1438 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)1439 nsXPCConstructor::GetFlags(uint32_t* aFlags) {
1440 *aFlags = 0;
1441 return NS_OK;
1442 }
1443
1444 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)1445 nsXPCConstructor::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
1446 return NS_ERROR_NOT_AVAILABLE;
1447 }
1448
nsXPCConstructor(nsIJSCID * aClassID,nsIJSIID * aInterfaceID,const char * aInitializer)1449 nsXPCConstructor::nsXPCConstructor(nsIJSCID* aClassID, nsIJSIID* aInterfaceID,
1450 const char* aInitializer)
1451 : mClassID(aClassID), mInterfaceID(aInterfaceID) {
1452 mInitializer = aInitializer ? moz_xstrdup(aInitializer) : nullptr;
1453 }
1454
~nsXPCConstructor()1455 nsXPCConstructor::~nsXPCConstructor() {
1456 if (mInitializer) free(mInitializer);
1457 }
1458
1459 NS_IMETHODIMP
GetClassID(nsIJSCID ** aClassID)1460 nsXPCConstructor::GetClassID(nsIJSCID** aClassID) {
1461 RefPtr<nsIJSCID> rval = mClassID;
1462 rval.forget(aClassID);
1463 return NS_OK;
1464 }
1465
1466 NS_IMETHODIMP
GetInterfaceID(nsIJSIID ** aInterfaceID)1467 nsXPCConstructor::GetInterfaceID(nsIJSIID** aInterfaceID) {
1468 RefPtr<nsIJSIID> rval = mInterfaceID;
1469 rval.forget(aInterfaceID);
1470 return NS_OK;
1471 }
1472
1473 NS_IMETHODIMP
GetInitializer(char ** aInitializer)1474 nsXPCConstructor::GetInitializer(char** aInitializer) {
1475 XPC_STRING_GETTER_BODY(aInitializer, mInitializer);
1476 }
1477
NS_IMPL_ISUPPORTS(nsXPCConstructor,nsIXPCConstructor,nsIXPCScriptable,nsIClassInfo)1478 NS_IMPL_ISUPPORTS(nsXPCConstructor, nsIXPCConstructor, nsIXPCScriptable,
1479 nsIClassInfo)
1480
1481 // The nsIXPCScriptable map declaration that will generate stubs for us...
1482 #define XPC_MAP_CLASSNAME nsXPCConstructor
1483 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCConstructor"
1484 #define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_CALL | XPC_SCRIPTABLE_WANT_CONSTRUCT)
1485 #include "xpc_map_end.h" /* This will #undef the above */
1486
1487 NS_IMETHODIMP
1488 nsXPCConstructor::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
1489 JSObject* objArg, const CallArgs& args, bool* _retval) {
1490 RootedObject obj(cx, objArg);
1491 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1492 }
1493
1494 NS_IMETHODIMP
Construct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,const CallArgs & args,bool * _retval)1495 nsXPCConstructor::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
1496 JSObject* objArg, const CallArgs& args,
1497 bool* _retval) {
1498 RootedObject obj(cx, objArg);
1499 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1500 }
1501
1502 // static
CallOrConstruct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,HandleObject obj,const CallArgs & args,bool * _retval)1503 nsresult nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
1504 JSContext* cx, HandleObject obj,
1505 const CallArgs& args,
1506 bool* _retval) {
1507 nsXPConnect* xpc = nsXPConnect::XPConnect();
1508
1509 // security check not required because we are going to call through the
1510 // code which is reflected into JS which will do that for us later.
1511
1512 RootedObject cidObj(cx);
1513 RootedObject iidObj(cx);
1514
1515 if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID),
1516 cidObj.address())) ||
1517 !cidObj ||
1518 NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID),
1519 iidObj.address())) ||
1520 !iidObj) {
1521 return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
1522 }
1523
1524 JS::Rooted<JS::Value> arg(cx, ObjectValue(*iidObj));
1525 RootedValue rval(cx);
1526 if (!JS_CallFunctionName(cx, cidObj, "createInstance",
1527 JS::HandleValueArray(arg), &rval) ||
1528 rval.isPrimitive()) {
1529 // createInstance will have thrown an exception
1530 *_retval = false;
1531 return NS_OK;
1532 }
1533
1534 args.rval().set(rval);
1535
1536 // call initializer method if supplied
1537 if (mInitializer) {
1538 RootedObject newObj(cx, &rval.toObject());
1539 // first check existence of function property for better error reporting
1540 RootedValue fun(cx);
1541 if (!JS_GetProperty(cx, newObj, mInitializer, &fun) || fun.isPrimitive()) {
1542 return ThrowAndFail(NS_ERROR_XPC_BAD_INITIALIZER_NAME, cx, _retval);
1543 }
1544
1545 RootedValue dummy(cx);
1546 if (!JS_CallFunctionValue(cx, newObj, fun, args, &dummy)) {
1547 // function should have thrown an exception
1548 *_retval = false;
1549 return NS_OK;
1550 }
1551 }
1552
1553 return NS_OK;
1554 }
1555
1556 /*******************************************************/
1557 // JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
1558
1559 class nsXPCComponents_Constructor final : public nsIXPCComponents_Constructor,
1560 public nsIXPCScriptable,
1561 public nsIClassInfo {
1562 public:
1563 // all the interface method declarations...
1564 NS_DECL_ISUPPORTS
1565 NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
1566 NS_DECL_NSIXPCSCRIPTABLE
1567 NS_DECL_NSICLASSINFO
1568
1569 public:
1570 nsXPCComponents_Constructor();
1571
1572 private:
1573 virtual ~nsXPCComponents_Constructor();
1574 static nsresult CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
1575 JSContext* cx, HandleObject obj,
1576 const CallArgs& args, bool* _retval);
1577 };
1578
1579 /***************************************************************************/
1580 NS_IMETHODIMP
GetInterfaces(uint32_t * aCount,nsIID *** aArray)1581 nsXPCComponents_Constructor::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
1582 *aCount = 2;
1583 nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
1584 *aArray = array;
1585
1586 array[0] = NS_GET_IID(nsIXPCComponents_Constructor).Clone();
1587 array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
1588 return NS_OK;
1589 }
1590
1591 NS_IMETHODIMP
GetScriptableHelper(nsIXPCScriptable ** retval)1592 nsXPCComponents_Constructor::GetScriptableHelper(nsIXPCScriptable** retval) {
1593 *retval = nullptr;
1594 return NS_OK;
1595 }
1596
1597 NS_IMETHODIMP
GetContractID(nsACString & aContractID)1598 nsXPCComponents_Constructor::GetContractID(nsACString& aContractID) {
1599 aContractID.SetIsVoid(true);
1600 return NS_ERROR_NOT_AVAILABLE;
1601 }
1602
1603 NS_IMETHODIMP
GetClassDescription(nsACString & aClassDescription)1604 nsXPCComponents_Constructor::GetClassDescription(
1605 nsACString& aClassDescription) {
1606 aClassDescription.AssignLiteral("XPCComponents_Constructor");
1607 return NS_OK;
1608 }
1609
1610 NS_IMETHODIMP
GetClassID(nsCID ** aClassID)1611 nsXPCComponents_Constructor::GetClassID(nsCID** aClassID) {
1612 *aClassID = nullptr;
1613 return NS_OK;
1614 }
1615
1616 NS_IMETHODIMP
GetFlags(uint32_t * aFlags)1617 nsXPCComponents_Constructor::GetFlags(uint32_t* aFlags) {
1618 *aFlags = 0;
1619 return NS_OK;
1620 }
1621
1622 NS_IMETHODIMP
GetClassIDNoAlloc(nsCID * aClassIDNoAlloc)1623 nsXPCComponents_Constructor::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
1624 return NS_ERROR_NOT_AVAILABLE;
1625 }
1626
nsXPCComponents_Constructor()1627 nsXPCComponents_Constructor::nsXPCComponents_Constructor() {}
1628
~nsXPCComponents_Constructor()1629 nsXPCComponents_Constructor::~nsXPCComponents_Constructor() {
1630 // empty
1631 }
1632
NS_IMPL_ISUPPORTS(nsXPCComponents_Constructor,nsIXPCComponents_Constructor,nsIXPCScriptable,nsIClassInfo)1633 NS_IMPL_ISUPPORTS(nsXPCComponents_Constructor, nsIXPCComponents_Constructor,
1634 nsIXPCScriptable, nsIClassInfo)
1635
1636 // The nsIXPCScriptable map declaration that will generate stubs for us...
1637 #define XPC_MAP_CLASSNAME nsXPCComponents_Constructor
1638 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Constructor"
1639 #define XPC_MAP_FLAGS \
1640 (XPC_SCRIPTABLE_WANT_CALL | XPC_SCRIPTABLE_WANT_CONSTRUCT | \
1641 XPC_SCRIPTABLE_WANT_HASINSTANCE | \
1642 XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
1643 #include "xpc_map_end.h" /* This will #undef the above */
1644
1645 NS_IMETHODIMP
1646 nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative* wrapper,
1647 JSContext* cx, JSObject* objArg,
1648 const CallArgs& args, bool* _retval) {
1649 RootedObject obj(cx, objArg);
1650 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1651 }
1652
1653 NS_IMETHODIMP
Construct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * objArg,const CallArgs & args,bool * _retval)1654 nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative* wrapper,
1655 JSContext* cx, JSObject* objArg,
1656 const CallArgs& args, bool* _retval) {
1657 RootedObject obj(cx, objArg);
1658 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1659 }
1660
1661 // static
CallOrConstruct(nsIXPConnectWrappedNative * wrapper,JSContext * cx,HandleObject obj,const CallArgs & args,bool * _retval)1662 nsresult nsXPCComponents_Constructor::CallOrConstruct(
1663 nsIXPConnectWrappedNative* wrapper, JSContext* cx, HandleObject obj,
1664 const CallArgs& args, bool* _retval) {
1665 // make sure we have at least one arg
1666
1667 if (args.length() < 1)
1668 return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
1669
1670 // get the various other object pointers we need
1671
1672 nsXPConnect* xpc = nsXPConnect::XPConnect();
1673 XPCWrappedNativeScope* scope = ObjectScope(obj);
1674 nsCOMPtr<nsIXPCComponents> comp;
1675
1676 if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents())))
1677 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
1678
1679 // Do the security check if necessary
1680
1681 if (NS_FAILED(nsXPConnect::SecurityManager()->CanCreateInstance(
1682 cx, nsXPCConstructor::GetCID()))) {
1683 // the security manager vetoed. It should have set an exception.
1684 *_retval = false;
1685 return NS_OK;
1686 }
1687
1688 // initialization params for the Constructor object we will create
1689 nsCOMPtr<nsIJSCID> cClassID;
1690 nsCOMPtr<nsIJSIID> cInterfaceID;
1691 const char* cInitializer = nullptr;
1692 JSAutoByteString cInitializerBytes;
1693
1694 if (args.length() >= 3) {
1695 // args[2] is an initializer function or property name
1696 RootedString str(cx, ToString(cx, args[2]));
1697 if (!str || !(cInitializer = cInitializerBytes.encodeLatin1(cx, str)))
1698 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
1699 }
1700
1701 if (args.length() >= 2) {
1702 // args[1] is an iid name string
1703 // XXXjband support passing "Components.interfaces.foo"?
1704
1705 nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
1706 RootedObject ifacesObj(cx);
1707
1708 // we do the lookup by asking the Components.interfaces object
1709 // for the property with this name - i.e. we let its caching of these
1710 // nsIJSIID objects work for us.
1711
1712 if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
1713 NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
1714 NS_GET_IID(nsIXPCComponents_Interfaces),
1715 ifacesObj.address())) ||
1716 !ifacesObj) {
1717 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
1718 }
1719
1720 RootedString str(cx, ToString(cx, args[1]));
1721 RootedId id(cx);
1722 if (!str || !JS_StringToId(cx, str, &id))
1723 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
1724
1725 RootedValue val(cx);
1726 if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive())
1727 return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
1728
1729 nsCOMPtr<nsIXPConnectWrappedNative> wn;
1730 if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(),
1731 getter_AddRefs(wn))) ||
1732 !wn || !(cInterfaceID = do_QueryWrappedNative(wn))) {
1733 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
1734 }
1735 } else {
1736 nsCOMPtr<nsIInterfaceInfo> info;
1737 xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info));
1738
1739 if (info) {
1740 cInterfaceID = nsJSIID::NewID(info);
1741 }
1742 if (!cInterfaceID)
1743 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
1744 }
1745
1746 // a new scope to avoid warnings about shadowed names
1747 {
1748 // argv[0] is a contractid name string
1749 // XXXjband support passing "Components.classes.foo"?
1750
1751 // we do the lookup by asking the Components.classes object
1752 // for the property with this name - i.e. we let its caching of these
1753 // nsIJSCID objects work for us.
1754
1755 nsCOMPtr<nsIXPCComponents_Classes> classes;
1756 RootedObject classesObj(cx);
1757
1758 if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
1759 NS_FAILED(xpc->WrapNative(cx, obj, classes,
1760 NS_GET_IID(nsIXPCComponents_Classes),
1761 classesObj.address())) ||
1762 !classesObj) {
1763 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
1764 }
1765
1766 RootedString str(cx, ToString(cx, args[0]));
1767 RootedId id(cx);
1768 if (!str || !JS_StringToId(cx, str, &id))
1769 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
1770
1771 RootedValue val(cx);
1772 if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive())
1773 return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
1774
1775 nsCOMPtr<nsIXPConnectWrappedNative> wn;
1776 if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, val.toObjectOrNull(),
1777 getter_AddRefs(wn))) ||
1778 !wn || !(cClassID = do_QueryWrappedNative(wn))) {
1779 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
1780 }
1781 }
1782
1783 nsCOMPtr<nsIXPCConstructor> ctor =
1784 new nsXPCConstructor(cClassID, cInterfaceID, cInitializer);
1785 RootedObject newObj(cx);
1786
1787 if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor),
1788 newObj.address())) ||
1789 !newObj) {
1790 return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
1791 }
1792
1793 args.rval().setObject(*newObj);
1794 return NS_OK;
1795 }
1796
1797 NS_IMETHODIMP
HasInstance(nsIXPConnectWrappedNative * wrapper,JSContext * cx,JSObject * obj,HandleValue val,bool * bp,bool * _retval)1798 nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative* wrapper,
1799 JSContext* cx, JSObject* obj,
1800 HandleValue val, bool* bp,
1801 bool* _retval) {
1802 if (bp) *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIXPCConstructor));
1803 return NS_OK;
1804 }
1805
1806 class nsXPCComponents_Utils final : public nsIXPCComponents_Utils,
1807 public nsIXPCScriptable {
1808 public:
1809 // all the interface method declarations...
1810 NS_DECL_ISUPPORTS
1811 NS_DECL_NSIXPCSCRIPTABLE
1812 NS_DECL_NSIXPCCOMPONENTS_UTILS
1813
1814 public:
nsXPCComponents_Utils()1815 nsXPCComponents_Utils() {}
1816
1817 private:
~nsXPCComponents_Utils()1818 virtual ~nsXPCComponents_Utils() {}
1819 nsCOMPtr<nsIXPCComponents_utils_Sandbox> mSandbox;
1820 };
1821
NS_IMPL_ISUPPORTS(nsXPCComponents_Utils,nsIXPCComponents_Utils,nsIXPCScriptable)1822 NS_IMPL_ISUPPORTS(nsXPCComponents_Utils, nsIXPCComponents_Utils,
1823 nsIXPCScriptable)
1824
1825 // The nsIXPCScriptable map declaration that will generate stubs for us...
1826 #define XPC_MAP_CLASSNAME nsXPCComponents_Utils
1827 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Utils"
1828 #define XPC_MAP_FLAGS XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE
1829 #include "xpc_map_end.h" /* This will #undef the above */
1830
1831 NS_IMETHODIMP
1832 nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox** aSandbox) {
1833 NS_ENSURE_ARG_POINTER(aSandbox);
1834 if (!mSandbox) mSandbox = NewSandboxConstructor();
1835
1836 nsCOMPtr<nsIXPCComponents_utils_Sandbox> rval = mSandbox;
1837 rval.forget(aSandbox);
1838 return NS_OK;
1839 }
1840
1841 NS_IMETHODIMP
ReportError(HandleValue error,HandleValue stack,JSContext * cx)1842 nsXPCComponents_Utils::ReportError(HandleValue error, HandleValue stack,
1843 JSContext* cx) {
1844 // This function shall never fail! Silently eat any failure conditions.
1845
1846 nsCOMPtr<nsIConsoleService> console(
1847 do_GetService(NS_CONSOLESERVICE_CONTRACTID));
1848 if (!console) return NS_OK;
1849
1850 nsGlobalWindowInner* globalWin = CurrentWindowOrNull(cx);
1851 nsPIDOMWindowInner* win = globalWin ? globalWin->AsInner() : nullptr;
1852 const uint64_t innerWindowID = win ? win->WindowID() : 0;
1853
1854 RootedObject errorObj(cx, error.isObject() ? &error.toObject() : nullptr);
1855 JSErrorReport* err = errorObj ? JS_ErrorFromException(cx, errorObj) : nullptr;
1856
1857 nsCOMPtr<nsIScriptError> scripterr;
1858
1859 if (errorObj) {
1860 JS::RootedObject stackVal(cx,
1861 FindExceptionStackForConsoleReport(win, error));
1862 if (stackVal) {
1863 scripterr = new nsScriptErrorWithStack(stackVal);
1864 }
1865 }
1866
1867 nsString fileName;
1868 uint32_t lineNo = 0;
1869
1870 if (!scripterr) {
1871 RootedObject stackObj(cx);
1872 if (stack.isObject()) {
1873 if (!JS::IsSavedFrame(&stack.toObject())) {
1874 return NS_ERROR_INVALID_ARG;
1875 }
1876
1877 stackObj = &stack.toObject();
1878
1879 if (GetSavedFrameLine(cx, stackObj, &lineNo) != SavedFrameResult::Ok) {
1880 JS_ClearPendingException(cx);
1881 }
1882
1883 RootedString source(cx);
1884 nsAutoJSString str;
1885 if (GetSavedFrameSource(cx, stackObj, &source) == SavedFrameResult::Ok &&
1886 str.init(cx, source)) {
1887 fileName = str;
1888 } else {
1889 JS_ClearPendingException(cx);
1890 }
1891 } else {
1892 nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
1893 if (frame) {
1894 frame->GetFilename(cx, fileName);
1895 lineNo = frame->GetLineNumber(cx);
1896 JS::Rooted<JS::Value> stack(cx);
1897 nsresult rv = frame->GetNativeSavedFrame(&stack);
1898 if (NS_SUCCEEDED(rv) && stack.isObject()) {
1899 stackObj = &stack.toObject();
1900 }
1901 }
1902 }
1903
1904 if (stackObj) {
1905 scripterr = new nsScriptErrorWithStack(stackObj);
1906 }
1907 }
1908
1909 if (!scripterr) {
1910 scripterr = new nsScriptError();
1911 }
1912
1913 if (err) {
1914 // It's a proper JS Error
1915 nsAutoString fileUni;
1916 CopyUTF8toUTF16(err->filename, fileUni);
1917
1918 uint32_t column = err->tokenOffset();
1919
1920 const char16_t* linebuf = err->linebuf();
1921
1922 nsresult rv = scripterr->InitWithWindowID(
1923 err->message() ? NS_ConvertUTF8toUTF16(err->message().c_str())
1924 : EmptyString(),
1925 fileUni,
1926 linebuf ? nsDependentString(linebuf, err->linebufLength())
1927 : EmptyString(),
1928 err->lineno, column, err->flags, "XPConnect JavaScript", innerWindowID);
1929 NS_ENSURE_SUCCESS(rv, NS_OK);
1930
1931 console->LogMessage(scripterr);
1932 return NS_OK;
1933 }
1934
1935 // It's not a JS Error object, so we synthesize as best we're able.
1936 RootedString msgstr(cx, ToString(cx, error));
1937 if (!msgstr) return NS_OK;
1938
1939 nsAutoJSString msg;
1940 if (!msg.init(cx, msgstr)) return NS_OK;
1941
1942 nsresult rv =
1943 scripterr->InitWithWindowID(msg, fileName, EmptyString(), lineNo, 0, 0,
1944 "XPConnect JavaScript", innerWindowID);
1945 NS_ENSURE_SUCCESS(rv, NS_OK);
1946
1947 console->LogMessage(scripterr);
1948 return NS_OK;
1949 }
1950
1951 NS_IMETHODIMP
EvalInSandbox(const nsAString & source,HandleValue sandboxVal,HandleValue version,const nsACString & filenameArg,int32_t lineNumber,JSContext * cx,uint8_t optionalArgc,MutableHandleValue retval)1952 nsXPCComponents_Utils::EvalInSandbox(
1953 const nsAString& source, HandleValue sandboxVal, HandleValue version,
1954 const nsACString& filenameArg, int32_t lineNumber, JSContext* cx,
1955 uint8_t optionalArgc, MutableHandleValue retval) {
1956 RootedObject sandbox(cx);
1957 if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox)
1958 return NS_ERROR_INVALID_ARG;
1959
1960 // Optional third argument: JS version, as a string, is unused.
1961
1962 // Optional fourth and fifth arguments: filename and line number.
1963 int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1;
1964 nsCString filename;
1965 if (!filenameArg.IsVoid()) {
1966 filename.Assign(filenameArg);
1967 } else {
1968 // Get the current source info.
1969 nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
1970 if (frame) {
1971 nsString frameFile;
1972 frame->GetFilename(cx, frameFile);
1973 CopyUTF16toUTF8(frameFile, filename);
1974 lineNo = frame->GetLineNumber(cx);
1975 }
1976 }
1977
1978 return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo, retval);
1979 }
1980
1981 NS_IMETHODIMP
GetSandboxAddonId(HandleValue sandboxVal,JSContext * cx,MutableHandleValue rval)1982 nsXPCComponents_Utils::GetSandboxAddonId(HandleValue sandboxVal, JSContext* cx,
1983 MutableHandleValue rval) {
1984 if (!sandboxVal.isObject()) return NS_ERROR_INVALID_ARG;
1985
1986 RootedObject sandbox(cx, &sandboxVal.toObject());
1987 sandbox = js::CheckedUnwrap(sandbox);
1988 if (!sandbox || !xpc::IsSandbox(sandbox)) return NS_ERROR_INVALID_ARG;
1989
1990 return xpc::GetSandboxAddonId(cx, sandbox, rval);
1991 }
1992
1993 NS_IMETHODIMP
GetSandboxMetadata(HandleValue sandboxVal,JSContext * cx,MutableHandleValue rval)1994 nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal, JSContext* cx,
1995 MutableHandleValue rval) {
1996 if (!sandboxVal.isObject()) return NS_ERROR_INVALID_ARG;
1997
1998 RootedObject sandbox(cx, &sandboxVal.toObject());
1999 sandbox = js::CheckedUnwrap(sandbox);
2000 if (!sandbox || !xpc::IsSandbox(sandbox)) return NS_ERROR_INVALID_ARG;
2001
2002 return xpc::GetSandboxMetadata(cx, sandbox, rval);
2003 }
2004
2005 NS_IMETHODIMP
SetSandboxMetadata(HandleValue sandboxVal,HandleValue metadataVal,JSContext * cx)2006 nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal,
2007 HandleValue metadataVal,
2008 JSContext* cx) {
2009 if (!sandboxVal.isObject()) return NS_ERROR_INVALID_ARG;
2010
2011 RootedObject sandbox(cx, &sandboxVal.toObject());
2012 sandbox = js::CheckedUnwrap(sandbox);
2013 if (!sandbox || !xpc::IsSandbox(sandbox)) return NS_ERROR_INVALID_ARG;
2014
2015 nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadataVal);
2016 NS_ENSURE_SUCCESS(rv, rv);
2017
2018 return NS_OK;
2019 }
2020
2021 NS_IMETHODIMP
Import(const nsACString & registryLocation,HandleValue targetObj,JSContext * cx,uint8_t optionalArgc,MutableHandleValue retval)2022 nsXPCComponents_Utils::Import(const nsACString& registryLocation,
2023 HandleValue targetObj, JSContext* cx,
2024 uint8_t optionalArgc, MutableHandleValue retval) {
2025 RefPtr<mozJSComponentLoader> moduleloader = mozJSComponentLoader::Get();
2026 MOZ_ASSERT(moduleloader);
2027
2028 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("nsXPCComponents_Utils::Import", OTHER,
2029 registryLocation);
2030
2031 return moduleloader->ImportInto(registryLocation, targetObj, cx, optionalArgc,
2032 retval);
2033 }
2034
2035 NS_IMETHODIMP
IsModuleLoaded(const nsACString & registryLocation,bool * retval)2036 nsXPCComponents_Utils::IsModuleLoaded(const nsACString& registryLocation,
2037 bool* retval) {
2038 RefPtr<mozJSComponentLoader> moduleloader = mozJSComponentLoader::Get();
2039 MOZ_ASSERT(moduleloader);
2040 return moduleloader->IsModuleLoaded(registryLocation, retval);
2041 }
2042
2043 NS_IMETHODIMP
Unload(const nsACString & registryLocation)2044 nsXPCComponents_Utils::Unload(const nsACString& registryLocation) {
2045 RefPtr<mozJSComponentLoader> moduleloader = mozJSComponentLoader::Get();
2046 MOZ_ASSERT(moduleloader);
2047 return moduleloader->Unload(registryLocation);
2048 }
2049
2050 NS_IMETHODIMP
ImportGlobalProperties(HandleValue aPropertyList,JSContext * cx)2051 nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
2052 JSContext* cx) {
2053 RootedObject global(cx, CurrentGlobalOrNull(cx));
2054 MOZ_ASSERT(global);
2055
2056 // Don't allow doing this if the global is a Window
2057 nsGlobalWindowInner* win;
2058 if (NS_SUCCEEDED(UNWRAP_OBJECT(Window, &global, win))) {
2059 return NS_ERROR_NOT_AVAILABLE;
2060 }
2061
2062 GlobalProperties options;
2063 NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
2064
2065 RootedObject propertyList(cx, &aPropertyList.toObject());
2066 bool isArray;
2067 if (NS_WARN_IF(!JS_IsArrayObject(cx, propertyList, &isArray))) {
2068 return NS_ERROR_FAILURE;
2069 }
2070 if (NS_WARN_IF(!isArray)) {
2071 return NS_ERROR_INVALID_ARG;
2072 }
2073
2074 if (!options.Parse(cx, propertyList) ||
2075 !options.DefineInXPCComponents(cx, global)) {
2076 return NS_ERROR_FAILURE;
2077 }
2078
2079 return NS_OK;
2080 }
2081
2082 NS_IMETHODIMP
GetWeakReference(HandleValue object,JSContext * cx,xpcIJSWeakReference ** _retval)2083 nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext* cx,
2084 xpcIJSWeakReference** _retval) {
2085 RefPtr<xpcJSWeakReference> ref = new xpcJSWeakReference();
2086 nsresult rv = ref->Init(cx, object);
2087 NS_ENSURE_SUCCESS(rv, rv);
2088 ref.forget(_retval);
2089 return NS_OK;
2090 }
2091
2092 NS_IMETHODIMP
ForceGC()2093 nsXPCComponents_Utils::ForceGC() {
2094 JSContext* cx = XPCJSContext::Get()->Context();
2095 PrepareForFullGC(cx);
2096 GCForReason(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
2097 return NS_OK;
2098 }
2099
2100 NS_IMETHODIMP
ForceCC(nsICycleCollectorListener * listener)2101 nsXPCComponents_Utils::ForceCC(nsICycleCollectorListener* listener) {
2102 nsJSContext::CycleCollectNow(listener);
2103 return NS_OK;
2104 }
2105
2106 NS_IMETHODIMP
FinishCC()2107 nsXPCComponents_Utils::FinishCC() {
2108 nsCycleCollector_finishAnyCurrentCollection();
2109 return NS_OK;
2110 }
2111
2112 NS_IMETHODIMP
CcSlice(int64_t budget)2113 nsXPCComponents_Utils::CcSlice(int64_t budget) {
2114 nsJSContext::RunCycleCollectorWorkSlice(budget);
2115 return NS_OK;
2116 }
2117
2118 NS_IMETHODIMP
GetMaxCCSliceTimeSinceClear(int32_t * out)2119 nsXPCComponents_Utils::GetMaxCCSliceTimeSinceClear(int32_t* out) {
2120 *out = nsJSContext::GetMaxCCSliceTimeSinceClear();
2121 return NS_OK;
2122 }
2123
2124 NS_IMETHODIMP
ClearMaxCCTime()2125 nsXPCComponents_Utils::ClearMaxCCTime() {
2126 nsJSContext::ClearMaxCCSliceTime();
2127 return NS_OK;
2128 }
2129
2130 NS_IMETHODIMP
ForceShrinkingGC()2131 nsXPCComponents_Utils::ForceShrinkingGC() {
2132 JSContext* cx = dom::danger::GetJSContext();
2133 PrepareForFullGC(cx);
2134 GCForReason(cx, GC_SHRINK, gcreason::COMPONENT_UTILS);
2135 return NS_OK;
2136 }
2137
2138 class PreciseGCRunnable : public Runnable {
2139 public:
PreciseGCRunnable(ScheduledGCCallback * aCallback,bool aShrinking)2140 PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking)
2141 : mozilla::Runnable("PreciseGCRunnable"),
2142 mCallback(aCallback),
2143 mShrinking(aShrinking) {}
2144
Run()2145 NS_IMETHOD Run() override {
2146 nsJSContext::GarbageCollectNow(
2147 gcreason::COMPONENT_UTILS, nsJSContext::NonIncrementalGC,
2148 mShrinking ? nsJSContext::ShrinkingGC : nsJSContext::NonShrinkingGC);
2149
2150 mCallback->Callback();
2151 return NS_OK;
2152 }
2153
2154 private:
2155 RefPtr<ScheduledGCCallback> mCallback;
2156 bool mShrinking;
2157 };
2158
2159 NS_IMETHODIMP
SchedulePreciseGC(ScheduledGCCallback * aCallback)2160 nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback) {
2161 RefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, false);
2162 return NS_DispatchToMainThread(event);
2163 }
2164
2165 NS_IMETHODIMP
SchedulePreciseShrinkingGC(ScheduledGCCallback * aCallback)2166 nsXPCComponents_Utils::SchedulePreciseShrinkingGC(
2167 ScheduledGCCallback* aCallback) {
2168 RefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, true);
2169 return NS_DispatchToMainThread(event);
2170 }
2171
2172 NS_IMETHODIMP
UnlinkGhostWindows()2173 nsXPCComponents_Utils::UnlinkGhostWindows() {
2174 #ifdef DEBUG
2175 nsWindowMemoryReporter::UnlinkGhostWindows();
2176
2177 if (XRE_IsParentProcess()) {
2178 nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
2179 if (obsvc) {
2180 obsvc->NotifyObservers(nullptr, "child-ghost-request", nullptr);
2181 }
2182 }
2183
2184 return NS_OK;
2185 #else
2186 return NS_ERROR_NOT_IMPLEMENTED;
2187 #endif
2188 }
2189
2190 NS_IMETHODIMP
GetJSTestingFunctions(JSContext * cx,MutableHandleValue retval)2191 nsXPCComponents_Utils::GetJSTestingFunctions(JSContext* cx,
2192 MutableHandleValue retval) {
2193 JSObject* obj = js::GetTestingFunctions(cx);
2194 if (!obj) return NS_ERROR_XPC_JAVASCRIPT_ERROR;
2195 retval.setObject(*obj);
2196 return NS_OK;
2197 }
2198
2199 NS_IMETHODIMP
CallFunctionWithAsyncStack(HandleValue function,nsIStackFrame * stack,const nsAString & asyncCause,JSContext * cx,MutableHandleValue retval)2200 nsXPCComponents_Utils::CallFunctionWithAsyncStack(HandleValue function,
2201 nsIStackFrame* stack,
2202 const nsAString& asyncCause,
2203 JSContext* cx,
2204 MutableHandleValue retval) {
2205 nsresult rv;
2206
2207 if (!stack || asyncCause.IsEmpty()) {
2208 return NS_ERROR_INVALID_ARG;
2209 }
2210
2211 JS::Rooted<JS::Value> asyncStack(cx);
2212 rv = stack->GetNativeSavedFrame(&asyncStack);
2213 if (NS_FAILED(rv)) return rv;
2214 if (!asyncStack.isObject()) {
2215 JS_ReportErrorASCII(cx, "Must use a native JavaScript stack frame");
2216 return NS_ERROR_INVALID_ARG;
2217 }
2218
2219 JS::Rooted<JSObject*> asyncStackObj(cx, &asyncStack.toObject());
2220
2221 NS_ConvertUTF16toUTF8 utf8Cause(asyncCause);
2222 JS::AutoSetAsyncStackForNewCalls sas(
2223 cx, asyncStackObj, utf8Cause.get(),
2224 JS::AutoSetAsyncStackForNewCalls::AsyncCallKind::EXPLICIT);
2225
2226 if (!JS_CallFunctionValue(cx, nullptr, function,
2227 JS::HandleValueArray::empty(), retval)) {
2228 return NS_ERROR_XPC_JAVASCRIPT_ERROR;
2229 }
2230
2231 return NS_OK;
2232 }
2233
2234 NS_IMETHODIMP
GetGlobalForObject(HandleValue object,JSContext * cx,MutableHandleValue retval)2235 nsXPCComponents_Utils::GetGlobalForObject(HandleValue object, JSContext* cx,
2236 MutableHandleValue retval) {
2237 // First argument must be an object.
2238 if (object.isPrimitive()) return NS_ERROR_XPC_BAD_CONVERT_JS;
2239
2240 // Wrappers are parented to their the global in their home compartment. But
2241 // when getting the global for a cross-compartment wrapper, we really want
2242 // a wrapper for the foreign global. So we need to unwrap before getting the
2243 // parent, enter the compartment for the duration of the call, and wrap the
2244 // result.
2245 Rooted<JSObject*> obj(cx, &object.toObject());
2246 obj = js::UncheckedUnwrap(obj);
2247 {
2248 JSAutoCompartment ac(cx, obj);
2249 obj = JS_GetGlobalForObject(cx, obj);
2250 }
2251
2252 if (!JS_WrapObject(cx, &obj)) return NS_ERROR_FAILURE;
2253
2254 // Get the WindowProxy if necessary.
2255 obj = js::ToWindowProxyIfWindow(obj);
2256
2257 retval.setObject(*obj);
2258 return NS_OK;
2259 }
2260
2261 NS_IMETHODIMP
IsProxy(HandleValue vobj,JSContext * cx,bool * rval)2262 nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext* cx, bool* rval) {
2263 if (!vobj.isObject()) {
2264 *rval = false;
2265 return NS_OK;
2266 }
2267
2268 RootedObject obj(cx, &vobj.toObject());
2269 obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
2270 NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
2271
2272 *rval = js::IsScriptedProxy(obj);
2273 return NS_OK;
2274 }
2275
2276 NS_IMETHODIMP
ExportFunction(HandleValue vfunction,HandleValue vscope,HandleValue voptions,JSContext * cx,MutableHandleValue rval)2277 nsXPCComponents_Utils::ExportFunction(HandleValue vfunction, HandleValue vscope,
2278 HandleValue voptions, JSContext* cx,
2279 MutableHandleValue rval) {
2280 if (!xpc::ExportFunction(cx, vfunction, vscope, voptions, rval))
2281 return NS_ERROR_FAILURE;
2282 return NS_OK;
2283 }
2284
2285 NS_IMETHODIMP
CreateObjectIn(HandleValue vobj,HandleValue voptions,JSContext * cx,MutableHandleValue rval)2286 nsXPCComponents_Utils::CreateObjectIn(HandleValue vobj, HandleValue voptions,
2287 JSContext* cx, MutableHandleValue rval) {
2288 RootedObject optionsObject(
2289 cx, voptions.isObject() ? &voptions.toObject() : nullptr);
2290 CreateObjectInOptions options(cx, optionsObject);
2291 if (voptions.isObject() && !options.Parse()) {
2292 return NS_ERROR_FAILURE;
2293 }
2294
2295 if (!xpc::CreateObjectIn(cx, vobj, options, rval)) return NS_ERROR_FAILURE;
2296 return NS_OK;
2297 }
2298
2299 NS_IMETHODIMP
MakeObjectPropsNormal(HandleValue vobj,JSContext * cx)2300 nsXPCComponents_Utils::MakeObjectPropsNormal(HandleValue vobj, JSContext* cx) {
2301 if (!cx) return NS_ERROR_FAILURE;
2302
2303 // first argument must be an object
2304 if (vobj.isPrimitive()) return NS_ERROR_XPC_BAD_CONVERT_JS;
2305
2306 RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
2307 JSAutoCompartment ac(cx, obj);
2308 Rooted<IdVector> ida(cx, IdVector(cx));
2309 if (!JS_Enumerate(cx, obj, &ida)) return NS_ERROR_FAILURE;
2310
2311 RootedId id(cx);
2312 RootedValue v(cx);
2313 for (size_t i = 0; i < ida.length(); ++i) {
2314 id = ida[i];
2315
2316 if (!JS_GetPropertyById(cx, obj, id, &v)) return NS_ERROR_FAILURE;
2317
2318 if (v.isPrimitive()) continue;
2319
2320 RootedObject propobj(cx, &v.toObject());
2321 // TODO Deal with non-functions.
2322 if (!js::IsWrapper(propobj) || !JS::IsCallable(propobj)) continue;
2323
2324 FunctionForwarderOptions forwarderOptions;
2325 if (!NewFunctionForwarder(cx, id, propobj, forwarderOptions, &v) ||
2326 !JS_SetPropertyById(cx, obj, id, v))
2327 return NS_ERROR_FAILURE;
2328 }
2329
2330 return NS_OK;
2331 }
2332
2333 NS_IMETHODIMP
IsDeadWrapper(HandleValue obj,bool * out)2334 nsXPCComponents_Utils::IsDeadWrapper(HandleValue obj, bool* out) {
2335 *out = false;
2336 if (obj.isPrimitive()) return NS_ERROR_INVALID_ARG;
2337
2338 // We should never have cross-compartment wrappers for dead wrappers.
2339 MOZ_ASSERT_IF(js::IsCrossCompartmentWrapper(&obj.toObject()),
2340 !JS_IsDeadWrapper(js::UncheckedUnwrap(&obj.toObject())));
2341
2342 *out = JS_IsDeadWrapper(&obj.toObject());
2343 return NS_OK;
2344 }
2345
2346 NS_IMETHODIMP
IsCrossProcessWrapper(HandleValue obj,bool * out)2347 nsXPCComponents_Utils::IsCrossProcessWrapper(HandleValue obj, bool* out) {
2348 *out = false;
2349 if (obj.isPrimitive()) return NS_ERROR_INVALID_ARG;
2350
2351 *out = jsipc::IsWrappedCPOW(&obj.toObject());
2352 return NS_OK;
2353 }
2354
2355 NS_IMETHODIMP
GetCrossProcessWrapperTag(HandleValue obj,nsACString & out)2356 nsXPCComponents_Utils::GetCrossProcessWrapperTag(HandleValue obj,
2357 nsACString& out) {
2358 if (obj.isPrimitive() || !jsipc::IsWrappedCPOW(&obj.toObject()))
2359 return NS_ERROR_INVALID_ARG;
2360
2361 jsipc::GetWrappedCPOWTag(&obj.toObject(), out);
2362 return NS_OK;
2363 }
2364
2365 NS_IMETHODIMP
PermitCPOWsInScope(HandleValue obj)2366 nsXPCComponents_Utils::PermitCPOWsInScope(HandleValue obj) {
2367 if (!obj.isObject()) return NS_ERROR_INVALID_ARG;
2368
2369 JSObject* scopeObj = js::UncheckedUnwrap(&obj.toObject());
2370 MOZ_DIAGNOSTIC_ASSERT(
2371 !mozJSComponentLoader::Get()->IsLoaderGlobal(scopeObj),
2372 "Don't call Cu.PermitCPOWsInScope() in a JSM that shares its global");
2373 CompartmentPrivate::Get(scopeObj)->allowCPOWs = true;
2374 return NS_OK;
2375 }
2376
2377 NS_IMETHODIMP
RecomputeWrappers(HandleValue vobj,JSContext * cx)2378 nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext* cx) {
2379 // Determine the compartment of the given object, if any.
2380 JSCompartment* c =
2381 vobj.isObject()
2382 ? js::GetObjectCompartment(js::UncheckedUnwrap(&vobj.toObject()))
2383 : nullptr;
2384
2385 // If no compartment was given, recompute all.
2386 if (!c)
2387 js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments());
2388 // Otherwise, recompute wrappers for the given compartment.
2389 else
2390 js::RecomputeWrappers(cx, js::SingleCompartment(c),
2391 js::AllCompartments()) &&
2392 js::RecomputeWrappers(cx, js::AllCompartments(),
2393 js::SingleCompartment(c));
2394
2395 return NS_OK;
2396 }
2397
2398 NS_IMETHODIMP
SetWantXrays(HandleValue vscope,JSContext * cx)2399 nsXPCComponents_Utils::SetWantXrays(HandleValue vscope, JSContext* cx) {
2400 if (!vscope.isObject()) return NS_ERROR_INVALID_ARG;
2401 JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
2402 MOZ_DIAGNOSTIC_ASSERT(
2403 !mozJSComponentLoader::Get()->IsLoaderGlobal(scopeObj),
2404 "Don't call Cu.setWantXrays() in a JSM that shares its global");
2405 JSCompartment* compartment = js::GetObjectCompartment(scopeObj);
2406 CompartmentPrivate::Get(scopeObj)->wantXrays = true;
2407 bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
2408 js::AllCompartments());
2409 NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
2410 return NS_OK;
2411 }
2412
2413 NS_IMETHODIMP
ForcePermissiveCOWs(JSContext * cx)2414 nsXPCComponents_Utils::ForcePermissiveCOWs(JSContext* cx) {
2415 xpc::CrashIfNotInAutomation();
2416 JSObject* currentGlobal = CurrentGlobalOrNull(cx);
2417 MOZ_DIAGNOSTIC_ASSERT(
2418 !mozJSComponentLoader::Get()->IsLoaderGlobal(currentGlobal),
2419 "Don't call Cu.forcePermissiveCOWs() in a JSM that shares its global");
2420 CompartmentPrivate::Get(currentGlobal)->forcePermissiveCOWs = true;
2421 return NS_OK;
2422 }
2423
2424 NS_IMETHODIMP
ForcePrivilegedComponentsForScope(HandleValue vscope,JSContext * cx)2425 nsXPCComponents_Utils::ForcePrivilegedComponentsForScope(HandleValue vscope,
2426 JSContext* cx) {
2427 if (!vscope.isObject()) return NS_ERROR_INVALID_ARG;
2428 xpc::CrashIfNotInAutomation();
2429 JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
2430 XPCWrappedNativeScope* scope = ObjectScope(scopeObj);
2431 scope->ForcePrivilegedComponents();
2432 return NS_OK;
2433 }
2434
2435 NS_IMETHODIMP
GetComponentsForScope(HandleValue vscope,JSContext * cx,MutableHandleValue rval)2436 nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext* cx,
2437 MutableHandleValue rval) {
2438 if (!vscope.isObject()) return NS_ERROR_INVALID_ARG;
2439 JSObject* scopeObj = js::UncheckedUnwrap(&vscope.toObject());
2440 XPCWrappedNativeScope* scope = ObjectScope(scopeObj);
2441 RootedObject components(cx);
2442 if (!scope->GetComponentsJSObject(&components)) return NS_ERROR_FAILURE;
2443 if (!JS_WrapObject(cx, &components)) return NS_ERROR_FAILURE;
2444 rval.setObject(*components);
2445 return NS_OK;
2446 }
2447
2448 NS_IMETHODIMP
Dispatch(HandleValue runnableArg,HandleValue scope,JSContext * cx)2449 nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
2450 JSContext* cx) {
2451 RootedValue runnable(cx, runnableArg);
2452 // Enter the given compartment, if any, and rewrap runnable.
2453 Maybe<JSAutoCompartment> ac;
2454 if (scope.isObject()) {
2455 JSObject* scopeObj = js::UncheckedUnwrap(&scope.toObject());
2456 if (!scopeObj) return NS_ERROR_FAILURE;
2457 ac.emplace(cx, scopeObj);
2458 if (!JS_WrapValue(cx, &runnable)) return NS_ERROR_FAILURE;
2459 }
2460
2461 // Get an XPCWrappedJS for |runnable|.
2462 if (!runnable.isObject()) return NS_ERROR_INVALID_ARG;
2463
2464 nsCOMPtr<nsIRunnable> run;
2465 nsresult rv = nsXPConnect::XPConnect()->WrapJS(
2466 cx, &runnable.toObject(), NS_GET_IID(nsIRunnable), getter_AddRefs(run));
2467 NS_ENSURE_SUCCESS(rv, rv);
2468 MOZ_ASSERT(run);
2469
2470 // Dispatch.
2471 return NS_DispatchToMainThread(run);
2472 }
2473
2474 #define GENERATE_JSCONTEXTOPTION_GETTER_SETTER(_attr, _getter, _setter) \
2475 NS_IMETHODIMP \
2476 nsXPCComponents_Utils::Get##_attr(JSContext* cx, bool* aValue) { \
2477 *aValue = ContextOptionsRef(cx)._getter(); \
2478 return NS_OK; \
2479 } \
2480 NS_IMETHODIMP \
2481 nsXPCComponents_Utils::Set##_attr(JSContext* cx, bool aValue) { \
2482 ContextOptionsRef(cx)._setter(aValue); \
2483 return NS_OK; \
2484 }
2485
GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict,extraWarnings,setExtraWarnings)2486 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
2487 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Werror, werror, setWerror)
2488 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
2489 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Ion, ion, setIon)
2490
2491 #undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
2492
2493 NS_IMETHODIMP
2494 nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx) {
2495 #ifdef JS_GC_ZEAL
2496 JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ);
2497 #endif
2498 return NS_OK;
2499 }
2500
2501 NS_IMETHODIMP
GetIsInAutomation(bool * aResult)2502 nsXPCComponents_Utils::GetIsInAutomation(bool* aResult) {
2503 NS_ENSURE_ARG_POINTER(aResult);
2504
2505 *aResult = xpc::IsInAutomation();
2506 return NS_OK;
2507 }
2508
2509 NS_IMETHODIMP
CrashIfNotInAutomation()2510 nsXPCComponents_Utils::CrashIfNotInAutomation() {
2511 xpc::CrashIfNotInAutomation();
2512 return NS_OK;
2513 }
2514
2515 NS_IMETHODIMP
NukeSandbox(HandleValue obj,JSContext * cx)2516 nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext* cx) {
2517 AUTO_PROFILER_LABEL("nsXPCComponents_Utils::NukeSandbox", JS);
2518 NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG);
2519 JSObject* wrapper = &obj.toObject();
2520 NS_ENSURE_TRUE(IsWrapper(wrapper), NS_ERROR_INVALID_ARG);
2521 RootedObject sb(cx, UncheckedUnwrap(wrapper));
2522 NS_ENSURE_TRUE(IsSandbox(sb), NS_ERROR_INVALID_ARG);
2523
2524 xpc::NukeAllWrappersForCompartment(cx, GetObjectCompartment(sb));
2525
2526 return NS_OK;
2527 }
2528
2529 NS_IMETHODIMP
BlockScriptForGlobal(HandleValue globalArg,JSContext * cx)2530 nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
2531 JSContext* cx) {
2532 NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
2533 RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
2534 /* stopAtWindowProxy = */ false));
2535 NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
2536 if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
2537 JS_ReportErrorASCII(cx, "Script may not be disabled for system globals");
2538 return NS_ERROR_FAILURE;
2539 }
2540 Scriptability::Get(global).Block();
2541 return NS_OK;
2542 }
2543
2544 NS_IMETHODIMP
UnblockScriptForGlobal(HandleValue globalArg,JSContext * cx)2545 nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
2546 JSContext* cx) {
2547 NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
2548 RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
2549 /* stopAtWindowProxy = */ false));
2550 NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
2551 if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
2552 JS_ReportErrorASCII(cx, "Script may not be disabled for system globals");
2553 return NS_ERROR_FAILURE;
2554 }
2555 Scriptability::Get(global).Unblock();
2556 return NS_OK;
2557 }
2558
2559 NS_IMETHODIMP
IsXrayWrapper(HandleValue obj,bool * aRetval)2560 nsXPCComponents_Utils::IsXrayWrapper(HandleValue obj, bool* aRetval) {
2561 *aRetval =
2562 obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
2563 return NS_OK;
2564 }
2565
2566 NS_IMETHODIMP
WaiveXrays(HandleValue aVal,JSContext * aCx,MutableHandleValue aRetval)2567 nsXPCComponents_Utils::WaiveXrays(HandleValue aVal, JSContext* aCx,
2568 MutableHandleValue aRetval) {
2569 RootedValue value(aCx, aVal);
2570 if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value))
2571 return NS_ERROR_FAILURE;
2572 aRetval.set(value);
2573 return NS_OK;
2574 }
2575
2576 NS_IMETHODIMP
UnwaiveXrays(HandleValue aVal,JSContext * aCx,MutableHandleValue aRetval)2577 nsXPCComponents_Utils::UnwaiveXrays(HandleValue aVal, JSContext* aCx,
2578 MutableHandleValue aRetval) {
2579 if (!aVal.isObject()) {
2580 aRetval.set(aVal);
2581 return NS_OK;
2582 }
2583
2584 RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject()));
2585 if (!JS_WrapObject(aCx, &obj)) return NS_ERROR_FAILURE;
2586 aRetval.setObject(*obj);
2587 return NS_OK;
2588 }
2589
2590 NS_IMETHODIMP
GetClassName(HandleValue aObj,bool aUnwrap,JSContext * aCx,char ** aRv)2591 nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap,
2592 JSContext* aCx, char** aRv) {
2593 if (!aObj.isObject()) return NS_ERROR_INVALID_ARG;
2594 RootedObject obj(aCx, &aObj.toObject());
2595 if (aUnwrap) obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
2596 *aRv = NS_strdup(js::GetObjectClass(obj)->name);
2597 NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY);
2598 return NS_OK;
2599 }
2600
2601 NS_IMETHODIMP
GetDOMClassInfo(const nsAString & aClassName,nsIClassInfo ** aClassInfo)2602 nsXPCComponents_Utils::GetDOMClassInfo(const nsAString& aClassName,
2603 nsIClassInfo** aClassInfo) {
2604 *aClassInfo = nullptr;
2605 return NS_ERROR_NOT_AVAILABLE;
2606 }
2607
2608 NS_IMETHODIMP
GetIncumbentGlobal(HandleValue aCallback,JSContext * aCx,MutableHandleValue aOut)2609 nsXPCComponents_Utils::GetIncumbentGlobal(HandleValue aCallback, JSContext* aCx,
2610 MutableHandleValue aOut) {
2611 nsCOMPtr<nsIGlobalObject> global = mozilla::dom::GetIncumbentGlobal();
2612 RootedValue globalVal(aCx);
2613
2614 if (!global) {
2615 globalVal = NullValue();
2616 } else {
2617 // Note: We rely on the wrap call for outerization.
2618 globalVal = ObjectValue(*global->GetGlobalJSObject());
2619 if (!JS_WrapValue(aCx, &globalVal)) return NS_ERROR_FAILURE;
2620 }
2621
2622 // Invoke the callback, if passed.
2623 if (aCallback.isObject()) {
2624 RootedValue ignored(aCx);
2625 if (!JS_CallFunctionValue(aCx, nullptr, aCallback,
2626 JS::HandleValueArray(globalVal), &ignored))
2627 return NS_ERROR_FAILURE;
2628 }
2629
2630 aOut.set(globalVal);
2631 return NS_OK;
2632 }
2633
2634 /*
2635 * Below is a bunch of awkward junk to allow JS test code to trigger the
2636 * creation of an XPCWrappedJS, such that it ends up in the map. We need to
2637 * hand the caller some sort of reference to hold onto (to prevent the
2638 * refcount from dropping to zero as soon as the function returns), but trying
2639 * to return a bonafide XPCWrappedJS to script causes all sorts of trouble. So
2640 * we create a benign holder class instead, which acts as an opaque reference
2641 * that script can use to keep the XPCWrappedJS alive and in the map.
2642 */
2643
2644 class WrappedJSHolder : public nsISupports {
2645 NS_DECL_ISUPPORTS
WrappedJSHolder()2646 WrappedJSHolder() {}
2647
2648 RefPtr<nsXPCWrappedJS> mWrappedJS;
2649
2650 private:
~WrappedJSHolder()2651 virtual ~WrappedJSHolder() {}
2652 };
2653
2654 NS_IMPL_ADDREF(WrappedJSHolder)
2655 NS_IMPL_RELEASE(WrappedJSHolder)
2656
2657 // nsINamed is always supported by nsXPCWrappedJSClass.
2658 // We expose this interface only for the identity in telemetry analysis.
2659 NS_INTERFACE_TABLE_HEAD(WrappedJSHolder)
2660 if (aIID.Equals(NS_GET_IID(nsINamed))) {
2661 return mWrappedJS->QueryInterface(aIID, aInstancePtr);
2662 }
NS_INTERFACE_TABLE0(WrappedJSHolder)2663 NS_INTERFACE_TABLE0(WrappedJSHolder)
2664 NS_INTERFACE_TABLE_TAIL
2665
2666 NS_IMETHODIMP
2667 nsXPCComponents_Utils::GenerateXPCWrappedJS(HandleValue aObj,
2668 HandleValue aScope, JSContext* aCx,
2669 nsISupports** aOut) {
2670 if (!aObj.isObject()) return NS_ERROR_INVALID_ARG;
2671 RootedObject obj(aCx, &aObj.toObject());
2672 RootedObject scope(aCx, aScope.isObject()
2673 ? js::UncheckedUnwrap(&aScope.toObject())
2674 : CurrentGlobalOrNull(aCx));
2675 JSAutoCompartment ac(aCx, scope);
2676 if (!JS_WrapObject(aCx, &obj)) return NS_ERROR_FAILURE;
2677
2678 RefPtr<WrappedJSHolder> holder = new WrappedJSHolder();
2679 nsresult rv = nsXPCWrappedJS::GetNewOrUsed(
2680 obj, NS_GET_IID(nsISupports), getter_AddRefs(holder->mWrappedJS));
2681 holder.forget(aOut);
2682 return rv;
2683 }
2684
2685 NS_IMETHODIMP
GetWatchdogTimestamp(const nsAString & aCategory,PRTime * aOut)2686 nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory,
2687 PRTime* aOut) {
2688 WatchdogTimestampCategory category;
2689 if (aCategory.EqualsLiteral("ContextStateChange"))
2690 category = TimestampContextStateChange;
2691 else if (aCategory.EqualsLiteral("WatchdogWakeup"))
2692 category = TimestampWatchdogWakeup;
2693 else if (aCategory.EqualsLiteral("WatchdogHibernateStart"))
2694 category = TimestampWatchdogHibernateStart;
2695 else if (aCategory.EqualsLiteral("WatchdogHibernateStop"))
2696 category = TimestampWatchdogHibernateStop;
2697 else
2698 return NS_ERROR_INVALID_ARG;
2699 *aOut = XPCJSContext::Get()->GetWatchdogTimestamp(category);
2700 return NS_OK;
2701 }
2702
2703 NS_IMETHODIMP
GetJSEngineTelemetryValue(JSContext * cx,MutableHandleValue rval)2704 nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext* cx,
2705 MutableHandleValue rval) {
2706 RootedObject obj(cx, JS_NewPlainObject(cx));
2707 if (!obj) return NS_ERROR_OUT_OF_MEMORY;
2708
2709 // No JS engine telemetry in use at the moment.
2710
2711 rval.setObject(*obj);
2712 return NS_OK;
2713 }
2714
CloneInto(JSContext * aCx,HandleValue aValue,HandleValue aScope,HandleValue aOptions,MutableHandleValue aCloned)2715 bool xpc::CloneInto(JSContext* aCx, HandleValue aValue, HandleValue aScope,
2716 HandleValue aOptions, MutableHandleValue aCloned) {
2717 if (!aScope.isObject()) return false;
2718
2719 RootedObject scope(aCx, &aScope.toObject());
2720 scope = js::CheckedUnwrap(scope);
2721 if (!scope) {
2722 JS_ReportErrorASCII(aCx, "Permission denied to clone object into scope");
2723 return false;
2724 }
2725
2726 if (!aOptions.isUndefined() && !aOptions.isObject()) {
2727 JS_ReportErrorASCII(aCx, "Invalid argument");
2728 return false;
2729 }
2730
2731 RootedObject optionsObject(
2732 aCx, aOptions.isObject() ? &aOptions.toObject() : nullptr);
2733 StackScopedCloneOptions options(aCx, optionsObject);
2734 if (aOptions.isObject() && !options.Parse()) return false;
2735
2736 {
2737 JSAutoCompartment ac(aCx, scope);
2738 aCloned.set(aValue);
2739 if (!StackScopedClone(aCx, options, aCloned)) return false;
2740 }
2741
2742 return JS_WrapValue(aCx, aCloned);
2743 }
2744
2745 NS_IMETHODIMP
CloneInto(HandleValue aValue,HandleValue aScope,HandleValue aOptions,JSContext * aCx,MutableHandleValue aCloned)2746 nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope,
2747 HandleValue aOptions, JSContext* aCx,
2748 MutableHandleValue aCloned) {
2749 return xpc::CloneInto(aCx, aValue, aScope, aOptions, aCloned)
2750 ? NS_OK
2751 : NS_ERROR_FAILURE;
2752 }
2753
2754 NS_IMETHODIMP
GetWebIDLCallerPrincipal(nsIPrincipal ** aResult)2755 nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal** aResult) {
2756 // This API may only be when the Entry Settings Object corresponds to a
2757 // JS-implemented WebIDL call. In all other cases, the value will be null,
2758 // and we throw.
2759 nsCOMPtr<nsIPrincipal> callerPrin = mozilla::dom::GetWebIDLCallerPrincipal();
2760 if (!callerPrin) return NS_ERROR_NOT_AVAILABLE;
2761 callerPrin.forget(aResult);
2762 return NS_OK;
2763 }
2764
2765 NS_IMETHODIMP
GetObjectPrincipal(HandleValue val,JSContext * cx,nsIPrincipal ** result)2766 nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext* cx,
2767 nsIPrincipal** result) {
2768 if (!val.isObject()) return NS_ERROR_INVALID_ARG;
2769 RootedObject obj(cx, &val.toObject());
2770 obj = js::CheckedUnwrap(obj);
2771 MOZ_ASSERT(obj);
2772
2773 nsCOMPtr<nsIPrincipal> prin = nsContentUtils::ObjectPrincipal(obj);
2774 prin.forget(result);
2775 return NS_OK;
2776 }
2777
2778 NS_IMETHODIMP
GetCompartmentLocation(HandleValue val,JSContext * cx,nsACString & result)2779 nsXPCComponents_Utils::GetCompartmentLocation(HandleValue val, JSContext* cx,
2780 nsACString& result) {
2781 if (!val.isObject()) return NS_ERROR_INVALID_ARG;
2782 RootedObject obj(cx, &val.toObject());
2783 obj = js::CheckedUnwrap(obj);
2784 MOZ_ASSERT(obj);
2785
2786 result = xpc::CompartmentPrivate::Get(obj)->GetLocation();
2787 return NS_OK;
2788 }
2789
2790 NS_IMETHODIMP
AllowCPOWsInAddon(const nsACString & addonIdStr,bool allow,JSContext * cx)2791 nsXPCComponents_Utils::AllowCPOWsInAddon(const nsACString& addonIdStr,
2792 bool allow, JSContext* cx) {
2793 JSAddonId* addonId = xpc::NewAddonId(cx, addonIdStr);
2794 if (!addonId) return NS_ERROR_FAILURE;
2795 if (!XPCWrappedNativeScope::AllowCPOWsInAddon(cx, addonId, allow))
2796 return NS_ERROR_FAILURE;
2797
2798 return NS_OK;
2799 }
2800
2801 NS_IMETHODIMP
ReadUTF8File(nsIFile * aFile,nsACString & aResult)2802 nsXPCComponents_Utils::ReadUTF8File(nsIFile* aFile, nsACString& aResult) {
2803 NS_ENSURE_TRUE(aFile, NS_ERROR_INVALID_ARG);
2804
2805 MOZ_TRY_VAR(aResult, URLPreloader::ReadFile(aFile));
2806 return NS_OK;
2807 }
2808
2809 NS_IMETHODIMP
ReadUTF8URI(nsIURI * aURI,nsACString & aResult)2810 nsXPCComponents_Utils::ReadUTF8URI(nsIURI* aURI, nsACString& aResult) {
2811 NS_ENSURE_TRUE(aURI, NS_ERROR_INVALID_ARG);
2812
2813 MOZ_TRY_VAR(aResult, URLPreloader::ReadURI(aURI));
2814 return NS_OK;
2815 }
2816
2817 NS_IMETHODIMP
Now(double * aRetval)2818 nsXPCComponents_Utils::Now(double* aRetval) {
2819 TimeStamp start = TimeStamp::ProcessCreation();
2820 *aRetval = (TimeStamp::Now() - start).ToMilliseconds();
2821 return NS_OK;
2822 }
2823
2824 NS_IMETHODIMP
BlockThreadedExecution(nsIBlockThreadedExecutionCallback * aCallback)2825 nsXPCComponents_Utils::BlockThreadedExecution(
2826 nsIBlockThreadedExecutionCallback* aCallback) {
2827 Scheduler::BlockThreadedExecution(aCallback);
2828 return NS_OK;
2829 }
2830
2831 NS_IMETHODIMP
UnblockThreadedExecution()2832 nsXPCComponents_Utils::UnblockThreadedExecution() {
2833 Scheduler::UnblockThreadedExecution();
2834 return NS_OK;
2835 }
2836
2837 /***************************************************************************/
2838 /***************************************************************************/
2839 /***************************************************************************/
2840
nsXPCComponentsBase(XPCWrappedNativeScope * aScope)2841 nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope)
2842 : mScope(aScope) {
2843 MOZ_ASSERT(aScope, "aScope must not be null");
2844 }
2845
nsXPCComponents(XPCWrappedNativeScope * aScope)2846 nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
2847 : nsXPCComponentsBase(aScope) {}
2848
~nsXPCComponentsBase()2849 nsXPCComponentsBase::~nsXPCComponentsBase() {}
2850
~nsXPCComponents()2851 nsXPCComponents::~nsXPCComponents() {}
2852
ClearMembers()2853 void nsXPCComponentsBase::ClearMembers() {
2854 mInterfaces = nullptr;
2855 mInterfacesByID = nullptr;
2856 mResults = nullptr;
2857 }
2858
ClearMembers()2859 void nsXPCComponents::ClearMembers() {
2860 mClasses = nullptr;
2861 mClassesByID = nullptr;
2862 mID = nullptr;
2863 mException = nullptr;
2864 mConstructor = nullptr;
2865 mUtils = nullptr;
2866
2867 nsXPCComponentsBase::ClearMembers();
2868 }
2869
2870 /*******************************************/
2871 #define XPC_IMPL_GET_OBJ_METHOD(_class, _n) \
2872 NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n** a##_n) { \
2873 NS_ENSURE_ARG_POINTER(a##_n); \
2874 if (!m##_n) m##_n = new nsXPCComponents_##_n(); \
2875 RefPtr<nsXPCComponents_##_n> ret = m##_n; \
2876 ret.forget(a##_n); \
2877 return NS_OK; \
2878 }
2879
XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase,Interfaces)2880 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Interfaces)
2881 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, InterfacesByID)
2882 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes)
2883 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ClassesByID)
2884 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Results)
2885 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID)
2886 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception)
2887 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor)
2888 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils)
2889
2890 #undef XPC_IMPL_GET_OBJ_METHOD
2891 /*******************************************/
2892
2893 NS_IMETHODIMP
2894 nsXPCComponentsBase::IsSuccessCode(nsresult result, bool* out) {
2895 *out = NS_SUCCEEDED(result);
2896 return NS_OK;
2897 }
2898
2899 NS_IMETHODIMP
GetStack(nsIStackFrame ** aStack)2900 nsXPCComponents::GetStack(nsIStackFrame** aStack) {
2901 nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
2902 frame.forget(aStack);
2903 return NS_OK;
2904 }
2905
2906 NS_IMETHODIMP
GetManager(nsIComponentManager ** aManager)2907 nsXPCComponents::GetManager(nsIComponentManager** aManager) {
2908 MOZ_ASSERT(aManager, "bad param");
2909 return NS_GetComponentManager(aManager);
2910 }
2911
2912 NS_IMETHODIMP
GetReturnCode(JSContext * aCx,MutableHandleValue aOut)2913 nsXPCComponents::GetReturnCode(JSContext* aCx, MutableHandleValue aOut) {
2914 nsresult res = XPCJSContext::Get()->GetPendingResult();
2915 aOut.setNumber(static_cast<uint32_t>(res));
2916 return NS_OK;
2917 }
2918
2919 NS_IMETHODIMP
SetReturnCode(JSContext * aCx,HandleValue aCode)2920 nsXPCComponents::SetReturnCode(JSContext* aCx, HandleValue aCode) {
2921 nsresult rv;
2922 if (!ToUint32(aCx, aCode, (uint32_t*)&rv)) return NS_ERROR_FAILURE;
2923 XPCJSContext::Get()->SetPendingResult(rv);
2924 return NS_OK;
2925 }
2926
2927 /**********************************************/
2928
2929 class ComponentsSH : public nsIXPCScriptable {
2930 public:
ComponentsSH(unsigned dummy)2931 explicit constexpr ComponentsSH(unsigned dummy) {}
2932
2933 // We don't actually inherit any ref counting infrastructure, but we don't
2934 // need an nsAutoRefCnt member, so the _INHERITED macro is a hack to avoid
2935 // having one.
2936 NS_DECL_ISUPPORTS_INHERITED
2937 NS_DECL_NSIXPCSCRIPTABLE
Get(nsIXPCScriptable ** helper)2938 static nsresult Get(nsIXPCScriptable** helper) {
2939 *helper = &singleton;
2940 return NS_OK;
2941 }
2942
2943 private:
2944 static ComponentsSH singleton;
2945 };
2946
2947 ComponentsSH ComponentsSH::singleton(0);
2948
2949 // Singleton refcounting.
NS_IMETHODIMP_(MozExternalRefCountType)2950 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::AddRef(void) { return 1; }
NS_IMETHODIMP_(MozExternalRefCountType)2951 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::Release(void) {
2952 return 1;
2953 }
2954
NS_IMPL_QUERY_INTERFACE(ComponentsSH,nsIXPCScriptable)2955 NS_IMPL_QUERY_INTERFACE(ComponentsSH, nsIXPCScriptable)
2956
2957 #define NSXPCCOMPONENTSBASE_CID \
2958 { \
2959 0xc62998e5, 0x95f1, 0x4058, { \
2960 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 \
2961 } \
2962 }
2963
2964 #define NSXPCCOMPONENTS_CID \
2965 { \
2966 0x3649f405, 0xf0ec, 0x4c28, { \
2967 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 \
2968 } \
2969 }
2970
2971 NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get,
2972 nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID)
2973 NS_IMPL_ISUPPORTS_CI(nsXPCComponentsBase, nsIXPCComponentsBase)
2974
2975 NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT,
2976 NSXPCCOMPONENTS_CID)
2977 // Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like
2978 // if it existed.
2979 NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase)
2980 NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase)
2981 NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
2982 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
2983 NS_IMPL_QUERY_CLASSINFO(nsXPCComponents)
2984 NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase)
2985 NS_IMPL_CI_INTERFACE_GETTER(nsXPCComponents, nsIXPCComponents)
2986
2987 // The nsIXPCScriptable map declaration that will generate stubs for us
2988 #define XPC_MAP_CLASSNAME ComponentsSH
2989 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents"
2990 #define XPC_MAP_FLAGS XPC_SCRIPTABLE_WANT_PRECREATE
2991 #include "xpc_map_end.h" /* This will #undef the above */
2992
2993 NS_IMETHODIMP
2994 ComponentsSH::PreCreate(nsISupports* nativeObj, JSContext* cx,
2995 JSObject* globalObj, JSObject** parentObj) {
2996 nsXPCComponentsBase* self = static_cast<nsXPCComponentsBase*>(nativeObj);
2997 // this should never happen
2998 if (!self->GetScope()) {
2999 NS_WARNING(
3000 "mScope must not be null when nsXPCComponents::PreCreate is called");
3001 return NS_ERROR_FAILURE;
3002 }
3003 *parentObj = self->GetScope()->GetGlobalJSObject();
3004 return NS_OK;
3005 }
3006