js/xpconnect/src/XPCComponents.cpp

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

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

mercurial