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