Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
7 /* The "Components" xpcom objects for JavaScript. */
9 #include "xpcprivate.h"
10 #include "xpcIJSModuleLoader.h"
11 #include "XPCJSWeakReference.h"
12 #include "WrapperFactory.h"
13 #include "nsJSUtils.h"
14 #include "mozJSComponentLoader.h"
15 #include "nsContentUtils.h"
16 #include "jsfriendapi.h"
17 #include "js/StructuredClone.h"
18 #include "mozilla/Attributes.h"
19 #include "nsJSEnvironment.h"
20 #include "mozilla/XPTInterfaceInfoManager.h"
21 #include "mozilla/dom/DOMException.h"
22 #include "mozilla/dom/DOMExceptionBinding.h"
23 #include "mozilla/dom/BindingUtils.h"
24 #include "mozilla/dom/StructuredCloneTags.h"
25 #include "nsZipArchive.h"
26 #include "nsIDOMFile.h"
27 #include "nsIDOMFileList.h"
28 #include "nsWindowMemoryReporter.h"
30 using namespace mozilla;
31 using namespace JS;
32 using namespace js;
33 using namespace xpc;
34 using mozilla::dom::Exception;
36 /***************************************************************************/
37 // stuff used by all
39 nsresult
40 xpc::ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval)
41 {
42 XPCThrower::Throw(errNum, cx);
43 *retval = false;
44 return NS_OK;
45 }
47 static bool
48 JSValIsInterfaceOfType(JSContext *cx, HandleValue v, REFNSIID iid)
49 {
51 nsCOMPtr<nsIXPConnectWrappedNative> wn;
52 nsCOMPtr<nsISupports> sup;
53 nsISupports* iface;
55 if (v.isPrimitive())
56 return false;
58 nsXPConnect* xpc = nsXPConnect::XPConnect();
59 RootedObject obj(cx, &v.toObject());
60 if (NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) && wn &&
61 NS_SUCCEEDED(wn->Native()->QueryInterface(iid, (void**)&iface)) && iface)
62 {
63 NS_RELEASE(iface);
64 return true;
65 }
66 return false;
67 }
69 char *
70 xpc::CloneAllAccess()
71 {
72 static const char allAccess[] = "AllAccess";
73 return (char*)nsMemory::Clone(allAccess, sizeof(allAccess));
74 }
76 char *
77 xpc::CheckAccessList(const char16_t *wideName, const char *const list[])
78 {
79 nsAutoCString asciiName;
80 CopyUTF16toUTF8(nsDependentString(wideName), asciiName);
82 for (const char* const* p = list; *p; p++)
83 if (!strcmp(*p, asciiName.get()))
84 return CloneAllAccess();
86 return nullptr;
87 }
89 /***************************************************************************/
90 /***************************************************************************/
91 /***************************************************************************/
94 class nsXPCComponents_Interfaces :
95 public nsIXPCComponents_Interfaces,
96 public nsIXPCScriptable,
97 public nsIClassInfo
98 {
99 public:
100 // all the interface method declarations...
101 NS_DECL_ISUPPORTS
102 NS_DECL_NSIXPCCOMPONENTS_INTERFACES
103 NS_DECL_NSIXPCSCRIPTABLE
104 NS_DECL_NSICLASSINFO
106 public:
107 nsXPCComponents_Interfaces();
108 virtual ~nsXPCComponents_Interfaces();
110 private:
111 nsCOMArray<nsIInterfaceInfo> mInterfaces;
112 };
114 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
115 out nsIIDPtr array); */
116 NS_IMETHODIMP
117 nsXPCComponents_Interfaces::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
118 {
119 const uint32_t count = 2;
120 *aCount = count;
121 nsIID **array;
122 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
123 if (!array)
124 return NS_ERROR_OUT_OF_MEMORY;
126 uint32_t index = 0;
127 nsIID* clone;
128 #define PUSH_IID(id) \
129 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
130 sizeof(nsIID))); \
131 if (!clone) \
132 goto oom; \
133 array[index++] = clone;
135 PUSH_IID(nsIXPCComponents_Interfaces)
136 PUSH_IID(nsIXPCScriptable)
137 #undef PUSH_IID
139 return NS_OK;
140 oom:
141 while (index)
142 nsMemory::Free(array[--index]);
143 nsMemory::Free(array);
144 *aArray = nullptr;
145 return NS_ERROR_OUT_OF_MEMORY;
146 }
148 /* nsISupports getHelperForLanguage (in uint32_t language); */
149 NS_IMETHODIMP
150 nsXPCComponents_Interfaces::GetHelperForLanguage(uint32_t language,
151 nsISupports **retval)
152 {
153 *retval = nullptr;
154 return NS_OK;
155 }
157 /* readonly attribute string contractID; */
158 NS_IMETHODIMP
159 nsXPCComponents_Interfaces::GetContractID(char * *aContractID)
160 {
161 *aContractID = nullptr;
162 return NS_ERROR_NOT_AVAILABLE;
163 }
165 /* readonly attribute string classDescription; */
166 NS_IMETHODIMP
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 }
174 /* readonly attribute nsCIDPtr classID; */
175 NS_IMETHODIMP
176 nsXPCComponents_Interfaces::GetClassID(nsCID * *aClassID)
177 {
178 *aClassID = nullptr;
179 return NS_OK;
180 }
182 /* readonly attribute uint32_t implementationLanguage; */
183 NS_IMETHODIMP
184 nsXPCComponents_Interfaces::GetImplementationLanguage(uint32_t *aImplementationLanguage)
185 {
186 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
187 return NS_OK;
188 }
190 /* readonly attribute uint32_t flags; */
191 NS_IMETHODIMP
192 nsXPCComponents_Interfaces::GetFlags(uint32_t *aFlags)
193 {
194 // Mark ourselves as a DOM object so that instances may be created in
195 // unprivileged scopes.
196 *aFlags = nsIClassInfo::DOM_OBJECT;
197 return NS_OK;
198 }
200 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
201 NS_IMETHODIMP
202 nsXPCComponents_Interfaces::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
203 {
204 return NS_ERROR_NOT_AVAILABLE;
205 }
207 nsXPCComponents_Interfaces::nsXPCComponents_Interfaces()
208 {
209 }
211 nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces()
212 {
213 // empty
214 }
217 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces)
218 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Interfaces)
219 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
220 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
221 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Interfaces)
222 NS_INTERFACE_MAP_END
224 NS_IMPL_ADDREF(nsXPCComponents_Interfaces)
225 NS_IMPL_RELEASE(nsXPCComponents_Interfaces)
227 // The nsIXPCScriptable map declaration that will generate stubs for us...
228 #define XPC_MAP_CLASSNAME nsXPCComponents_Interfaces
229 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Interfaces"
230 #define XPC_MAP_WANT_NEWRESOLVE
231 #define XPC_MAP_WANT_NEWENUMERATE
232 #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
233 nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
234 #include "xpc_map_end.h" /* This will #undef the above */
237 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
238 NS_IMETHODIMP
239 nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
240 JSContext * cx, JSObject * obj,
241 uint32_t enum_op, jsval * statep,
242 jsid * idp, bool *_retval)
243 {
244 switch (enum_op) {
245 case JSENUMERATE_INIT:
246 case JSENUMERATE_INIT_ALL:
247 {
248 // Lazily init the list of interfaces when someone tries to
249 // enumerate them.
250 if (mInterfaces.IsEmpty()) {
251 XPTInterfaceInfoManager::GetSingleton()->
252 GetScriptableInterfaces(mInterfaces);
253 }
255 *statep = JSVAL_ZERO;
256 if (idp)
257 *idp = INT_TO_JSID(mInterfaces.Length());
258 return NS_OK;
259 }
260 case JSENUMERATE_NEXT:
261 {
262 uint32_t idx = JSVAL_TO_INT(*statep);
263 nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
264 *statep = UINT_TO_JSVAL(idx + 1);
266 if (interface) {
267 const char* name;
269 RootedId id(cx);
270 if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) {
271 RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
272 if (idstr && JS_StringToId(cx, idstr, &id)) {
273 *idp = id;
274 return NS_OK;
275 }
276 }
277 }
278 // fall through
279 }
281 case JSENUMERATE_DESTROY:
282 default:
283 *statep = JSVAL_NULL;
284 return NS_OK;
285 }
286 }
288 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
289 NS_IMETHODIMP
290 nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper,
291 JSContext *cx, JSObject *objArg,
292 jsid idArg, JSObject **objp,
293 bool *_retval)
294 {
295 RootedObject obj(cx, objArg);
296 RootedId id(cx, idArg);
298 if (!JSID_IS_STRING(id))
299 return NS_OK;
301 JSAutoByteString name;
302 RootedString str(cx, JSID_TO_STRING(id));
304 // we only allow interfaces by name here
305 if (name.encodeLatin1(cx, str) && name.ptr()[0] != '{') {
306 nsCOMPtr<nsIInterfaceInfo> info;
307 XPTInterfaceInfoManager::GetSingleton()->
308 GetInfoForName(name.ptr(), getter_AddRefs(info));
309 if (!info)
310 return NS_OK;
312 nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
314 if (nsid) {
315 nsXPConnect* xpc = nsXPConnect::XPConnect();
316 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
317 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
318 static_cast<nsIJSIID*>(nsid),
319 NS_GET_IID(nsIJSIID),
320 getter_AddRefs(holder)))) {
321 RootedObject idobj(cx);
322 if (holder &&
323 // Assign, not compare
324 (idobj = holder->GetJSObject())) {
325 *objp = obj;
326 *_retval = JS_DefinePropertyById(cx, obj, id,
327 OBJECT_TO_JSVAL(idobj),
328 nullptr, nullptr,
329 JSPROP_ENUMERATE |
330 JSPROP_READONLY |
331 JSPROP_PERMANENT);
332 }
333 }
334 }
335 }
336 return NS_OK;
337 }
339 /***************************************************************************/
340 /***************************************************************************/
341 /***************************************************************************/
343 class nsXPCComponents_InterfacesByID :
344 public nsIXPCComponents_InterfacesByID,
345 public nsIXPCScriptable,
346 public nsIClassInfo
347 {
348 public:
349 // all the interface method declarations...
350 NS_DECL_ISUPPORTS
351 NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID
352 NS_DECL_NSIXPCSCRIPTABLE
353 NS_DECL_NSICLASSINFO
355 public:
356 nsXPCComponents_InterfacesByID();
357 virtual ~nsXPCComponents_InterfacesByID();
359 private:
360 nsCOMArray<nsIInterfaceInfo> mInterfaces;
361 };
363 /***************************************************************************/
364 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
365 out nsIIDPtr array); */
366 NS_IMETHODIMP
367 nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
368 {
369 const uint32_t count = 2;
370 *aCount = count;
371 nsIID **array;
372 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
373 if (!array)
374 return NS_ERROR_OUT_OF_MEMORY;
376 uint32_t index = 0;
377 nsIID* clone;
378 #define PUSH_IID(id) \
379 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
380 sizeof(nsIID))); \
381 if (!clone) \
382 goto oom; \
383 array[index++] = clone;
385 PUSH_IID(nsIXPCComponents_InterfacesByID)
386 PUSH_IID(nsIXPCScriptable)
387 #undef PUSH_IID
389 return NS_OK;
390 oom:
391 while (index)
392 nsMemory::Free(array[--index]);
393 nsMemory::Free(array);
394 *aArray = nullptr;
395 return NS_ERROR_OUT_OF_MEMORY;
396 }
398 /* nsISupports getHelperForLanguage (in uint32_t language); */
399 NS_IMETHODIMP
400 nsXPCComponents_InterfacesByID::GetHelperForLanguage(uint32_t language,
401 nsISupports **retval)
402 {
403 *retval = nullptr;
404 return NS_OK;
405 }
407 /* readonly attribute string contractID; */
408 NS_IMETHODIMP
409 nsXPCComponents_InterfacesByID::GetContractID(char * *aContractID)
410 {
411 *aContractID = nullptr;
412 return NS_ERROR_NOT_AVAILABLE;
413 }
415 /* readonly attribute string classDescription; */
416 NS_IMETHODIMP
417 nsXPCComponents_InterfacesByID::GetClassDescription(char * *aClassDescription)
418 {
419 static const char classDescription[] = "XPCComponents_InterfacesByID";
420 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
421 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
422 }
424 /* readonly attribute nsCIDPtr classID; */
425 NS_IMETHODIMP
426 nsXPCComponents_InterfacesByID::GetClassID(nsCID * *aClassID)
427 {
428 *aClassID = nullptr;
429 return NS_OK;
430 }
432 /* readonly attribute uint32_t implementationLanguage; */
433 NS_IMETHODIMP
434 nsXPCComponents_InterfacesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
435 {
436 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
437 return NS_OK;
438 }
440 /* readonly attribute uint32_t flags; */
441 NS_IMETHODIMP
442 nsXPCComponents_InterfacesByID::GetFlags(uint32_t *aFlags)
443 {
444 // Mark ourselves as a DOM object so that instances may be created in
445 // unprivileged scopes.
446 *aFlags = nsIClassInfo::DOM_OBJECT;
447 return NS_OK;
448 }
450 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
451 NS_IMETHODIMP
452 nsXPCComponents_InterfacesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
453 {
454 return NS_ERROR_NOT_AVAILABLE;
455 }
457 nsXPCComponents_InterfacesByID::nsXPCComponents_InterfacesByID()
458 {
459 }
461 nsXPCComponents_InterfacesByID::~nsXPCComponents_InterfacesByID()
462 {
463 // empty
464 }
466 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID)
467 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_InterfacesByID)
468 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
469 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
470 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_InterfacesByID)
471 NS_INTERFACE_MAP_END
473 NS_IMPL_ADDREF(nsXPCComponents_InterfacesByID)
474 NS_IMPL_RELEASE(nsXPCComponents_InterfacesByID)
476 // The nsIXPCScriptable map declaration that will generate stubs for us...
477 #define XPC_MAP_CLASSNAME nsXPCComponents_InterfacesByID
478 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_InterfacesByID"
479 #define XPC_MAP_WANT_NEWRESOLVE
480 #define XPC_MAP_WANT_NEWENUMERATE
481 #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
482 nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
483 #include "xpc_map_end.h" /* This will #undef the above */
485 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
486 NS_IMETHODIMP
487 nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
488 JSContext * cx, JSObject * obj,
489 uint32_t enum_op, jsval * statep,
490 jsid * idp, bool *_retval)
491 {
492 switch (enum_op) {
493 case JSENUMERATE_INIT:
494 case JSENUMERATE_INIT_ALL:
495 {
496 // Lazily init the list of interfaces when someone tries to
497 // enumerate them.
498 if (mInterfaces.IsEmpty()) {
499 XPTInterfaceInfoManager::GetSingleton()->
500 GetScriptableInterfaces(mInterfaces);
501 }
503 *statep = JSVAL_ZERO;
504 if (idp)
505 *idp = INT_TO_JSID(mInterfaces.Length());
506 return NS_OK;
507 }
508 case JSENUMERATE_NEXT:
509 {
510 uint32_t idx = JSVAL_TO_INT(*statep);
511 nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
512 *statep = UINT_TO_JSVAL(idx + 1);
513 if (interface) {
514 nsIID const *iid;
515 char idstr[NSID_LENGTH];
517 if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
518 iid->ToProvidedString(idstr);
519 RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr));
520 RootedId id(cx);
521 if (jsstr && JS_StringToId(cx, jsstr, &id)) {
522 *idp = id;
523 return NS_OK;
524 }
525 }
526 }
527 // FALL THROUGH
528 }
530 case JSENUMERATE_DESTROY:
531 default:
532 *statep = JSVAL_NULL;
533 return NS_OK;
534 }
535 }
537 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
538 NS_IMETHODIMP
539 nsXPCComponents_InterfacesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
540 JSContext *cx, JSObject *objArg,
541 jsid idArg, JSObject **objp,
542 bool *_retval)
543 {
544 RootedObject obj(cx, objArg);
545 RootedId id(cx, idArg);
547 if (!JSID_IS_STRING(id))
548 return NS_OK;
550 RootedString str(cx, JSID_TO_STRING(id));
551 if (38 != JS_GetStringLength(str))
552 return NS_OK;
554 if (const jschar *name = JS_GetInternedStringChars(str)) {
555 nsID iid;
556 if (!iid.Parse(NS_ConvertUTF16toUTF8(name).get()))
557 return NS_OK;
559 nsCOMPtr<nsIInterfaceInfo> info;
560 XPTInterfaceInfoManager::GetSingleton()->
561 GetInfoForIID(&iid, getter_AddRefs(info));
562 if (!info)
563 return NS_OK;
565 nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
567 if (!nsid)
568 return NS_ERROR_OUT_OF_MEMORY;
570 nsXPConnect* xpc = nsXPConnect::XPConnect();
571 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
572 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
573 static_cast<nsIJSIID*>(nsid),
574 NS_GET_IID(nsIJSIID),
575 getter_AddRefs(holder)))) {
576 RootedObject idobj(cx);
577 if (holder &&
578 // Assign, not compare
579 (idobj = holder->GetJSObject())) {
580 *objp = obj;
581 *_retval =
582 JS_DefinePropertyById(cx, obj, id,
583 OBJECT_TO_JSVAL(idobj),
584 nullptr, nullptr,
585 JSPROP_ENUMERATE |
586 JSPROP_READONLY |
587 JSPROP_PERMANENT);
588 }
589 }
590 }
591 return NS_OK;
592 }
594 /***************************************************************************/
595 /***************************************************************************/
596 /***************************************************************************/
600 class nsXPCComponents_Classes :
601 public nsIXPCComponents_Classes,
602 public nsIXPCScriptable,
603 public nsIClassInfo
604 {
605 public:
606 // all the interface method declarations...
607 NS_DECL_ISUPPORTS
608 NS_DECL_NSIXPCCOMPONENTS_CLASSES
609 NS_DECL_NSIXPCSCRIPTABLE
610 NS_DECL_NSICLASSINFO
612 public:
613 nsXPCComponents_Classes();
614 virtual ~nsXPCComponents_Classes();
615 };
617 /***************************************************************************/
618 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
619 out nsIIDPtr array); */
620 NS_IMETHODIMP
621 nsXPCComponents_Classes::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
622 {
623 const uint32_t count = 2;
624 *aCount = count;
625 nsIID **array;
626 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
627 if (!array)
628 return NS_ERROR_OUT_OF_MEMORY;
630 uint32_t index = 0;
631 nsIID* clone;
632 #define PUSH_IID(id) \
633 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
634 sizeof(nsIID))); \
635 if (!clone) \
636 goto oom; \
637 array[index++] = clone;
639 PUSH_IID(nsIXPCComponents_Classes)
640 PUSH_IID(nsIXPCScriptable)
641 #undef PUSH_IID
643 return NS_OK;
644 oom:
645 while (index)
646 nsMemory::Free(array[--index]);
647 nsMemory::Free(array);
648 *aArray = nullptr;
649 return NS_ERROR_OUT_OF_MEMORY;
650 }
652 /* nsISupports getHelperForLanguage (in uint32_t language); */
653 NS_IMETHODIMP
654 nsXPCComponents_Classes::GetHelperForLanguage(uint32_t language,
655 nsISupports **retval)
656 {
657 *retval = nullptr;
658 return NS_OK;
659 }
661 /* readonly attribute string contractID; */
662 NS_IMETHODIMP
663 nsXPCComponents_Classes::GetContractID(char * *aContractID)
664 {
665 *aContractID = nullptr;
666 return NS_ERROR_NOT_AVAILABLE;
667 }
669 /* readonly attribute string classDescription; */
670 NS_IMETHODIMP
671 nsXPCComponents_Classes::GetClassDescription(char * *aClassDescription)
672 {
673 static const char classDescription[] = "XPCComponents_Classes";
674 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
675 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
676 }
678 /* readonly attribute nsCIDPtr classID; */
679 NS_IMETHODIMP
680 nsXPCComponents_Classes::GetClassID(nsCID * *aClassID)
681 {
682 *aClassID = nullptr;
683 return NS_OK;
684 }
686 /* readonly attribute uint32_t implementationLanguage; */
687 NS_IMETHODIMP
688 nsXPCComponents_Classes::GetImplementationLanguage(uint32_t *aImplementationLanguage)
689 {
690 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
691 return NS_OK;
692 }
694 /* readonly attribute uint32_t flags; */
695 NS_IMETHODIMP
696 nsXPCComponents_Classes::GetFlags(uint32_t *aFlags)
697 {
698 *aFlags = 0;
699 return NS_OK;
700 }
702 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
703 NS_IMETHODIMP
704 nsXPCComponents_Classes::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
705 {
706 return NS_ERROR_NOT_AVAILABLE;
707 }
709 nsXPCComponents_Classes::nsXPCComponents_Classes()
710 {
711 }
713 nsXPCComponents_Classes::~nsXPCComponents_Classes()
714 {
715 // empty
716 }
718 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Classes)
719 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Classes)
720 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
721 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
722 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Classes)
723 NS_INTERFACE_MAP_END
725 NS_IMPL_ADDREF(nsXPCComponents_Classes)
726 NS_IMPL_RELEASE(nsXPCComponents_Classes)
728 // The nsIXPCScriptable map declaration that will generate stubs for us...
729 #define XPC_MAP_CLASSNAME nsXPCComponents_Classes
730 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Classes"
731 #define XPC_MAP_WANT_NEWRESOLVE
732 #define XPC_MAP_WANT_NEWENUMERATE
733 #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
734 nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
735 #include "xpc_map_end.h" /* This will #undef the above */
738 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
739 NS_IMETHODIMP
740 nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
741 JSContext * cx, JSObject * obj,
742 uint32_t enum_op, jsval * statep,
743 jsid * idp, bool *_retval)
744 {
745 nsISimpleEnumerator* e;
747 switch (enum_op) {
748 case JSENUMERATE_INIT:
749 case JSENUMERATE_INIT_ALL:
750 {
751 nsCOMPtr<nsIComponentRegistrar> compMgr;
752 if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
753 NS_FAILED(compMgr->EnumerateContractIDs(&e)) || !e ) {
754 *statep = JSVAL_NULL;
755 return NS_ERROR_UNEXPECTED;
756 }
758 *statep = PRIVATE_TO_JSVAL(e);
759 if (idp)
760 *idp = INT_TO_JSID(0); // indicate that we don't know the count
761 return NS_OK;
762 }
763 case JSENUMERATE_NEXT:
764 {
765 nsCOMPtr<nsISupports> isup;
766 bool hasMore;
767 e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
769 if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
770 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
771 nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
772 if (holder) {
773 nsAutoCString name;
774 if (NS_SUCCEEDED(holder->GetData(name))) {
775 RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
776 RootedId id(cx);
777 if (idstr && JS_StringToId(cx, idstr, &id)) {
778 *idp = id;
779 return NS_OK;
780 }
781 }
782 }
783 }
784 // else... FALL THROUGH
785 }
787 case JSENUMERATE_DESTROY:
788 default:
789 e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
790 NS_IF_RELEASE(e);
791 *statep = JSVAL_NULL;
792 return NS_OK;
793 }
794 }
796 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
797 NS_IMETHODIMP
798 nsXPCComponents_Classes::NewResolve(nsIXPConnectWrappedNative *wrapper,
799 JSContext *cx, JSObject *objArg,
800 jsid idArg, JSObject **objp,
801 bool *_retval)
803 {
804 RootedId id(cx, idArg);
805 RootedObject obj(cx, objArg);
807 JSAutoByteString name;
808 if (JSID_IS_STRING(id) &&
809 name.encodeLatin1(cx, JSID_TO_STRING(id)) &&
810 name.ptr()[0] != '{') { // we only allow contractids here
811 nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
812 if (nsid) {
813 nsXPConnect* xpc = nsXPConnect::XPConnect();
814 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
815 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
816 static_cast<nsIJSCID*>(nsid),
817 NS_GET_IID(nsIJSCID),
818 getter_AddRefs(holder)))) {
819 RootedObject idobj(cx);
820 if (holder &&
821 // Assign, not compare
822 (idobj = holder->GetJSObject())) {
823 *objp = obj;
824 *_retval = JS_DefinePropertyById(cx, obj, id,
825 OBJECT_TO_JSVAL(idobj),
826 nullptr, nullptr,
827 JSPROP_ENUMERATE |
828 JSPROP_READONLY |
829 JSPROP_PERMANENT);
830 }
831 }
832 }
833 }
834 return NS_OK;
835 }
837 /***************************************************************************/
838 /***************************************************************************/
839 /***************************************************************************/
841 class nsXPCComponents_ClassesByID :
842 public nsIXPCComponents_ClassesByID,
843 public nsIXPCScriptable,
844 public nsIClassInfo
845 {
846 public:
847 // all the interface method declarations...
848 NS_DECL_ISUPPORTS
849 NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID
850 NS_DECL_NSIXPCSCRIPTABLE
851 NS_DECL_NSICLASSINFO
853 public:
854 nsXPCComponents_ClassesByID();
855 virtual ~nsXPCComponents_ClassesByID();
856 };
858 /***************************************************************************/
859 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
860 out nsIIDPtr array); */
861 NS_IMETHODIMP
862 nsXPCComponents_ClassesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
863 {
864 const uint32_t count = 2;
865 *aCount = count;
866 nsIID **array;
867 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
868 if (!array)
869 return NS_ERROR_OUT_OF_MEMORY;
871 uint32_t index = 0;
872 nsIID* clone;
873 #define PUSH_IID(id) \
874 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
875 sizeof(nsIID))); \
876 if (!clone) \
877 goto oom; \
878 array[index++] = clone;
880 PUSH_IID(nsIXPCComponents_ClassesByID)
881 PUSH_IID(nsIXPCScriptable)
882 #undef PUSH_IID
884 return NS_OK;
885 oom:
886 while (index)
887 nsMemory::Free(array[--index]);
888 nsMemory::Free(array);
889 *aArray = nullptr;
890 return NS_ERROR_OUT_OF_MEMORY;
891 }
893 /* nsISupports getHelperForLanguage (in uint32_t language); */
894 NS_IMETHODIMP
895 nsXPCComponents_ClassesByID::GetHelperForLanguage(uint32_t language,
896 nsISupports **retval)
897 {
898 *retval = nullptr;
899 return NS_OK;
900 }
902 /* readonly attribute string contractID; */
903 NS_IMETHODIMP
904 nsXPCComponents_ClassesByID::GetContractID(char * *aContractID)
905 {
906 *aContractID = nullptr;
907 return NS_ERROR_NOT_AVAILABLE;
908 }
910 /* readonly attribute string classDescription; */
911 NS_IMETHODIMP
912 nsXPCComponents_ClassesByID::GetClassDescription(char * *aClassDescription)
913 {
914 static const char classDescription[] = "XPCComponents_ClassesByID";
915 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
916 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
917 }
919 /* readonly attribute nsCIDPtr classID; */
920 NS_IMETHODIMP
921 nsXPCComponents_ClassesByID::GetClassID(nsCID * *aClassID)
922 {
923 *aClassID = nullptr;
924 return NS_OK;
925 }
927 /* readonly attribute uint32_t implementationLanguage; */
928 NS_IMETHODIMP
929 nsXPCComponents_ClassesByID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
930 {
931 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
932 return NS_OK;
933 }
935 /* readonly attribute uint32_t flags; */
936 NS_IMETHODIMP
937 nsXPCComponents_ClassesByID::GetFlags(uint32_t *aFlags)
938 {
939 *aFlags = 0;
940 return NS_OK;
941 }
943 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
944 NS_IMETHODIMP
945 nsXPCComponents_ClassesByID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
946 {
947 return NS_ERROR_NOT_AVAILABLE;
948 }
950 nsXPCComponents_ClassesByID::nsXPCComponents_ClassesByID()
951 {
952 }
954 nsXPCComponents_ClassesByID::~nsXPCComponents_ClassesByID()
955 {
956 // empty
957 }
959 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ClassesByID)
960 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ClassesByID)
961 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
962 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
963 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ClassesByID)
964 NS_INTERFACE_MAP_END
966 NS_IMPL_ADDREF(nsXPCComponents_ClassesByID)
967 NS_IMPL_RELEASE(nsXPCComponents_ClassesByID)
969 // The nsIXPCScriptable map declaration that will generate stubs for us...
970 #define XPC_MAP_CLASSNAME nsXPCComponents_ClassesByID
971 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ClassesByID"
972 #define XPC_MAP_WANT_NEWRESOLVE
973 #define XPC_MAP_WANT_NEWENUMERATE
974 #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
975 nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
976 #include "xpc_map_end.h" /* This will #undef the above */
978 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
979 NS_IMETHODIMP
980 nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
981 JSContext * cx, JSObject * obj,
982 uint32_t enum_op, jsval * statep,
983 jsid * idp, bool *_retval)
984 {
985 nsISimpleEnumerator* e;
987 switch (enum_op) {
988 case JSENUMERATE_INIT:
989 case JSENUMERATE_INIT_ALL:
990 {
991 nsCOMPtr<nsIComponentRegistrar> compMgr;
992 if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
993 NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e ) {
994 *statep = JSVAL_NULL;
995 return NS_ERROR_UNEXPECTED;
996 }
998 *statep = PRIVATE_TO_JSVAL(e);
999 if (idp)
1000 *idp = INT_TO_JSID(0); // indicate that we don't know the count
1001 return NS_OK;
1002 }
1003 case JSENUMERATE_NEXT:
1004 {
1005 nsCOMPtr<nsISupports> isup;
1006 bool hasMore;
1007 e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
1009 if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
1010 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
1011 nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
1012 if (holder) {
1013 char* name;
1014 if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
1015 RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
1016 nsMemory::Free(name);
1017 RootedId id(cx);
1018 if (idstr && JS_StringToId(cx, idstr, &id)) {
1019 *idp = id;
1020 return NS_OK;
1021 }
1022 }
1023 }
1024 }
1025 // else... FALL THROUGH
1026 }
1028 case JSENUMERATE_DESTROY:
1029 default:
1030 e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
1031 NS_IF_RELEASE(e);
1032 *statep = JSVAL_NULL;
1033 return NS_OK;
1034 }
1035 }
1037 static bool
1038 IsRegisteredCLSID(const char* str)
1039 {
1040 bool registered;
1041 nsID id;
1043 if (!id.Parse(str))
1044 return false;
1046 nsCOMPtr<nsIComponentRegistrar> compMgr;
1047 if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
1048 NS_FAILED(compMgr->IsCIDRegistered(id, ®istered)))
1049 return false;
1051 return registered;
1052 }
1054 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
1055 NS_IMETHODIMP
1056 nsXPCComponents_ClassesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
1057 JSContext *cx, JSObject *objArg,
1058 jsid idArg, JSObject **objp,
1059 bool *_retval)
1060 {
1061 RootedObject obj(cx, objArg);
1062 RootedId id(cx, idArg);
1064 if (!JSID_IS_STRING(id))
1065 return NS_OK;
1067 JSAutoByteString name;
1068 RootedString str(cx, JSID_TO_STRING(id));
1069 if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' &&
1070 IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
1071 {
1072 nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
1073 if (nsid) {
1074 nsXPConnect* xpc = nsXPConnect::XPConnect();
1075 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
1076 if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
1077 static_cast<nsIJSCID*>(nsid),
1078 NS_GET_IID(nsIJSCID),
1079 getter_AddRefs(holder)))) {
1080 RootedObject idobj(cx);
1081 if (holder &&
1082 // Assign, not compare
1083 (idobj = holder->GetJSObject())) {
1084 *objp = obj;
1085 *_retval = JS_DefinePropertyById(cx, obj, id,
1086 ObjectValue(*idobj),
1087 nullptr, nullptr,
1088 JSPROP_ENUMERATE |
1089 JSPROP_READONLY |
1090 JSPROP_PERMANENT);
1091 }
1092 }
1093 }
1094 }
1095 return NS_OK;
1096 }
1099 /***************************************************************************/
1101 // Currently the possible results do not change at runtime, so they are only
1102 // cached once (unlike ContractIDs, CLSIDs, and IIDs)
1104 class nsXPCComponents_Results :
1105 public nsIXPCComponents_Results,
1106 public nsIXPCScriptable,
1107 public nsIClassInfo
1108 {
1109 public:
1110 // all the interface method declarations...
1111 NS_DECL_ISUPPORTS
1112 NS_DECL_NSIXPCCOMPONENTS_RESULTS
1113 NS_DECL_NSIXPCSCRIPTABLE
1114 NS_DECL_NSICLASSINFO
1116 public:
1117 nsXPCComponents_Results();
1118 virtual ~nsXPCComponents_Results();
1119 };
1121 /***************************************************************************/
1122 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
1123 out nsIIDPtr array); */
1124 NS_IMETHODIMP
1125 nsXPCComponents_Results::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
1126 {
1127 const uint32_t count = 2;
1128 *aCount = count;
1129 nsIID **array;
1130 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
1131 if (!array)
1132 return NS_ERROR_OUT_OF_MEMORY;
1134 uint32_t index = 0;
1135 nsIID* clone;
1136 #define PUSH_IID(id) \
1137 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
1138 sizeof(nsIID))); \
1139 if (!clone) \
1140 goto oom; \
1141 array[index++] = clone;
1143 PUSH_IID(nsIXPCComponents_Results)
1144 PUSH_IID(nsIXPCScriptable)
1145 #undef PUSH_IID
1147 return NS_OK;
1148 oom:
1149 while (index)
1150 nsMemory::Free(array[--index]);
1151 nsMemory::Free(array);
1152 *aArray = nullptr;
1153 return NS_ERROR_OUT_OF_MEMORY;
1154 }
1156 /* nsISupports getHelperForLanguage (in uint32_t language); */
1157 NS_IMETHODIMP
1158 nsXPCComponents_Results::GetHelperForLanguage(uint32_t language,
1159 nsISupports **retval)
1160 {
1161 *retval = nullptr;
1162 return NS_OK;
1163 }
1165 /* readonly attribute string contractID; */
1166 NS_IMETHODIMP
1167 nsXPCComponents_Results::GetContractID(char * *aContractID)
1168 {
1169 *aContractID = nullptr;
1170 return NS_ERROR_NOT_AVAILABLE;
1171 }
1173 /* readonly attribute string classDescription; */
1174 NS_IMETHODIMP
1175 nsXPCComponents_Results::GetClassDescription(char * *aClassDescription)
1176 {
1177 static const char classDescription[] = "XPCComponents_Results";
1178 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
1179 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1180 }
1182 /* readonly attribute nsCIDPtr classID; */
1183 NS_IMETHODIMP
1184 nsXPCComponents_Results::GetClassID(nsCID * *aClassID)
1185 {
1186 *aClassID = nullptr;
1187 return NS_OK;
1188 }
1190 /* readonly attribute uint32_t implementationLanguage; */
1191 NS_IMETHODIMP
1192 nsXPCComponents_Results::GetImplementationLanguage(uint32_t *aImplementationLanguage)
1193 {
1194 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
1195 return NS_OK;
1196 }
1198 /* readonly attribute uint32_t flags; */
1199 NS_IMETHODIMP
1200 nsXPCComponents_Results::GetFlags(uint32_t *aFlags)
1201 {
1202 // Mark ourselves as a DOM object so that instances may be created in
1203 // unprivileged scopes.
1204 *aFlags = nsIClassInfo::DOM_OBJECT;
1205 return NS_OK;
1206 }
1208 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
1209 NS_IMETHODIMP
1210 nsXPCComponents_Results::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
1211 {
1212 return NS_ERROR_NOT_AVAILABLE;
1213 }
1215 nsXPCComponents_Results::nsXPCComponents_Results()
1216 {
1217 }
1219 nsXPCComponents_Results::~nsXPCComponents_Results()
1220 {
1221 // empty
1222 }
1224 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Results)
1225 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Results)
1226 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
1227 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
1228 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Results)
1229 NS_INTERFACE_MAP_END
1231 NS_IMPL_ADDREF(nsXPCComponents_Results)
1232 NS_IMPL_RELEASE(nsXPCComponents_Results)
1234 // The nsIXPCScriptable map declaration that will generate stubs for us...
1235 #define XPC_MAP_CLASSNAME nsXPCComponents_Results
1236 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Results"
1237 #define XPC_MAP_WANT_NEWRESOLVE
1238 #define XPC_MAP_WANT_NEWENUMERATE
1239 #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
1240 nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
1241 #include "xpc_map_end.h" /* This will #undef the above */
1243 /* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
1244 NS_IMETHODIMP
1245 nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
1246 JSContext * cx, JSObject * obj,
1247 uint32_t enum_op, jsval * statep,
1248 jsid * idp, bool *_retval)
1249 {
1250 const void** iter;
1252 switch (enum_op) {
1253 case JSENUMERATE_INIT:
1254 case JSENUMERATE_INIT_ALL:
1255 {
1256 if (idp)
1257 *idp = INT_TO_JSID(nsXPCException::GetNSResultCount());
1259 void** space = (void**) new char[sizeof(void*)];
1260 *space = nullptr;
1261 *statep = PRIVATE_TO_JSVAL(space);
1262 return NS_OK;
1263 }
1264 case JSENUMERATE_NEXT:
1265 {
1266 const char* name;
1267 iter = (const void**) JSVAL_TO_PRIVATE(*statep);
1268 if (nsXPCException::IterateNSResults(nullptr, &name, nullptr, iter)) {
1269 RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
1270 JS::RootedId id(cx);
1271 if (idstr && JS_StringToId(cx, idstr, &id)) {
1272 *idp = id;
1273 return NS_OK;
1274 }
1275 }
1276 // else... FALL THROUGH
1277 }
1279 case JSENUMERATE_DESTROY:
1280 default:
1281 iter = (const void**) JSVAL_TO_PRIVATE(*statep);
1282 delete [] (char*) iter;
1283 *statep = JSVAL_NULL;
1284 return NS_OK;
1285 }
1286 }
1289 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
1290 NS_IMETHODIMP
1291 nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper,
1292 JSContext *cx, JSObject *objArg,
1293 jsid idArg, JSObject * *objp,
1294 bool *_retval)
1295 {
1296 RootedObject obj(cx, objArg);
1297 RootedId id(cx, idArg);
1298 JSAutoByteString name;
1300 if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) {
1301 const char* rv_name;
1302 const void* iter = nullptr;
1303 nsresult rv;
1304 while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) {
1305 if (!strcmp(name.ptr(), rv_name)) {
1306 jsval val = JS_NumberValue((double)rv);
1308 *objp = obj;
1309 if (!JS_DefinePropertyById(cx, obj, id, val,
1310 nullptr, nullptr,
1311 JSPROP_ENUMERATE |
1312 JSPROP_READONLY |
1313 JSPROP_PERMANENT)) {
1314 return NS_ERROR_UNEXPECTED;
1315 }
1316 }
1317 }
1318 }
1319 return NS_OK;
1320 }
1322 /***************************************************************************/
1323 // JavaScript Constructor for nsIJSID objects (Components.ID)
1325 class nsXPCComponents_ID :
1326 public nsIXPCComponents_ID,
1327 public nsIXPCScriptable,
1328 public nsIClassInfo
1329 {
1330 public:
1331 // all the interface method declarations...
1332 NS_DECL_ISUPPORTS
1333 NS_DECL_NSIXPCCOMPONENTS_ID
1334 NS_DECL_NSIXPCSCRIPTABLE
1335 NS_DECL_NSICLASSINFO
1338 public:
1339 nsXPCComponents_ID();
1340 virtual ~nsXPCComponents_ID();
1342 private:
1343 static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
1344 JSContext *cx, HandleObject obj,
1345 const CallArgs &args, bool *_retval);
1346 };
1348 /***************************************************************************/
1349 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
1350 out nsIIDPtr array); */
1351 NS_IMETHODIMP
1352 nsXPCComponents_ID::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
1353 {
1354 const uint32_t count = 2;
1355 *aCount = count;
1356 nsIID **array;
1357 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
1358 if (!array)
1359 return NS_ERROR_OUT_OF_MEMORY;
1361 uint32_t index = 0;
1362 nsIID* clone;
1363 #define PUSH_IID(id) \
1364 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
1365 sizeof(nsIID))); \
1366 if (!clone) \
1367 goto oom; \
1368 array[index++] = clone;
1370 PUSH_IID(nsIXPCComponents_ID)
1371 PUSH_IID(nsIXPCScriptable)
1372 #undef PUSH_IID
1374 return NS_OK;
1375 oom:
1376 while (index)
1377 nsMemory::Free(array[--index]);
1378 nsMemory::Free(array);
1379 *aArray = nullptr;
1380 return NS_ERROR_OUT_OF_MEMORY;
1381 }
1383 /* nsISupports getHelperForLanguage (in uint32_t language); */
1384 NS_IMETHODIMP
1385 nsXPCComponents_ID::GetHelperForLanguage(uint32_t language,
1386 nsISupports **retval)
1387 {
1388 *retval = nullptr;
1389 return NS_OK;
1390 }
1392 /* readonly attribute string contractID; */
1393 NS_IMETHODIMP
1394 nsXPCComponents_ID::GetContractID(char * *aContractID)
1395 {
1396 *aContractID = nullptr;
1397 return NS_ERROR_NOT_AVAILABLE;
1398 }
1400 /* readonly attribute string classDescription; */
1401 NS_IMETHODIMP
1402 nsXPCComponents_ID::GetClassDescription(char * *aClassDescription)
1403 {
1404 static const char classDescription[] = "XPCComponents_ID";
1405 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
1406 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1407 }
1409 /* readonly attribute nsCIDPtr classID; */
1410 NS_IMETHODIMP
1411 nsXPCComponents_ID::GetClassID(nsCID * *aClassID)
1412 {
1413 *aClassID = nullptr;
1414 return NS_OK;
1415 }
1417 /* readonly attribute uint32_t implementationLanguage; */
1418 NS_IMETHODIMP
1419 nsXPCComponents_ID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
1420 {
1421 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
1422 return NS_OK;
1423 }
1425 /* readonly attribute uint32_t flags; */
1426 NS_IMETHODIMP
1427 nsXPCComponents_ID::GetFlags(uint32_t *aFlags)
1428 {
1429 *aFlags = 0;
1430 return NS_OK;
1431 }
1433 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
1434 NS_IMETHODIMP
1435 nsXPCComponents_ID::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
1436 {
1437 return NS_ERROR_NOT_AVAILABLE;
1438 }
1440 nsXPCComponents_ID::nsXPCComponents_ID()
1441 {
1442 }
1444 nsXPCComponents_ID::~nsXPCComponents_ID()
1445 {
1446 // empty
1447 }
1449 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ID)
1450 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ID)
1451 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
1452 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
1453 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ID)
1454 NS_INTERFACE_MAP_END
1456 NS_IMPL_ADDREF(nsXPCComponents_ID)
1457 NS_IMPL_RELEASE(nsXPCComponents_ID)
1459 // The nsIXPCScriptable map declaration that will generate stubs for us...
1460 #define XPC_MAP_CLASSNAME nsXPCComponents_ID
1461 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_ID"
1462 #define XPC_MAP_WANT_CALL
1463 #define XPC_MAP_WANT_CONSTRUCT
1464 #define XPC_MAP_WANT_HASINSTANCE
1465 #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
1466 #include "xpc_map_end.h" /* This will #undef the above */
1469 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
1470 NS_IMETHODIMP
1471 nsXPCComponents_ID::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
1472 const CallArgs &args, bool *_retval)
1473 {
1474 RootedObject obj(cx, objArg);
1475 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1476 }
1478 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
1479 NS_IMETHODIMP
1480 nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
1481 const CallArgs &args, bool *_retval)
1482 {
1483 RootedObject obj(cx, objArg);
1484 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1485 }
1487 // static
1488 nsresult
1489 nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
1490 JSContext *cx, HandleObject obj,
1491 const CallArgs &args, bool *_retval)
1492 {
1493 // make sure we have at least one arg
1495 if (args.length() < 1)
1496 return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
1498 // Do the security check if necessary
1500 nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager();
1501 if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsJSID::GetCID()))) {
1502 // the security manager vetoed. It should have set an exception.
1503 *_retval = false;
1504 return NS_OK;
1505 }
1507 // convert the first argument into a string and see if it looks like an id
1509 JSString* jsstr;
1510 JSAutoByteString bytes;
1511 nsID id;
1513 if (!(jsstr = ToString(cx, args[0])) ||
1514 !bytes.encodeLatin1(cx, jsstr) ||
1515 !id.Parse(bytes.ptr())) {
1516 return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
1517 }
1519 // make the new object and return it.
1521 JSObject* newobj = xpc_NewIDObject(cx, obj, id);
1522 if (!newobj)
1523 return NS_ERROR_UNEXPECTED;
1525 args.rval().setObject(*newobj);
1526 return NS_OK;
1527 }
1529 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
1530 NS_IMETHODIMP
1531 nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative *wrapper,
1532 JSContext *cx, JSObject *obj,
1533 HandleValue val, bool *bp, bool *_retval)
1534 {
1535 if (bp)
1536 *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIJSID));
1537 return NS_OK;
1538 }
1540 /***************************************************************************/
1541 // JavaScript Constructor for nsIXPCException objects (Components.Exception)
1543 class nsXPCComponents_Exception :
1544 public nsIXPCComponents_Exception,
1545 public nsIXPCScriptable,
1546 public nsIClassInfo
1547 {
1548 public:
1549 // all the interface method declarations...
1550 NS_DECL_ISUPPORTS
1551 NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
1552 NS_DECL_NSIXPCSCRIPTABLE
1553 NS_DECL_NSICLASSINFO
1556 public:
1557 nsXPCComponents_Exception();
1558 virtual ~nsXPCComponents_Exception();
1560 private:
1561 static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
1562 JSContext *cx, HandleObject obj,
1563 const CallArgs &args, bool *_retval);
1564 };
1566 /***************************************************************************/
1567 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
1568 out nsIIDPtr array); */
1569 NS_IMETHODIMP
1570 nsXPCComponents_Exception::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
1571 {
1572 const uint32_t count = 2;
1573 *aCount = count;
1574 nsIID **array;
1575 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
1576 if (!array)
1577 return NS_ERROR_OUT_OF_MEMORY;
1579 uint32_t index = 0;
1580 nsIID* clone;
1581 #define PUSH_IID(id) \
1582 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
1583 sizeof(nsIID))); \
1584 if (!clone) \
1585 goto oom; \
1586 array[index++] = clone;
1588 PUSH_IID(nsIXPCComponents_Exception)
1589 PUSH_IID(nsIXPCScriptable)
1590 #undef PUSH_IID
1592 return NS_OK;
1593 oom:
1594 while (index)
1595 nsMemory::Free(array[--index]);
1596 nsMemory::Free(array);
1597 *aArray = nullptr;
1598 return NS_ERROR_OUT_OF_MEMORY;
1599 }
1601 /* nsISupports getHelperForLanguage (in uint32_t language); */
1602 NS_IMETHODIMP
1603 nsXPCComponents_Exception::GetHelperForLanguage(uint32_t language,
1604 nsISupports **retval)
1605 {
1606 *retval = nullptr;
1607 return NS_OK;
1608 }
1610 /* readonly attribute string contractID; */
1611 NS_IMETHODIMP
1612 nsXPCComponents_Exception::GetContractID(char * *aContractID)
1613 {
1614 *aContractID = nullptr;
1615 return NS_ERROR_NOT_AVAILABLE;
1616 }
1618 /* readonly attribute string classDescription; */
1619 NS_IMETHODIMP
1620 nsXPCComponents_Exception::GetClassDescription(char * *aClassDescription)
1621 {
1622 static const char classDescription[] = "XPCComponents_Exception";
1623 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
1624 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1625 }
1627 /* readonly attribute nsCIDPtr classID; */
1628 NS_IMETHODIMP
1629 nsXPCComponents_Exception::GetClassID(nsCID * *aClassID)
1630 {
1631 *aClassID = nullptr;
1632 return NS_OK;
1633 }
1635 /* readonly attribute uint32_t implementationLanguage; */
1636 NS_IMETHODIMP
1637 nsXPCComponents_Exception::GetImplementationLanguage(uint32_t *aImplementationLanguage)
1638 {
1639 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
1640 return NS_OK;
1641 }
1643 /* readonly attribute uint32_t flags; */
1644 NS_IMETHODIMP
1645 nsXPCComponents_Exception::GetFlags(uint32_t *aFlags)
1646 {
1647 *aFlags = 0;
1648 return NS_OK;
1649 }
1651 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
1652 NS_IMETHODIMP
1653 nsXPCComponents_Exception::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
1654 {
1655 return NS_ERROR_NOT_AVAILABLE;
1656 }
1658 nsXPCComponents_Exception::nsXPCComponents_Exception()
1659 {
1660 }
1662 nsXPCComponents_Exception::~nsXPCComponents_Exception()
1663 {
1664 // empty
1665 }
1667 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Exception)
1668 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Exception)
1669 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
1670 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
1671 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Exception)
1672 NS_INTERFACE_MAP_END
1674 NS_IMPL_ADDREF(nsXPCComponents_Exception)
1675 NS_IMPL_RELEASE(nsXPCComponents_Exception)
1677 // The nsIXPCScriptable map declaration that will generate stubs for us...
1678 #define XPC_MAP_CLASSNAME nsXPCComponents_Exception
1679 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Exception"
1680 #define XPC_MAP_WANT_CALL
1681 #define XPC_MAP_WANT_CONSTRUCT
1682 #define XPC_MAP_WANT_HASINSTANCE
1683 #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
1684 #include "xpc_map_end.h" /* This will #undef the above */
1687 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
1688 NS_IMETHODIMP
1689 nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
1690 const CallArgs &args, bool *_retval)
1691 {
1692 RootedObject obj(cx, objArg);
1693 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1694 }
1696 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
1697 NS_IMETHODIMP
1698 nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
1699 JSObject *objArg, const CallArgs &args, bool *_retval)
1700 {
1701 RootedObject obj(cx, objArg);
1702 return CallOrConstruct(wrapper, cx, obj, args, _retval);
1703 }
1705 struct MOZ_STACK_CLASS ExceptionArgParser
1706 {
1707 ExceptionArgParser(JSContext *context,
1708 nsXPConnect *xpconnect)
1709 : eMsg("exception")
1710 , eResult(NS_ERROR_FAILURE)
1711 , cx(context)
1712 , xpc(xpconnect)
1713 {}
1715 // Public exception parameter values. During construction, these are
1716 // initialized to the appropriate defaults.
1717 const char* eMsg;
1718 nsresult eResult;
1719 nsCOMPtr<nsIStackFrame> eStack;
1720 nsCOMPtr<nsISupports> eData;
1722 // Parse the constructor arguments into the above |eFoo| parameter values.
1723 bool parse(const CallArgs &args) {
1724 /*
1725 * The Components.Exception takes a series of arguments, all of them
1726 * optional:
1727 *
1728 * Argument 0: Exception message (defaults to 'exception').
1729 * Argument 1: Result code (defaults to NS_ERROR_FAILURE) _or_ options
1730 * object (see below).
1731 * Argument 2: Stack (defaults to the current stack, which we trigger
1732 * by leaving this nullptr in the parser).
1733 * Argument 3: Optional user data (defaults to nullptr).
1734 *
1735 * To dig our way out of this clunky API, we now support passing an
1736 * options object as the second parameter (as opposed to a result code).
1737 * If this is the case, all subsequent arguments are ignored, and the
1738 * following properties are parsed out of the object (using the
1739 * associated default if the property does not exist):
1740 *
1741 * result: Result code (see argument 1).
1742 * stack: Call stack (see argument 2).
1743 * data: User data (see argument 3).
1744 */
1745 if (args.length() > 0 && !parseMessage(args[0]))
1746 return false;
1747 if (args.length() > 1) {
1748 if (args[1].isObject()) {
1749 RootedObject obj(cx, &args[1].toObject());
1750 return parseOptionsObject(obj);
1751 }
1752 if (!parseResult(args[1]))
1753 return false;
1754 }
1755 if (args.length() > 2) {
1756 if (!parseStack(args[2]))
1757 return false;
1758 }
1759 if (args.length() > 3) {
1760 if (!parseData(args[3]))
1761 return false;
1762 }
1763 return true;
1764 }
1766 protected:
1768 /*
1769 * Parsing helpers.
1770 */
1772 bool parseMessage(HandleValue v) {
1773 JSString *str = ToString(cx, v);
1774 if (!str)
1775 return false;
1776 eMsg = messageBytes.encodeLatin1(cx, str);
1777 return !!eMsg;
1778 }
1780 bool parseResult(HandleValue v) {
1781 return JS::ToUint32(cx, v, (uint32_t*) &eResult);
1782 }
1784 bool parseStack(HandleValue v) {
1785 if (!v.isObject()) {
1786 // eStack has already been initialized to null, which is what we want
1787 // for any non-object values (including null).
1788 return true;
1789 }
1791 return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
1792 NS_GET_IID(nsIStackFrame),
1793 getter_AddRefs(eStack)));
1794 }
1796 bool parseData(HandleValue v) {
1797 if (!v.isObject()) {
1798 // eData has already been initialized to null, which is what we want
1799 // for any non-object values (including null).
1800 return true;
1801 }
1803 return NS_SUCCEEDED(xpc->WrapJS(cx, &v.toObject(),
1804 NS_GET_IID(nsISupports),
1805 getter_AddRefs(eData)));
1806 }
1808 bool parseOptionsObject(HandleObject obj) {
1809 RootedValue v(cx);
1811 if (!getOption(obj, "result", &v) ||
1812 (!v.isUndefined() && !parseResult(v)))
1813 return false;
1815 if (!getOption(obj, "stack", &v) ||
1816 (!v.isUndefined() && !parseStack(v)))
1817 return false;
1819 if (!getOption(obj, "data", &v) ||
1820 (!v.isUndefined() && !parseData(v)))
1821 return false;
1823 return true;
1824 }
1826 bool getOption(HandleObject obj, const char *name, MutableHandleValue rv) {
1827 // Look for the property.
1828 bool found;
1829 if (!JS_HasProperty(cx, obj, name, &found))
1830 return false;
1832 // If it wasn't found, indicate with undefined.
1833 if (!found) {
1834 rv.setUndefined();
1835 return true;
1836 }
1838 // Get the property.
1839 return JS_GetProperty(cx, obj, name, rv);
1840 }
1842 /*
1843 * Internal data members.
1844 */
1846 // If there's a non-default exception string, hold onto the allocated bytes.
1847 JSAutoByteString messageBytes;
1849 // Various bits and pieces that are helpful to have around.
1850 JSContext *cx;
1851 nsXPConnect *xpc;
1852 };
1854 // static
1855 nsresult
1856 nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
1857 JSContext *cx, HandleObject obj,
1858 const CallArgs &args, bool *_retval)
1859 {
1860 nsXPConnect* xpc = nsXPConnect::XPConnect();
1862 // Do the security check if necessary
1864 nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
1865 if (sm && NS_FAILED(sm->CanCreateInstance(cx, Exception::GetCID()))) {
1866 // the security manager vetoed. It should have set an exception.
1867 *_retval = false;
1868 return NS_OK;
1869 }
1871 // Parse the arguments to the Exception constructor.
1872 ExceptionArgParser parser(cx, xpc);
1873 if (!parser.parse(args))
1874 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
1876 nsCOMPtr<nsIException> e = new Exception(nsCString(parser.eMsg),
1877 parser.eResult,
1878 EmptyCString(),
1879 parser.eStack,
1880 parser.eData);
1882 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
1883 RootedObject newObj(cx);
1885 if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
1886 getter_AddRefs(holder))) || !holder ||
1887 // Assign, not compare
1888 !(newObj = holder->GetJSObject())) {
1889 return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
1890 }
1892 args.rval().setObject(*newObj);
1893 return NS_OK;
1894 }
1896 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
1897 NS_IMETHODIMP
1898 nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper,
1899 JSContext * cx, JSObject * obj,
1900 HandleValue val, bool *bp,
1901 bool *_retval)
1902 {
1903 using namespace mozilla::dom;
1905 RootedValue v(cx, val);
1906 if (bp) {
1907 Exception* e;
1908 *bp = NS_SUCCEEDED(UNWRAP_OBJECT(Exception, v.toObjectOrNull(), e)) ||
1909 JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException));
1910 }
1911 return NS_OK;
1912 }
1914 /***************************************************************************/
1915 // This class is for the thing returned by "new Component.Constructor".
1917 // XXXjband we use this CID for security check, but security system can't see
1918 // it since it has no registed factory. Security really kicks in when we try
1919 // to build a wrapper around an instance.
1921 // {B4A95150-E25A-11d3-8F61-0010A4E73D9A}
1922 #define NS_XPCCONSTRUCTOR_CID \
1923 { 0xb4a95150, 0xe25a, 0x11d3, \
1924 { 0x8f, 0x61, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
1926 class nsXPCConstructor :
1927 public nsIXPCConstructor,
1928 public nsIXPCScriptable,
1929 public nsIClassInfo
1930 {
1931 public:
1932 NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID)
1933 public:
1934 // all the interface method declarations...
1935 NS_DECL_ISUPPORTS
1936 NS_DECL_NSIXPCCONSTRUCTOR
1937 NS_DECL_NSIXPCSCRIPTABLE
1938 NS_DECL_NSICLASSINFO
1940 public:
1941 nsXPCConstructor(); // not implemented
1942 nsXPCConstructor(nsIJSCID* aClassID,
1943 nsIJSIID* aInterfaceID,
1944 const char* aInitializer);
1945 virtual ~nsXPCConstructor();
1947 private:
1948 nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
1949 JSContext *cx, HandleObject obj,
1950 const CallArgs &args, bool *_retval);
1951 private:
1952 nsRefPtr<nsIJSCID> mClassID;
1953 nsRefPtr<nsIJSIID> mInterfaceID;
1954 char* mInitializer;
1955 };
1957 /***************************************************************************/
1958 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
1959 out nsIIDPtr array); */
1960 NS_IMETHODIMP
1961 nsXPCConstructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
1962 {
1963 const uint32_t count = 2;
1964 *aCount = count;
1965 nsIID **array;
1966 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
1967 if (!array)
1968 return NS_ERROR_OUT_OF_MEMORY;
1970 uint32_t index = 0;
1971 nsIID* clone;
1972 #define PUSH_IID(id) \
1973 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
1974 sizeof(nsIID))); \
1975 if (!clone) \
1976 goto oom; \
1977 array[index++] = clone;
1979 PUSH_IID(nsIXPCConstructor)
1980 PUSH_IID(nsIXPCScriptable)
1981 #undef PUSH_IID
1983 return NS_OK;
1984 oom:
1985 while (index)
1986 nsMemory::Free(array[--index]);
1987 nsMemory::Free(array);
1988 *aArray = nullptr;
1989 return NS_ERROR_OUT_OF_MEMORY;
1990 }
1992 /* nsISupports getHelperForLanguage (in uint32_t language); */
1993 NS_IMETHODIMP
1994 nsXPCConstructor::GetHelperForLanguage(uint32_t language,
1995 nsISupports **retval)
1996 {
1997 *retval = nullptr;
1998 return NS_OK;
1999 }
2001 /* readonly attribute string contractID; */
2002 NS_IMETHODIMP
2003 nsXPCConstructor::GetContractID(char * *aContractID)
2004 {
2005 *aContractID = nullptr;
2006 return NS_ERROR_NOT_AVAILABLE;
2007 }
2009 /* readonly attribute string classDescription; */
2010 NS_IMETHODIMP
2011 nsXPCConstructor::GetClassDescription(char * *aClassDescription)
2012 {
2013 static const char classDescription[] = "XPCConstructor";
2014 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
2015 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
2016 }
2018 /* readonly attribute nsCIDPtr classID; */
2019 NS_IMETHODIMP
2020 nsXPCConstructor::GetClassID(nsCID * *aClassID)
2021 {
2022 *aClassID = nullptr;
2023 return NS_OK;
2024 }
2026 /* readonly attribute uint32_t implementationLanguage; */
2027 NS_IMETHODIMP
2028 nsXPCConstructor::GetImplementationLanguage(uint32_t *aImplementationLanguage)
2029 {
2030 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
2031 return NS_OK;
2032 }
2034 /* readonly attribute uint32_t flags; */
2035 NS_IMETHODIMP
2036 nsXPCConstructor::GetFlags(uint32_t *aFlags)
2037 {
2038 *aFlags = 0;
2039 return NS_OK;
2040 }
2042 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
2043 NS_IMETHODIMP
2044 nsXPCConstructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
2045 {
2046 return NS_ERROR_NOT_AVAILABLE;
2047 }
2049 nsXPCConstructor::nsXPCConstructor(nsIJSCID* aClassID,
2050 nsIJSIID* aInterfaceID,
2051 const char* aInitializer)
2052 : mClassID(aClassID),
2053 mInterfaceID(aInterfaceID)
2054 {
2055 mInitializer = aInitializer ?
2056 (char*) nsMemory::Clone(aInitializer, strlen(aInitializer)+1) :
2057 nullptr;
2058 }
2060 nsXPCConstructor::~nsXPCConstructor()
2061 {
2062 if (mInitializer)
2063 nsMemory::Free(mInitializer);
2064 }
2066 /* readonly attribute nsIJSCID classID; */
2067 NS_IMETHODIMP
2068 nsXPCConstructor::GetClassID(nsIJSCID * *aClassID)
2069 {
2070 nsRefPtr<nsIJSCID> rval = mClassID;
2071 rval.forget(aClassID);
2072 return NS_OK;
2073 }
2075 /* readonly attribute nsIJSIID interfaceID; */
2076 NS_IMETHODIMP
2077 nsXPCConstructor::GetInterfaceID(nsIJSIID * *aInterfaceID)
2078 {
2079 nsRefPtr<nsIJSIID> rval = mInterfaceID;
2080 rval.forget(aInterfaceID);
2081 return NS_OK;
2082 }
2084 /* readonly attribute string initializer; */
2085 NS_IMETHODIMP
2086 nsXPCConstructor::GetInitializer(char * *aInitializer)
2087 {
2088 XPC_STRING_GETTER_BODY(aInitializer, mInitializer);
2089 }
2091 NS_INTERFACE_MAP_BEGIN(nsXPCConstructor)
2092 NS_INTERFACE_MAP_ENTRY(nsIXPCConstructor)
2093 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
2094 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
2095 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCConstructor)
2096 NS_INTERFACE_MAP_END
2098 NS_IMPL_ADDREF(nsXPCConstructor)
2099 NS_IMPL_RELEASE(nsXPCConstructor)
2101 // The nsIXPCScriptable map declaration that will generate stubs for us...
2102 #define XPC_MAP_CLASSNAME nsXPCConstructor
2103 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCConstructor"
2104 #define XPC_MAP_WANT_CALL
2105 #define XPC_MAP_WANT_CONSTRUCT
2106 #define XPC_MAP_FLAGS 0
2107 #include "xpc_map_end.h" /* This will #undef the above */
2110 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
2111 NS_IMETHODIMP
2112 nsXPCConstructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
2113 const CallArgs &args, bool *_retval)
2114 {
2115 RootedObject obj(cx, objArg);
2116 return CallOrConstruct(wrapper, cx, obj, args, _retval);
2118 }
2120 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
2121 NS_IMETHODIMP
2122 nsXPCConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *objArg,
2123 const CallArgs &args, bool *_retval)
2124 {
2125 RootedObject obj(cx, objArg);
2126 return CallOrConstruct(wrapper, cx, obj, args, _retval);
2127 }
2129 // static
2130 nsresult
2131 nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,JSContext *cx,
2132 HandleObject obj, const CallArgs &args, bool *_retval)
2133 {
2134 nsXPConnect* xpc = nsXPConnect::XPConnect();
2136 // security check not required because we are going to call through the
2137 // code which is reflected into JS which will do that for us later.
2139 nsCOMPtr<nsIXPConnectJSObjectHolder> cidHolder;
2140 nsCOMPtr<nsIXPConnectJSObjectHolder> iidHolder;
2141 RootedObject cidObj(cx);
2142 RootedObject iidObj(cx);
2144 if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID),
2145 getter_AddRefs(cidHolder))) || !cidHolder ||
2146 // Assign, not compare
2147 !(cidObj = cidHolder->GetJSObject()) ||
2148 NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID),
2149 getter_AddRefs(iidHolder))) || !iidHolder ||
2150 // Assign, not compare
2151 !(iidObj = iidHolder->GetJSObject())) {
2152 return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
2153 }
2155 JS::Rooted<JS::Value> arg(cx, ObjectValue(*iidObj));
2156 RootedValue rval(cx);
2157 if (!JS_CallFunctionName(cx, cidObj, "createInstance", arg, &rval) ||
2158 rval.isPrimitive()) {
2159 // createInstance will have thrown an exception
2160 *_retval = false;
2161 return NS_OK;
2162 }
2164 args.rval().set(rval);
2166 // call initializer method if supplied
2167 if (mInitializer) {
2168 RootedObject newObj(cx, &rval.toObject());
2169 // first check existence of function property for better error reporting
2170 RootedValue fun(cx);
2171 if (!JS_GetProperty(cx, newObj, mInitializer, &fun) ||
2172 fun.isPrimitive()) {
2173 return ThrowAndFail(NS_ERROR_XPC_BAD_INITIALIZER_NAME, cx, _retval);
2174 }
2176 RootedValue dummy(cx);
2177 if (!JS_CallFunctionValue(cx, newObj, fun, args, &dummy)) {
2178 // function should have thrown an exception
2179 *_retval = false;
2180 return NS_OK;
2181 }
2182 }
2184 return NS_OK;
2185 }
2187 /*******************************************************/
2188 // JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
2190 class nsXPCComponents_Constructor :
2191 public nsIXPCComponents_Constructor,
2192 public nsIXPCScriptable,
2193 public nsIClassInfo
2194 {
2195 public:
2196 // all the interface method declarations...
2197 NS_DECL_ISUPPORTS
2198 NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
2199 NS_DECL_NSIXPCSCRIPTABLE
2200 NS_DECL_NSICLASSINFO
2202 public:
2203 nsXPCComponents_Constructor();
2204 virtual ~nsXPCComponents_Constructor();
2206 private:
2207 static nsresult CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
2208 JSContext *cx, HandleObject obj,
2209 const CallArgs &args, bool *_retval);
2210 };
2212 /***************************************************************************/
2213 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
2214 out nsIIDPtr array); */
2215 NS_IMETHODIMP
2216 nsXPCComponents_Constructor::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
2217 {
2218 const uint32_t count = 2;
2219 *aCount = count;
2220 nsIID **array;
2221 *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
2222 if (!array)
2223 return NS_ERROR_OUT_OF_MEMORY;
2225 uint32_t index = 0;
2226 nsIID* clone;
2227 #define PUSH_IID(id) \
2228 clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ), \
2229 sizeof(nsIID))); \
2230 if (!clone) \
2231 goto oom; \
2232 array[index++] = clone;
2234 PUSH_IID(nsIXPCComponents_Constructor)
2235 PUSH_IID(nsIXPCScriptable)
2236 #undef PUSH_IID
2238 return NS_OK;
2239 oom:
2240 while (index)
2241 nsMemory::Free(array[--index]);
2242 nsMemory::Free(array);
2243 *aArray = nullptr;
2244 return NS_ERROR_OUT_OF_MEMORY;
2245 }
2247 /* nsISupports getHelperForLanguage (in uint32_t language); */
2248 NS_IMETHODIMP
2249 nsXPCComponents_Constructor::GetHelperForLanguage(uint32_t language,
2250 nsISupports **retval)
2251 {
2252 *retval = nullptr;
2253 return NS_OK;
2254 }
2256 /* readonly attribute string contractID; */
2257 NS_IMETHODIMP
2258 nsXPCComponents_Constructor::GetContractID(char * *aContractID)
2259 {
2260 *aContractID = nullptr;
2261 return NS_ERROR_NOT_AVAILABLE;
2262 }
2264 /* readonly attribute string classDescription; */
2265 NS_IMETHODIMP
2266 nsXPCComponents_Constructor::GetClassDescription(char * *aClassDescription)
2267 {
2268 static const char classDescription[] = "XPCComponents_Constructor";
2269 *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
2270 return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
2271 }
2273 /* readonly attribute nsCIDPtr classID; */
2274 NS_IMETHODIMP
2275 nsXPCComponents_Constructor::GetClassID(nsCID * *aClassID)
2276 {
2277 *aClassID = nullptr;
2278 return NS_OK;
2279 }
2281 /* readonly attribute uint32_t implementationLanguage; */
2282 NS_IMETHODIMP
2283 nsXPCComponents_Constructor::GetImplementationLanguage(uint32_t *aImplementationLanguage)
2284 {
2285 *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
2286 return NS_OK;
2287 }
2289 /* readonly attribute uint32_t flags; */
2290 NS_IMETHODIMP
2291 nsXPCComponents_Constructor::GetFlags(uint32_t *aFlags)
2292 {
2293 *aFlags = 0;
2294 return NS_OK;
2295 }
2297 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
2298 NS_IMETHODIMP
2299 nsXPCComponents_Constructor::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
2300 {
2301 return NS_ERROR_NOT_AVAILABLE;
2302 }
2304 nsXPCComponents_Constructor::nsXPCComponents_Constructor()
2305 {
2306 }
2308 nsXPCComponents_Constructor::~nsXPCComponents_Constructor()
2309 {
2310 // empty
2311 }
2313 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Constructor)
2314 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Constructor)
2315 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
2316 NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
2317 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Constructor)
2318 NS_INTERFACE_MAP_END
2320 NS_IMPL_ADDREF(nsXPCComponents_Constructor)
2321 NS_IMPL_RELEASE(nsXPCComponents_Constructor)
2323 // The nsIXPCScriptable map declaration that will generate stubs for us...
2324 #define XPC_MAP_CLASSNAME nsXPCComponents_Constructor
2325 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Constructor"
2326 #define XPC_MAP_WANT_CALL
2327 #define XPC_MAP_WANT_CONSTRUCT
2328 #define XPC_MAP_WANT_HASINSTANCE
2329 #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
2330 #include "xpc_map_end.h" /* This will #undef the above */
2333 /* bool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
2334 NS_IMETHODIMP
2335 nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
2336 JSObject *objArg, const CallArgs &args, bool *_retval)
2337 {
2338 RootedObject obj(cx, objArg);
2339 return CallOrConstruct(wrapper, cx, obj, args, _retval);
2340 }
2342 /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t argc, in JSValPtr argv, in JSValPtr vp); */
2343 NS_IMETHODIMP
2344 nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
2345 JSObject *objArg, const CallArgs &args, bool *_retval)
2346 {
2347 RootedObject obj(cx, objArg);
2348 return CallOrConstruct(wrapper, cx, obj, args, _retval);
2349 }
2351 // static
2352 nsresult
2353 nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
2354 JSContext *cx, HandleObject obj,
2355 const CallArgs &args, bool *_retval)
2356 {
2357 // make sure we have at least one arg
2359 if (args.length() < 1)
2360 return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
2362 // get the various other object pointers we need
2364 nsXPConnect* xpc = nsXPConnect::XPConnect();
2365 XPCWrappedNativeScope* scope = GetObjectScope(obj);
2366 nsCOMPtr<nsIXPCComponents> comp;
2368 if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents())))
2369 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
2371 // Do the security check if necessary
2373 nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
2374 if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCConstructor::GetCID()))) {
2375 // the security manager vetoed. It should have set an exception.
2376 *_retval = false;
2377 return NS_OK;
2378 }
2380 // initialization params for the Constructor object we will create
2381 nsCOMPtr<nsIJSCID> cClassID;
2382 nsCOMPtr<nsIJSIID> cInterfaceID;
2383 const char* cInitializer = nullptr;
2384 JSAutoByteString cInitializerBytes;
2386 if (args.length() >= 3) {
2387 // args[2] is an initializer function or property name
2388 RootedString str(cx, ToString(cx, args[2]));
2389 if (!str || !(cInitializer = cInitializerBytes.encodeLatin1(cx, str)))
2390 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
2391 }
2393 if (args.length() >= 2) {
2394 // args[1] is an iid name string
2395 // XXXjband support passing "Components.interfaces.foo"?
2397 nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
2398 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
2399 RootedObject ifacesObj(cx);
2401 // we do the lookup by asking the Components.interfaces object
2402 // for the property with this name - i.e. we let its caching of these
2403 // nsIJSIID objects work for us.
2405 if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
2406 NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
2407 NS_GET_IID(nsIXPCComponents_Interfaces),
2408 getter_AddRefs(holder))) || !holder ||
2409 // Assign, not compare
2410 !(ifacesObj = holder->GetJSObject())) {
2411 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
2412 }
2414 RootedString str(cx, ToString(cx, args[1]));
2415 RootedId id(cx);
2416 if (!str || !JS_StringToId(cx, str, &id))
2417 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
2419 RootedValue val(cx);
2420 if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive())
2421 return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
2423 nsCOMPtr<nsIXPConnectWrappedNative> wn;
2424 if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(),
2425 getter_AddRefs(wn))) || !wn ||
2426 !(cInterfaceID = do_QueryWrappedNative(wn))) {
2427 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
2428 }
2429 } else {
2430 nsCOMPtr<nsIInterfaceInfo> info;
2431 xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info));
2433 if (info) {
2434 cInterfaceID = nsJSIID::NewID(info);
2435 }
2436 if (!cInterfaceID)
2437 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
2438 }
2440 // a new scope to avoid warnings about shadowed names
2441 {
2442 // argv[0] is a contractid name string
2443 // XXXjband support passing "Components.classes.foo"?
2445 // we do the lookup by asking the Components.classes object
2446 // for the property with this name - i.e. we let its caching of these
2447 // nsIJSCID objects work for us.
2449 nsCOMPtr<nsIXPCComponents_Classes> classes;
2450 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
2451 RootedObject classesObj(cx);
2453 if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
2454 NS_FAILED(xpc->WrapNative(cx, obj, classes,
2455 NS_GET_IID(nsIXPCComponents_Classes),
2456 getter_AddRefs(holder))) || !holder ||
2457 // Assign, not compare
2458 !(classesObj = holder->GetJSObject())) {
2459 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
2460 }
2462 RootedString str(cx, ToString(cx, args[0]));
2463 RootedId id(cx);
2464 if (!str || !JS_StringToId(cx, str, &id))
2465 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
2467 RootedValue val(cx);
2468 if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive())
2469 return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
2471 nsCOMPtr<nsIXPConnectWrappedNative> wn;
2472 if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val),
2473 getter_AddRefs(wn))) || !wn ||
2474 !(cClassID = do_QueryWrappedNative(wn))) {
2475 return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
2476 }
2477 }
2479 nsCOMPtr<nsIXPCConstructor> ctor = new nsXPCConstructor(cClassID, cInterfaceID, cInitializer);
2480 nsCOMPtr<nsIXPConnectJSObjectHolder> holder2;
2481 RootedObject newObj(cx);
2483 if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor),
2484 getter_AddRefs(holder2))) || !holder2 ||
2485 // Assign, not compare
2486 !(newObj = holder2->GetJSObject())) {
2487 return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
2488 }
2490 args.rval().setObject(*newObj);
2491 return NS_OK;
2492 }
2494 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
2495 NS_IMETHODIMP
2496 nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
2497 JSContext * cx, JSObject * obj,
2498 HandleValue val, bool *bp,
2499 bool *_retval)
2500 {
2501 if (bp)
2502 *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIXPCConstructor));
2503 return NS_OK;
2504 }
2506 class nsXPCComponents_Utils :
2507 public nsIXPCComponents_Utils,
2508 public nsIXPCScriptable
2509 {
2510 public:
2511 // all the interface method declarations...
2512 NS_DECL_ISUPPORTS
2513 NS_DECL_NSIXPCSCRIPTABLE
2514 NS_DECL_NSIXPCCOMPONENTS_UTILS
2516 public:
2517 nsXPCComponents_Utils() { }
2518 virtual ~nsXPCComponents_Utils() { }
2520 private:
2521 nsCOMPtr<nsIXPCComponents_utils_Sandbox> mSandbox;
2522 };
2524 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils)
2525 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils)
2526 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
2527 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils)
2528 NS_INTERFACE_MAP_END
2530 NS_IMPL_ADDREF(nsXPCComponents_Utils)
2531 NS_IMPL_RELEASE(nsXPCComponents_Utils)
2533 // The nsIXPCScriptable map declaration that will generate stubs for us...
2534 #define XPC_MAP_CLASSNAME nsXPCComponents_Utils
2535 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents_Utils"
2536 #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
2537 #include "xpc_map_end.h" /* This will #undef the above */
2539 NS_IMETHODIMP
2540 nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox **aSandbox)
2541 {
2542 NS_ENSURE_ARG_POINTER(aSandbox);
2543 if (!mSandbox)
2544 mSandbox = NewSandboxConstructor();
2546 nsCOMPtr<nsIXPCComponents_utils_Sandbox> rval = mSandbox;
2547 rval.forget(aSandbox);
2548 return NS_OK;
2549 }
2551 /* void reportError (); */
2552 NS_IMETHODIMP
2553 nsXPCComponents_Utils::ReportError(HandleValue error, JSContext *cx)
2554 {
2555 // This function shall never fail! Silently eat any failure conditions.
2557 nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
2559 nsCOMPtr<nsIScriptError> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
2561 if (!scripterr || !console)
2562 return NS_OK;
2564 const uint64_t innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
2566 RootedObject errorObj(cx, error.isObject() ? &error.toObject() : nullptr);
2567 JSErrorReport *err = errorObj ? JS_ErrorFromException(cx, errorObj) : nullptr;
2568 if (err) {
2569 // It's a proper JS Error
2570 nsAutoString fileUni;
2571 CopyUTF8toUTF16(err->filename, fileUni);
2573 uint32_t column = err->uctokenptr - err->uclinebuf;
2575 const char16_t* ucmessage =
2576 static_cast<const char16_t*>(err->ucmessage);
2577 const char16_t* uclinebuf =
2578 static_cast<const char16_t*>(err->uclinebuf);
2580 nsresult rv = scripterr->InitWithWindowID(
2581 ucmessage ? nsDependentString(ucmessage) : EmptyString(),
2582 fileUni,
2583 uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
2584 err->lineno,
2585 column, err->flags, "XPConnect JavaScript", innerWindowID);
2586 NS_ENSURE_SUCCESS(rv, NS_OK);
2588 console->LogMessage(scripterr);
2589 return NS_OK;
2590 }
2592 // It's not a JS Error object, so we synthesize as best we're able.
2593 RootedString msgstr(cx, ToString(cx, error));
2594 if (!msgstr)
2595 return NS_OK;
2597 nsCOMPtr<nsIStackFrame> frame;
2598 nsXPConnect *xpc = nsXPConnect::XPConnect();
2599 xpc->GetCurrentJSStack(getter_AddRefs(frame));
2601 nsString fileName;
2602 int32_t lineNo = 0;
2603 if (frame) {
2604 frame->GetFilename(fileName);
2605 frame->GetLineNumber(&lineNo);
2606 }
2608 const jschar *msgchars = JS_GetStringCharsZ(cx, msgstr);
2609 if (!msgchars)
2610 return NS_OK;
2612 nsresult rv = scripterr->InitWithWindowID(
2613 nsDependentString(static_cast<const char16_t *>(msgchars)),
2614 fileName, EmptyString(), lineNo, 0, 0,
2615 "XPConnect JavaScript", innerWindowID);
2616 NS_ENSURE_SUCCESS(rv, NS_OK);
2618 console->LogMessage(scripterr);
2619 return NS_OK;
2620 }
2622 /* void evalInSandbox(in AString source, in nativeobj sandbox); */
2623 NS_IMETHODIMP
2624 nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
2625 HandleValue sandboxVal,
2626 HandleValue version,
2627 const nsACString& filenameArg,
2628 int32_t lineNumber,
2629 JSContext *cx,
2630 uint8_t optionalArgc,
2631 MutableHandleValue retval)
2632 {
2633 RootedObject sandbox(cx);
2634 if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox)
2635 return NS_ERROR_INVALID_ARG;
2637 // Optional third argument: JS version, as a string.
2638 JSVersion jsVersion = JSVERSION_DEFAULT;
2639 if (optionalArgc >= 1) {
2640 JSString *jsVersionStr = ToString(cx, version);
2641 if (!jsVersionStr)
2642 return NS_ERROR_INVALID_ARG;
2644 JSAutoByteString bytes(cx, jsVersionStr);
2645 if (!bytes)
2646 return NS_ERROR_INVALID_ARG;
2648 jsVersion = JS_StringToVersion(bytes.ptr());
2649 // Explicitly check for "latest", which we support for sandboxes but
2650 // isn't in the set of web-exposed version strings.
2651 if (jsVersion == JSVERSION_UNKNOWN &&
2652 !strcmp(bytes.ptr(), "latest"))
2653 {
2654 jsVersion = JSVERSION_LATEST;
2655 }
2656 if (jsVersion == JSVERSION_UNKNOWN)
2657 return NS_ERROR_INVALID_ARG;
2658 }
2660 // Optional fourth and fifth arguments: filename and line number.
2661 int32_t lineNo = (optionalArgc >= 3) ? lineNumber : 1;
2662 nsCString filename;
2663 if (!filenameArg.IsVoid()) {
2664 filename.Assign(filenameArg);
2665 } else {
2666 // Get the current source info from xpc.
2667 nsresult rv;
2668 nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
2669 NS_ENSURE_SUCCESS(rv, rv);
2671 nsCOMPtr<nsIStackFrame> frame;
2672 xpc->GetCurrentJSStack(getter_AddRefs(frame));
2673 if (frame) {
2674 nsString frameFile;
2675 frame->GetFilename(frameFile);
2676 CopyUTF16toUTF8(frameFile, filename);
2677 frame->GetLineNumber(&lineNo);
2678 }
2679 }
2681 return xpc::EvalInSandbox(cx, sandbox, source, filename, lineNo,
2682 jsVersion, false, retval);
2683 }
2685 NS_IMETHODIMP
2686 nsXPCComponents_Utils::GetSandboxMetadata(HandleValue sandboxVal,
2687 JSContext *cx, MutableHandleValue rval)
2688 {
2689 if (!sandboxVal.isObject())
2690 return NS_ERROR_INVALID_ARG;
2692 RootedObject sandbox(cx, &sandboxVal.toObject());
2693 sandbox = js::CheckedUnwrap(sandbox);
2694 if (!sandbox || !xpc::IsSandbox(sandbox))
2695 return NS_ERROR_INVALID_ARG;
2697 return xpc::GetSandboxMetadata(cx, sandbox, rval);
2698 }
2700 NS_IMETHODIMP
2701 nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal,
2702 HandleValue metadataVal,
2703 JSContext *cx)
2704 {
2705 if (!sandboxVal.isObject())
2706 return NS_ERROR_INVALID_ARG;
2708 RootedObject sandbox(cx, &sandboxVal.toObject());
2709 sandbox = js::CheckedUnwrap(sandbox);
2710 if (!sandbox || !xpc::IsSandbox(sandbox))
2711 return NS_ERROR_INVALID_ARG;
2713 nsresult rv = xpc::SetSandboxMetadata(cx, sandbox, metadataVal);
2714 NS_ENSURE_SUCCESS(rv, rv);
2716 return NS_OK;
2717 }
2719 /* JSObject import (in AUTF8String registryLocation,
2720 * [optional] in JSObject targetObj);
2721 */
2722 NS_IMETHODIMP
2723 nsXPCComponents_Utils::Import(const nsACString& registryLocation,
2724 HandleValue targetObj,
2725 JSContext* cx,
2726 uint8_t optionalArgc,
2727 MutableHandleValue retval)
2728 {
2729 nsCOMPtr<xpcIJSModuleLoader> moduleloader =
2730 do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
2731 if (!moduleloader)
2732 return NS_ERROR_FAILURE;
2733 return moduleloader->Import(registryLocation, targetObj, cx, optionalArgc, retval);
2734 }
2736 /* unload (in AUTF8String registryLocation);
2737 */
2738 NS_IMETHODIMP
2739 nsXPCComponents_Utils::Unload(const nsACString & registryLocation)
2740 {
2741 nsCOMPtr<xpcIJSModuleLoader> moduleloader =
2742 do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
2743 if (!moduleloader)
2744 return NS_ERROR_FAILURE;
2745 return moduleloader->Unload(registryLocation);
2746 }
2748 /*
2749 * JSObject importGlobalProperties (in jsval aPropertyList);
2750 */
2751 NS_IMETHODIMP
2752 nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
2753 JSContext* cx)
2754 {
2755 RootedObject global(cx, CurrentGlobalOrNull(cx));
2756 MOZ_ASSERT(global);
2757 GlobalProperties options(false);
2758 NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
2759 RootedObject propertyList(cx, &aPropertyList.toObject());
2760 NS_ENSURE_TRUE(JS_IsArrayObject(cx, propertyList), NS_ERROR_INVALID_ARG);
2761 if (!options.Parse(cx, propertyList) ||
2762 !options.Define(cx, global))
2763 {
2764 return NS_ERROR_FAILURE;
2765 }
2767 return NS_OK;
2768 }
2770 /* xpcIJSWeakReference getWeakReference (); */
2771 NS_IMETHODIMP
2772 nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext *cx,
2773 xpcIJSWeakReference **_retval)
2774 {
2775 nsRefPtr<xpcJSWeakReference> ref = new xpcJSWeakReference();
2776 nsresult rv = ref->Init(cx, object);
2777 NS_ENSURE_SUCCESS(rv, rv);
2778 ref.forget(_retval);
2779 return NS_OK;
2780 }
2782 /* void forceGC (); */
2783 NS_IMETHODIMP
2784 nsXPCComponents_Utils::ForceGC()
2785 {
2786 JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
2787 PrepareForFullGC(rt);
2788 GCForReason(rt, gcreason::COMPONENT_UTILS);
2789 return NS_OK;
2790 }
2792 /* void forceCC (); */
2793 NS_IMETHODIMP
2794 nsXPCComponents_Utils::ForceCC()
2795 {
2796 nsJSContext::CycleCollectNow();
2797 return NS_OK;
2798 }
2800 /* void forceShrinkingGC (); */
2801 NS_IMETHODIMP
2802 nsXPCComponents_Utils::ForceShrinkingGC()
2803 {
2804 JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
2805 PrepareForFullGC(rt);
2806 ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
2807 return NS_OK;
2808 }
2810 class PreciseGCRunnable : public nsRunnable
2811 {
2812 public:
2813 PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking)
2814 : mCallback(aCallback), mShrinking(aShrinking) {}
2816 NS_IMETHOD Run()
2817 {
2818 JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
2820 JSContext *cx;
2821 JSContext *iter = nullptr;
2822 while ((cx = JS_ContextIterator(rt, &iter)) != nullptr) {
2823 if (JS_IsRunning(cx)) {
2824 return NS_DispatchToMainThread(this);
2825 }
2826 }
2828 PrepareForFullGC(rt);
2829 if (mShrinking)
2830 ShrinkingGC(rt, gcreason::COMPONENT_UTILS);
2831 else
2832 GCForReason(rt, gcreason::COMPONENT_UTILS);
2834 mCallback->Callback();
2835 return NS_OK;
2836 }
2838 private:
2839 nsRefPtr<ScheduledGCCallback> mCallback;
2840 bool mShrinking;
2841 };
2843 /* void schedulePreciseGC(in ScheduledGCCallback callback); */
2844 NS_IMETHODIMP
2845 nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback)
2846 {
2847 nsRefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, false);
2848 return NS_DispatchToMainThread(event);
2849 }
2851 /* void schedulePreciseShrinkingGC(in ScheduledGCCallback callback); */
2852 NS_IMETHODIMP
2853 nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback)
2854 {
2855 nsRefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCallback, true);
2856 return NS_DispatchToMainThread(event);
2857 }
2859 /* void unlinkGhostWindows(); */
2860 NS_IMETHODIMP
2861 nsXPCComponents_Utils::UnlinkGhostWindows()
2862 {
2863 #ifdef DEBUG
2864 nsWindowMemoryReporter::UnlinkGhostWindows();
2865 return NS_OK;
2866 #else
2867 return NS_ERROR_NOT_IMPLEMENTED;
2868 #endif
2869 }
2871 /* [implicit_jscontext] jsval nondeterministicGetWeakMapKeys(in jsval aMap); */
2872 NS_IMETHODIMP
2873 nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(HandleValue aMap,
2874 JSContext *aCx,
2875 MutableHandleValue aKeys)
2876 {
2877 if (!aMap.isObject()) {
2878 aKeys.setUndefined();
2879 return NS_OK;
2880 }
2881 RootedObject objRet(aCx);
2882 RootedObject mapObj(aCx, &aMap.toObject());
2883 if (!JS_NondeterministicGetWeakMapKeys(aCx, mapObj, &objRet))
2884 return NS_ERROR_OUT_OF_MEMORY;
2885 aKeys.set(objRet ? ObjectValue(*objRet) : UndefinedValue());
2886 return NS_OK;
2887 }
2889 /* void getDebugObject(); */
2890 NS_IMETHODIMP
2891 nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx,
2892 MutableHandleValue retval)
2893 {
2894 JSObject *obj = js::GetTestingFunctions(cx);
2895 if (!obj)
2896 return NS_ERROR_XPC_JAVASCRIPT_ERROR;
2897 retval.setObject(*obj);
2898 return NS_OK;
2899 }
2901 /* void getGlobalForObject(); */
2902 NS_IMETHODIMP
2903 nsXPCComponents_Utils::GetGlobalForObject(HandleValue object,
2904 JSContext *cx,
2905 MutableHandleValue retval)
2906 {
2907 // First argument must be an object.
2908 if (object.isPrimitive())
2909 return NS_ERROR_XPC_BAD_CONVERT_JS;
2911 // Wrappers are parented to their the global in their home compartment. But
2912 // when getting the global for a cross-compartment wrapper, we really want
2913 // a wrapper for the foreign global. So we need to unwrap before getting the
2914 // parent, enter the compartment for the duration of the call, and wrap the
2915 // result.
2916 Rooted<JSObject*> obj(cx, &object.toObject());
2917 obj = js::UncheckedUnwrap(obj);
2918 {
2919 JSAutoCompartment ac(cx, obj);
2920 obj = JS_GetGlobalForObject(cx, obj);
2921 }
2923 if (!JS_WrapObject(cx, &obj))
2924 return NS_ERROR_FAILURE;
2926 // Outerize if necessary.
2927 if (JSObjectOp outerize = js::GetObjectClass(obj)->ext.outerObject)
2928 obj = outerize(cx, obj);
2930 retval.setObject(*obj);
2931 return NS_OK;
2932 }
2934 /* jsval createObjectIn(in jsval vobj); */
2935 bool
2936 xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectInOptions &options,
2937 MutableHandleValue rval)
2938 {
2939 if (!vobj.isObject()) {
2940 JS_ReportError(cx, "Expected an object as the target scope");
2941 return false;
2942 }
2944 RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject()));
2945 if (!scope) {
2946 JS_ReportError(cx, "Permission denied to create object in the target scope");
2947 return false;
2948 }
2950 bool define = !JSID_IS_VOID(options.defineAs);
2952 if (define && js::IsScriptedProxy(scope)) {
2953 JS_ReportError(cx, "Defining property on proxy object is not allowed");
2954 return false;
2955 }
2957 RootedObject obj(cx);
2958 {
2959 JSAutoCompartment ac(cx, scope);
2960 obj = JS_NewObject(cx, nullptr, JS::NullPtr(), scope);
2961 if (!obj)
2962 return false;
2964 if (define) {
2965 if (!JS_DefinePropertyById(cx, scope, options.defineAs, ObjectValue(*obj),
2966 JS_PropertyStub, JS_StrictPropertyStub,
2967 JSPROP_ENUMERATE))
2968 return false;
2969 }
2970 }
2972 rval.setObject(*obj);
2973 if (!WrapperFactory::WaiveXrayAndWrap(cx, rval))
2974 return false;
2976 return true;
2977 }
2979 /* boolean isProxy(in value vobj); */
2980 NS_IMETHODIMP
2981 nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext *cx, bool *rval)
2982 {
2983 if (!vobj.isObject()) {
2984 *rval = false;
2985 return NS_OK;
2986 }
2988 RootedObject obj(cx, &vobj.toObject());
2989 obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
2990 NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
2992 *rval = js::IsScriptedProxy(obj);
2993 return NS_OK;
2994 }
2996 /* jsval evalInWindow(in string source, in jsval window); */
2997 NS_IMETHODIMP
2998 nsXPCComponents_Utils::EvalInWindow(const nsAString &source, HandleValue window,
2999 JSContext *cx, MutableHandleValue rval)
3000 {
3001 if (!window.isObject())
3002 return NS_ERROR_INVALID_ARG;
3004 RootedObject rwindow(cx, &window.toObject());
3005 if (!xpc::EvalInWindow(cx, source, rwindow, rval))
3006 return NS_ERROR_FAILURE;
3007 return NS_OK;
3008 }
3010 /* jsval exportFunction(in jsval vfunction, in jsval vscope, in jsval voptions); */
3011 NS_IMETHODIMP
3012 nsXPCComponents_Utils::ExportFunction(HandleValue vfunction, HandleValue vscope,
3013 HandleValue voptions, JSContext *cx,
3014 MutableHandleValue rval)
3015 {
3016 if (!xpc::ExportFunction(cx, vfunction, vscope, voptions, rval))
3017 return NS_ERROR_FAILURE;
3018 return NS_OK;
3019 }
3021 /* jsval createObjectIn(in jsval vobj, [optional] in jsval voptions); */
3022 NS_IMETHODIMP
3023 nsXPCComponents_Utils::CreateObjectIn(HandleValue vobj, HandleValue voptions,
3024 JSContext *cx, MutableHandleValue rval)
3025 {
3026 RootedObject optionsObject(cx, voptions.isObject() ? &voptions.toObject()
3027 : nullptr);
3028 CreateObjectInOptions options(cx, optionsObject);
3029 if (voptions.isObject() &&
3030 !options.Parse())
3031 {
3032 return NS_ERROR_FAILURE;
3033 }
3035 if (!xpc::CreateObjectIn(cx, vobj, options, rval))
3036 return NS_ERROR_FAILURE;
3037 return NS_OK;
3038 }
3040 /* void makeObjectPropsNormal(jsval vobj); */
3041 NS_IMETHODIMP
3042 nsXPCComponents_Utils::MakeObjectPropsNormal(HandleValue vobj, JSContext *cx)
3043 {
3044 if (!cx)
3045 return NS_ERROR_FAILURE;
3047 // first argument must be an object
3048 if (vobj.isPrimitive())
3049 return NS_ERROR_XPC_BAD_CONVERT_JS;
3051 RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
3052 JSAutoCompartment ac(cx, obj);
3053 AutoIdArray ida(cx, JS_Enumerate(cx, obj));
3054 if (!ida)
3055 return NS_ERROR_FAILURE;
3057 RootedId id(cx);
3058 RootedValue v(cx);
3059 for (size_t i = 0; i < ida.length(); ++i) {
3060 id = ida[i];
3062 if (!JS_GetPropertyById(cx, obj, id, &v))
3063 return NS_ERROR_FAILURE;
3065 if (v.isPrimitive())
3066 continue;
3068 RootedObject propobj(cx, &v.toObject());
3069 // TODO Deal with non-functions.
3070 if (!js::IsWrapper(propobj) || !JS_ObjectIsCallable(cx, propobj))
3071 continue;
3073 if (!NewFunctionForwarder(cx, id, propobj, /* doclone = */ false, &v) ||
3074 !JS_SetPropertyById(cx, obj, id, v))
3075 return NS_ERROR_FAILURE;
3076 }
3078 return NS_OK;
3079 }
3081 NS_IMETHODIMP
3082 nsXPCComponents_Utils::IsDeadWrapper(HandleValue obj, bool *out)
3083 {
3084 *out = false;
3085 if (obj.isPrimitive())
3086 return NS_ERROR_INVALID_ARG;
3088 // Make sure to unwrap first. Once a proxy is nuked, it ceases to be a
3089 // wrapper, meaning that, if passed to another compartment, we'll generate
3090 // a CCW for it. Make sure that IsDeadWrapper sees through the confusion.
3091 *out = JS_IsDeadWrapper(js::CheckedUnwrap(&obj.toObject()));
3092 return NS_OK;
3093 }
3095 /* void recomputerWrappers(jsval vobj); */
3096 NS_IMETHODIMP
3097 nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext *cx)
3098 {
3099 // Determine the compartment of the given object, if any.
3100 JSCompartment *c = vobj.isObject()
3101 ? js::GetObjectCompartment(js::UncheckedUnwrap(&vobj.toObject()))
3102 : nullptr;
3104 // If no compartment was given, recompute all.
3105 if (!c)
3106 js::RecomputeWrappers(cx, js::AllCompartments(), js::AllCompartments());
3107 // Otherwise, recompute wrappers for the given compartment.
3108 else
3109 js::RecomputeWrappers(cx, js::SingleCompartment(c), js::AllCompartments()) &&
3110 js::RecomputeWrappers(cx, js::AllCompartments(), js::SingleCompartment(c));
3112 return NS_OK;
3113 }
3115 /* jsval setWantXrays(jsval vscope); */
3116 NS_IMETHODIMP
3117 nsXPCComponents_Utils::SetWantXrays(HandleValue vscope, JSContext *cx)
3118 {
3119 if (!vscope.isObject())
3120 return NS_ERROR_INVALID_ARG;
3121 JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
3122 JSCompartment *compartment = js::GetObjectCompartment(scopeObj);
3123 EnsureCompartmentPrivate(scopeObj)->wantXrays = true;
3124 bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
3125 js::AllCompartments());
3126 NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
3127 return NS_OK;
3128 }
3130 /* jsval forcePrivilegedComponentsForScope(jsval vscope); */
3131 NS_IMETHODIMP
3132 nsXPCComponents_Utils::ForcePrivilegedComponentsForScope(HandleValue vscope,
3133 JSContext *cx)
3134 {
3135 if (!vscope.isObject())
3136 return NS_ERROR_INVALID_ARG;
3137 JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
3138 XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
3139 scope->ForcePrivilegedComponents();
3140 return NS_OK;
3141 }
3143 /* jsval getComponentsForScope(jsval vscope); */
3144 NS_IMETHODIMP
3145 nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext *cx,
3146 MutableHandleValue rval)
3147 {
3148 if (!vscope.isObject())
3149 return NS_ERROR_INVALID_ARG;
3150 JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
3151 XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
3152 RootedObject components(cx);
3153 if (!scope->GetComponentsJSObject(&components))
3154 return NS_ERROR_FAILURE;
3155 if (!JS_WrapObject(cx, &components))
3156 return NS_ERROR_FAILURE;
3157 rval.setObject(*components);
3158 return NS_OK;
3159 }
3161 NS_IMETHODIMP
3162 nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
3163 JSContext *cx)
3164 {
3165 RootedValue runnable(cx, runnableArg);
3166 // Enter the given compartment, if any, and rewrap runnable.
3167 Maybe<JSAutoCompartment> ac;
3168 if (scope.isObject()) {
3169 JSObject *scopeObj = js::UncheckedUnwrap(&scope.toObject());
3170 if (!scopeObj)
3171 return NS_ERROR_FAILURE;
3172 ac.construct(cx, scopeObj);
3173 if (!JS_WrapValue(cx, &runnable))
3174 return NS_ERROR_FAILURE;
3175 }
3177 // Get an XPCWrappedJS for |runnable|.
3178 if (!runnable.isObject())
3179 return NS_ERROR_INVALID_ARG;
3181 nsCOMPtr<nsIRunnable> run;
3182 nsresult rv = nsXPConnect::XPConnect()->WrapJS(cx, &runnable.toObject(),
3183 NS_GET_IID(nsIRunnable),
3184 getter_AddRefs(run));
3185 NS_ENSURE_SUCCESS(rv, rv);
3186 MOZ_ASSERT(run);
3188 // Dispatch.
3189 return NS_DispatchToMainThread(run);
3190 }
3192 #define GENERATE_JSCONTEXTOPTION_GETTER_SETTER(_attr, _getter, _setter) \
3193 NS_IMETHODIMP \
3194 nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
3195 { \
3196 *aValue = ContextOptionsRef(cx)._getter(); \
3197 return NS_OK; \
3198 } \
3199 NS_IMETHODIMP \
3200 nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
3201 { \
3202 ContextOptionsRef(cx)._setter(aValue); \
3203 return NS_OK; \
3204 }
3206 #define GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(_attr, _getter, _setter) \
3207 NS_IMETHODIMP \
3208 nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
3209 { \
3210 *aValue = RuntimeOptionsRef(cx)._getter(); \
3211 return NS_OK; \
3212 } \
3213 NS_IMETHODIMP \
3214 nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
3215 { \
3216 RuntimeOptionsRef(cx)._setter(aValue); \
3217 return NS_OK; \
3218 }
3220 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
3221 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Werror, werror, setWerror)
3222 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
3223 GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Ion, ion, setIon)
3225 #undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
3226 #undef GENERATE_JSRUNTIMEOPTION_GETTER_SETTER
3228 NS_IMETHODIMP
3229 nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx)
3230 {
3231 #ifdef JS_GC_ZEAL
3232 JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ);
3233 #endif
3234 return NS_OK;
3235 }
3237 NS_IMETHODIMP
3238 nsXPCComponents_Utils::NukeSandbox(HandleValue obj, JSContext *cx)
3239 {
3240 NS_ENSURE_TRUE(obj.isObject(), NS_ERROR_INVALID_ARG);
3241 JSObject *wrapper = &obj.toObject();
3242 NS_ENSURE_TRUE(IsWrapper(wrapper), NS_ERROR_INVALID_ARG);
3243 JSObject *sb = UncheckedUnwrap(wrapper);
3244 NS_ENSURE_TRUE(IsSandbox(sb), NS_ERROR_INVALID_ARG);
3245 NukeCrossCompartmentWrappers(cx, AllCompartments(),
3246 SingleCompartment(GetObjectCompartment(sb)),
3247 NukeWindowReferences);
3248 return NS_OK;
3249 }
3251 NS_IMETHODIMP
3252 nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
3253 JSContext *cx)
3254 {
3255 NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
3256 RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
3257 /* stopAtOuter = */ false));
3258 NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
3259 if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
3260 JS_ReportError(cx, "Script may not be disabled for system globals");
3261 return NS_ERROR_FAILURE;
3262 }
3263 Scriptability::Get(global).Block();
3264 return NS_OK;
3265 }
3267 NS_IMETHODIMP
3268 nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
3269 JSContext *cx)
3270 {
3271 NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
3272 RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
3273 /* stopAtOuter = */ false));
3274 NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
3275 if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
3276 JS_ReportError(cx, "Script may not be disabled for system globals");
3277 return NS_ERROR_FAILURE;
3278 }
3279 Scriptability::Get(global).Unblock();
3280 return NS_OK;
3281 }
3283 NS_IMETHODIMP
3284 nsXPCComponents_Utils::IsXrayWrapper(HandleValue obj, bool* aRetval)
3285 {
3286 *aRetval =
3287 obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
3288 return NS_OK;
3289 }
3291 NS_IMETHODIMP
3292 nsXPCComponents_Utils::WaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval)
3293 {
3294 RootedValue value(aCx, aVal);
3295 if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value))
3296 return NS_ERROR_FAILURE;
3297 aRetval.set(value);
3298 return NS_OK;
3299 }
3301 NS_IMETHODIMP
3302 nsXPCComponents_Utils::UnwaiveXrays(HandleValue aVal, JSContext *aCx, MutableHandleValue aRetval)
3303 {
3304 if (!aVal.isObject()) {
3305 aRetval.set(aVal);
3306 return NS_OK;
3307 }
3309 RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject()));
3310 if (!JS_WrapObject(aCx, &obj))
3311 return NS_ERROR_FAILURE;
3312 aRetval.setObject(*obj);
3313 return NS_OK;
3314 }
3316 NS_IMETHODIMP
3317 nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap, JSContext *aCx, char **aRv)
3318 {
3319 if (!aObj.isObject())
3320 return NS_ERROR_INVALID_ARG;
3321 RootedObject obj(aCx, &aObj.toObject());
3322 if (aUnwrap)
3323 obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
3324 *aRv = NS_strdup(js::GetObjectClass(obj)->name);
3325 NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY);
3326 return NS_OK;
3327 }
3329 NS_IMETHODIMP
3330 nsXPCComponents_Utils::GetDOMClassInfo(const nsAString& aClassName,
3331 nsIClassInfo** aClassInfo)
3332 {
3333 *aClassInfo = nullptr;
3334 return NS_ERROR_NOT_AVAILABLE;
3335 }
3337 NS_IMETHODIMP
3338 nsXPCComponents_Utils::GetIncumbentGlobal(HandleValue aCallback,
3339 JSContext *aCx, MutableHandleValue aOut)
3340 {
3341 nsCOMPtr<nsIGlobalObject> global = mozilla::dom::GetIncumbentGlobal();
3342 RootedValue globalVal(aCx);
3344 if (!global) {
3345 globalVal = NullValue();
3346 } else {
3347 // Note: We rely on the wrap call for outerization.
3348 globalVal = ObjectValue(*global->GetGlobalJSObject());
3349 if (!JS_WrapValue(aCx, &globalVal))
3350 return NS_ERROR_FAILURE;
3351 }
3353 // Invoke the callback, if passed.
3354 if (aCallback.isObject()) {
3355 RootedValue ignored(aCx);
3356 if (!JS_CallFunctionValue(aCx, JS::NullPtr(), aCallback, globalVal, &ignored))
3357 return NS_ERROR_FAILURE;
3358 }
3360 aOut.set(globalVal);
3361 return NS_OK;
3362 }
3364 /*
3365 * Below is a bunch of awkward junk to allow JS test code to trigger the
3366 * creation of an XPCWrappedJS, such that it ends up in the map. We need to
3367 * hand the caller some sort of reference to hold onto (to prevent the
3368 * refcount from dropping to zero as soon as the function returns), but trying
3369 * to return a bonafide XPCWrappedJS to script causes all sorts of trouble. So
3370 * we create a benign holder class instead, which acts as an opaque reference
3371 * that script can use to keep the XPCWrappedJS alive and in the map.
3372 */
3374 class WrappedJSHolder : public nsISupports
3375 {
3376 NS_DECL_ISUPPORTS
3377 WrappedJSHolder() {}
3378 virtual ~WrappedJSHolder() {}
3380 nsRefPtr<nsXPCWrappedJS> mWrappedJS;
3381 };
3382 NS_IMPL_ISUPPORTS0(WrappedJSHolder);
3384 NS_IMETHODIMP
3385 nsXPCComponents_Utils::GenerateXPCWrappedJS(HandleValue aObj, HandleValue aScope,
3386 JSContext *aCx, nsISupports **aOut)
3387 {
3388 if (!aObj.isObject())
3389 return NS_ERROR_INVALID_ARG;
3390 RootedObject obj(aCx, &aObj.toObject());
3391 RootedObject scope(aCx, aScope.isObject() ? js::UncheckedUnwrap(&aScope.toObject())
3392 : CurrentGlobalOrNull(aCx));
3393 JSAutoCompartment ac(aCx, scope);
3394 if (!JS_WrapObject(aCx, &obj))
3395 return NS_ERROR_FAILURE;
3397 nsRefPtr<WrappedJSHolder> holder = new WrappedJSHolder();
3398 nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports),
3399 getter_AddRefs(holder->mWrappedJS));
3400 holder.forget(aOut);
3401 return rv;
3402 }
3404 NS_IMETHODIMP
3405 nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory, PRTime *aOut)
3406 {
3407 WatchdogTimestampCategory category;
3408 if (aCategory.EqualsLiteral("RuntimeStateChange"))
3409 category = TimestampRuntimeStateChange;
3410 else if (aCategory.EqualsLiteral("WatchdogWakeup"))
3411 category = TimestampWatchdogWakeup;
3412 else if (aCategory.EqualsLiteral("WatchdogHibernateStart"))
3413 category = TimestampWatchdogHibernateStart;
3414 else if (aCategory.EqualsLiteral("WatchdogHibernateStop"))
3415 category = TimestampWatchdogHibernateStop;
3416 else
3417 return NS_ERROR_INVALID_ARG;
3418 *aOut = XPCJSRuntime::Get()->GetWatchdogTimestamp(category);
3419 return NS_OK;
3420 }
3422 NS_IMETHODIMP
3423 nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext *cx, MutableHandleValue rval)
3424 {
3425 RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
3426 if (!obj)
3427 return NS_ERROR_OUT_OF_MEMORY;
3429 unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
3431 size_t i = JS_SetProtoCalled(cx);
3432 RootedValue v(cx, DoubleValue(i));
3433 if (!JS_DefineProperty(cx, obj, "setProto", v, attrs))
3434 return NS_ERROR_OUT_OF_MEMORY;
3436 i = JS_GetCustomIteratorCount(cx);
3437 v.setDouble(i);
3438 if (!JS_DefineProperty(cx, obj, "customIter", v, attrs))
3439 return NS_ERROR_OUT_OF_MEMORY;
3441 rval.setObject(*obj);
3442 return NS_OK;
3443 }
3445 class MOZ_STACK_CLASS CloneIntoOptions : public OptionsBase
3446 {
3447 public:
3448 CloneIntoOptions(JSContext *cx = xpc_GetSafeJSContext(),
3449 JSObject *options = nullptr)
3450 : OptionsBase(cx, options)
3451 , cloneFunctions(false)
3452 {}
3454 virtual bool Parse()
3455 {
3456 return ParseBoolean("cloneFunctions", &cloneFunctions);
3457 }
3459 bool cloneFunctions;
3460 };
3462 class MOZ_STACK_CLASS CloneIntoCallbacksData
3463 {
3464 public:
3465 CloneIntoCallbacksData(JSContext *aCx, CloneIntoOptions *aOptions)
3466 : mOptions(aOptions)
3467 , mFunctions(aCx)
3468 {}
3470 CloneIntoOptions *mOptions;
3471 AutoObjectVector mFunctions;
3472 };
3474 static JSObject*
3475 CloneIntoReadStructuredClone(JSContext *cx,
3476 JSStructuredCloneReader *reader,
3477 uint32_t tag,
3478 uint32_t value,
3479 void* closure)
3480 {
3481 CloneIntoCallbacksData* data = static_cast<CloneIntoCallbacksData*>(closure);
3482 MOZ_ASSERT(data);
3484 if (tag == mozilla::dom::SCTAG_DOM_BLOB || tag == mozilla::dom::SCTAG_DOM_FILELIST) {
3485 MOZ_ASSERT(!value, "Data should be empty");
3487 nsISupports *supports;
3488 if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
3489 RootedValue val(cx);
3490 if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val)))
3491 return val.toObjectOrNull();
3492 }
3493 }
3495 if (tag == mozilla::dom::SCTAG_DOM_FUNCTION) {
3496 MOZ_ASSERT(value < data->mFunctions.length());
3498 RootedValue functionValue(cx);
3499 RootedObject obj(cx, data->mFunctions[value]);
3501 if (!JS_WrapObject(cx, &obj))
3502 return nullptr;
3504 if (!xpc::NewFunctionForwarder(cx, obj, false, &functionValue))
3505 return nullptr;
3507 return &functionValue.toObject();
3508 }
3510 return nullptr;
3511 }
3513 static bool
3514 CloneIntoWriteStructuredClone(JSContext *cx,
3515 JSStructuredCloneWriter *writer,
3516 HandleObject obj,
3517 void *closure)
3518 {
3519 CloneIntoCallbacksData* data = static_cast<CloneIntoCallbacksData*>(closure);
3520 MOZ_ASSERT(data);
3522 nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
3523 nsContentUtils::XPConnect()->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
3524 if (wrappedNative) {
3525 uint32_t scTag = 0;
3526 nsISupports *supports = wrappedNative->Native();
3528 nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
3529 if (blob)
3530 scTag = mozilla::dom::SCTAG_DOM_BLOB;
3531 else {
3532 nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
3533 if (list)
3534 scTag = mozilla::dom::SCTAG_DOM_FILELIST;
3535 }
3537 if (scTag) {
3538 return JS_WriteUint32Pair(writer, scTag, 0) &&
3539 JS_WriteBytes(writer, &supports, sizeof(supports));
3540 }
3541 }
3543 if (data->mOptions->cloneFunctions && JS_ObjectIsCallable(cx, obj)) {
3544 data->mFunctions.append(obj);
3545 return JS_WriteUint32Pair(writer, mozilla::dom::SCTAG_DOM_FUNCTION,
3546 data->mFunctions.length() - 1);
3547 }
3549 return false;
3550 }
3552 // These functions serialize raw XPCOM pointers in the data stream, and thus
3553 // should only be used when the read and write are done together
3554 // synchronously.
3555 static JSStructuredCloneCallbacks CloneIntoCallbacks = {
3556 CloneIntoReadStructuredClone,
3557 CloneIntoWriteStructuredClone,
3558 nullptr
3559 };
3561 bool
3562 xpc::CloneInto(JSContext *aCx, HandleValue aValue, HandleValue aScope,
3563 HandleValue aOptions, MutableHandleValue aCloned)
3564 {
3565 if (!aScope.isObject())
3566 return false;
3568 RootedObject scope(aCx, &aScope.toObject());
3569 scope = js::CheckedUnwrap(scope);
3570 if(!scope) {
3571 JS_ReportError(aCx, "Permission denied to clone object into scope");
3572 return false;
3573 }
3575 if (!aOptions.isUndefined() && !aOptions.isObject()) {
3576 JS_ReportError(aCx, "Invalid argument");
3577 return false;
3578 }
3580 RootedObject optionsObject(aCx, aOptions.isObject() ? &aOptions.toObject()
3581 : nullptr);
3582 CloneIntoOptions options(aCx, optionsObject);
3583 if (aOptions.isObject() && !options.Parse())
3584 return false;
3586 {
3587 CloneIntoCallbacksData data(aCx, &options);
3588 JSAutoCompartment ac(aCx, scope);
3589 if (!JS_StructuredClone(aCx, aValue, aCloned, &CloneIntoCallbacks, &data))
3590 return false;
3591 }
3593 return JS_WrapValue(aCx, aCloned);
3594 }
3596 NS_IMETHODIMP
3597 nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope,
3598 HandleValue aOptions, JSContext *aCx,
3599 MutableHandleValue aCloned)
3600 {
3601 return xpc::CloneInto(aCx, aValue, aScope, aOptions, aCloned) ?
3602 NS_OK : NS_ERROR_FAILURE;
3603 }
3605 NS_IMETHODIMP
3606 nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal **aResult)
3607 {
3608 // This API may only be when the Entry Settings Object corresponds to a
3609 // JS-implemented WebIDL call. In all other cases, the value will be null,
3610 // and we throw.
3611 nsCOMPtr<nsIPrincipal> callerPrin = mozilla::dom::GetWebIDLCallerPrincipal();
3612 if (!callerPrin)
3613 return NS_ERROR_NOT_AVAILABLE;
3614 callerPrin.forget(aResult);
3615 return NS_OK;
3616 }
3618 NS_IMETHODIMP
3619 nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext *cx,
3620 nsIPrincipal **result)
3621 {
3622 if (!val.isObject())
3623 return NS_ERROR_INVALID_ARG;
3624 RootedObject obj(cx, &val.toObject());
3625 obj = js::CheckedUnwrap(obj);
3626 MOZ_ASSERT(obj);
3628 nsCOMPtr<nsIPrincipal> prin = nsContentUtils::GetObjectPrincipal(obj);
3629 prin.forget(result);
3630 return NS_OK;
3631 }
3633 /***************************************************************************/
3634 /***************************************************************************/
3635 /***************************************************************************/
3638 nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope)
3639 : mScope(aScope)
3640 {
3641 MOZ_ASSERT(aScope, "aScope must not be null");
3642 }
3644 nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
3645 : nsXPCComponentsBase(aScope)
3646 {
3647 }
3649 nsXPCComponentsBase::~nsXPCComponentsBase()
3650 {
3651 }
3653 nsXPCComponents::~nsXPCComponents()
3654 {
3655 }
3657 void
3658 nsXPCComponentsBase::ClearMembers()
3659 {
3660 mInterfaces = nullptr;
3661 mInterfacesByID = nullptr;
3662 mResults = nullptr;
3663 }
3665 void
3666 nsXPCComponents::ClearMembers()
3667 {
3668 mClasses = nullptr;
3669 mClassesByID = nullptr;
3670 mID = nullptr;
3671 mException = nullptr;
3672 mConstructor = nullptr;
3673 mUtils = nullptr;
3675 nsXPCComponentsBase::ClearMembers();
3676 }
3678 /*******************************************/
3679 #define XPC_IMPL_GET_OBJ_METHOD(_class, _n) \
3680 NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n * *a##_n) { \
3681 NS_ENSURE_ARG_POINTER(a##_n); \
3682 if (!m##_n) \
3683 m##_n = new nsXPCComponents_##_n(); \
3684 nsRefPtr<nsXPCComponents_##_n> ret = m##_n; \
3685 ret.forget(a##_n); \
3686 return NS_OK; \
3687 }
3689 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Interfaces)
3690 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, InterfacesByID)
3691 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes)
3692 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ClassesByID)
3693 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Results)
3694 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID)
3695 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception)
3696 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor)
3697 XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils)
3699 #undef XPC_IMPL_GET_OBJ_METHOD
3700 /*******************************************/
3702 NS_IMETHODIMP
3703 nsXPCComponentsBase::IsSuccessCode(nsresult result, bool *out)
3704 {
3705 *out = NS_SUCCEEDED(result);
3706 return NS_OK;
3707 }
3709 NS_IMETHODIMP
3710 nsXPCComponents::GetStack(nsIStackFrame * *aStack)
3711 {
3712 nsresult rv;
3713 nsXPConnect* xpc = nsXPConnect::XPConnect();
3714 rv = xpc->GetCurrentJSStack(aStack);
3715 return rv;
3716 }
3718 NS_IMETHODIMP
3719 nsXPCComponents::GetManager(nsIComponentManager * *aManager)
3720 {
3721 MOZ_ASSERT(aManager, "bad param");
3722 return NS_GetComponentManager(aManager);
3723 }
3725 NS_IMETHODIMP
3726 nsXPCComponents::GetLastResult(JSContext *aCx, MutableHandleValue aOut)
3727 {
3728 XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
3729 if (!xpcc)
3730 return NS_ERROR_FAILURE;
3731 nsresult res = xpcc->GetLastResult();
3732 aOut.setNumber(static_cast<uint32_t>(res));
3733 return NS_OK;
3734 }
3736 NS_IMETHODIMP
3737 nsXPCComponents::GetReturnCode(JSContext *aCx, MutableHandleValue aOut)
3738 {
3739 XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
3740 if (!xpcc)
3741 return NS_ERROR_FAILURE;
3742 nsresult res = xpcc->GetPendingResult();
3743 aOut.setNumber(static_cast<uint32_t>(res));
3744 return NS_OK;
3745 }
3747 NS_IMETHODIMP
3748 nsXPCComponents::SetReturnCode(JSContext *aCx, HandleValue aCode)
3749 {
3750 XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
3751 if (!xpcc)
3752 return NS_ERROR_FAILURE;
3753 nsresult rv;
3754 if (!ToUint32(aCx, aCode, (uint32_t*)&rv))
3755 return NS_ERROR_FAILURE;
3756 xpcc->SetPendingResult(rv);
3757 xpcc->SetLastResult(rv);
3758 return NS_OK;
3759 }
3761 // static
3762 /* void reportError (); */
3763 NS_IMETHODIMP nsXPCComponents::ReportError(HandleValue error, JSContext *cx)
3764 {
3765 NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
3767 nsCOMPtr<nsIXPCComponents_Utils> utils;
3768 nsresult rv = GetUtils(getter_AddRefs(utils));
3769 if (NS_FAILED(rv))
3770 return rv;
3772 return utils->ReportError(error, cx);
3773 }
3775 /**********************************************/
3777 class ComponentsSH : public nsIXPCScriptable
3778 {
3779 public:
3780 ComponentsSH(unsigned dummy)
3781 {
3782 }
3784 NS_DECL_ISUPPORTS
3785 NS_DECL_NSIXPCSCRIPTABLE
3786 // The NS_IMETHODIMP isn't really accurate here, but NS_CALLBACK requires
3787 // the referent to be declared __stdcall on Windows, and this is the only
3788 // macro that does that.
3789 static NS_IMETHODIMP Get(uint32_t aLangId, nsISupports **helper)
3790 {
3791 *helper = &singleton;
3792 return NS_OK;
3793 }
3795 private:
3796 static ComponentsSH singleton;
3797 };
3799 ComponentsSH ComponentsSH::singleton(0);
3801 // Singleton refcounting.
3802 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::AddRef(void) { return 1; }
3803 NS_IMETHODIMP_(MozExternalRefCountType) ComponentsSH::Release(void) { return 1; }
3805 NS_INTERFACE_MAP_BEGIN(ComponentsSH)
3806 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
3807 NS_INTERFACE_MAP_ENTRY(nsISupports)
3808 NS_INTERFACE_MAP_END
3810 #define NSXPCCOMPONENTSBASE_CID \
3811 { 0xc62998e5, 0x95f1, 0x4058, \
3812 { 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 } }
3814 #define NSXPCCOMPONENTS_CID \
3815 { 0x3649f405, 0xf0ec, 0x4c28, \
3816 { 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 } }
3818 NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID)
3819 NS_IMPL_ISUPPORTS_CI(nsXPCComponentsBase, nsIXPCComponentsBase)
3821 NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTS_CID)
3822 // Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like
3823 // if it existed.
3824 NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase)
3825 NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase)
3826 NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
3827 NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
3828 NS_IMPL_QUERY_CLASSINFO(nsXPCComponents)
3829 NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase)
3830 NS_IMPL_CI_INTERFACE_GETTER(nsXPCComponents, nsIXPCComponents)
3832 // The nsIXPCScriptable map declaration that will generate stubs for us
3833 #define XPC_MAP_CLASSNAME ComponentsSH
3834 #define XPC_MAP_QUOTED_CLASSNAME "nsXPCComponents"
3835 #define XPC_MAP_WANT_PRECREATE
3836 #include "xpc_map_end.h" /* This will #undef the above */
3838 NS_IMETHODIMP
3839 ComponentsSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj)
3840 {
3841 nsXPCComponentsBase *self = static_cast<nsXPCComponentsBase*>(nativeObj);
3842 // this should never happen
3843 if (!self->GetScope()) {
3844 NS_WARNING("mScope must not be null when nsXPCComponents::PreCreate is called");
3845 return NS_ERROR_FAILURE;
3846 }
3847 *parentObj = self->GetScope()->GetGlobalJSObject();
3848 return NS_OK;
3849 }