1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code, released
17 : * March 31, 1998.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Netscape Communications Corporation.
21 : * Portions created by the Initial Developer are Copyright (C) 1998
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * John Bandhauer <jband@netscape.com> (original author)
26 : * Pierre Phaneuf <pp@ludusdesign.com>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either of the GNU General Public License Version 2 or later (the "GPL"),
30 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK ***** */
41 :
42 : /* An xpcom implementation of the JavaScript nsIID and nsCID objects. */
43 :
44 : #include "xpcprivate.h"
45 :
46 : /***************************************************************************/
47 : // nsJSID
48 :
49 3162213 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsJSID, nsIJSID)
50 :
51 : char nsJSID::gNoString[] = "";
52 :
53 210367 : nsJSID::nsJSID()
54 210367 : : mID(GetInvalidIID()), mNumber(gNoString), mName(gNoString)
55 : {
56 210367 : }
57 :
58 376365 : nsJSID::~nsJSID()
59 : {
60 210155 : if (mNumber && mNumber != gNoString)
61 6114 : NS_Free(mNumber);
62 210155 : if (mName && mName != gNoString)
63 42359 : NS_Free(mName);
64 752730 : }
65 :
66 42560 : void nsJSID::Reset()
67 : {
68 42560 : mID = GetInvalidIID();
69 :
70 42560 : if (mNumber && mNumber != gNoString)
71 0 : NS_Free(mNumber);
72 42560 : if (mName && mName != gNoString)
73 0 : NS_Free(mName);
74 :
75 42560 : mNumber = mName = nsnull;
76 42560 : }
77 :
78 : bool
79 42558 : nsJSID::SetName(const char* name)
80 : {
81 42558 : NS_ASSERTION(!mName || mName == gNoString ,"name already set");
82 42558 : NS_ASSERTION(name,"null name");
83 42558 : mName = NS_strdup(name);
84 42558 : return mName ? true : false;
85 : }
86 :
87 : NS_IMETHODIMP
88 182 : nsJSID::GetName(char * *aName)
89 : {
90 182 : if (!aName)
91 0 : return NS_ERROR_NULL_POINTER;
92 :
93 182 : if (!NameIsSet())
94 0 : SetNameToNoString();
95 182 : NS_ASSERTION(mName, "name not set");
96 182 : *aName = NS_strdup(mName);
97 182 : return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
98 : }
99 :
100 : NS_IMETHODIMP
101 6124 : nsJSID::GetNumber(char * *aNumber)
102 : {
103 6124 : if (!aNumber)
104 0 : return NS_ERROR_NULL_POINTER;
105 :
106 6124 : if (!mNumber) {
107 6121 : if (!(mNumber = mID.ToString()))
108 0 : mNumber = gNoString;
109 : }
110 :
111 6124 : *aNumber = NS_strdup(mNumber);
112 6124 : return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
113 : }
114 :
115 : NS_IMETHODIMP_(const nsID*)
116 115524 : nsJSID::GetID()
117 : {
118 115524 : return &mID;
119 : }
120 :
121 : NS_IMETHODIMP
122 0 : nsJSID::GetValid(bool *aValid)
123 : {
124 0 : if (!aValid)
125 0 : return NS_ERROR_NULL_POINTER;
126 :
127 0 : *aValid = IsValid();
128 0 : return NS_OK;
129 : }
130 :
131 : NS_IMETHODIMP
132 357213 : nsJSID::Equals(nsIJSID *other, bool *_retval)
133 : {
134 357213 : if (!_retval)
135 0 : return NS_ERROR_NULL_POINTER;
136 :
137 357213 : if (!other || mID.Equals(GetInvalidIID())) {
138 0 : *_retval = false;
139 0 : return NS_OK;
140 : }
141 :
142 357213 : *_retval = other->GetID()->Equals(mID);
143 357213 : return NS_OK;
144 : }
145 :
146 : NS_IMETHODIMP
147 2 : nsJSID::Initialize(const char *idString)
148 : {
149 2 : if (!idString)
150 0 : return NS_ERROR_NULL_POINTER;
151 :
152 2 : if (*idString != '\0' && mID.Equals(GetInvalidIID())) {
153 2 : Reset();
154 :
155 2 : if (idString[0] == '{') {
156 2 : if (mID.Parse(idString)) {
157 2 : return NS_OK;
158 : }
159 :
160 : // error - reset to invalid state
161 0 : mID = GetInvalidIID();
162 : }
163 : }
164 0 : return NS_ERROR_FAILURE;
165 : }
166 :
167 : bool
168 42558 : nsJSID::InitWithName(const nsID& id, const char *nameString)
169 : {
170 42558 : NS_ASSERTION(nameString, "no name");
171 42558 : Reset();
172 42558 : mID = id;
173 42558 : return SetName(nameString);
174 : }
175 :
176 : // try to use the name, if no name, then use the number
177 : NS_IMETHODIMP
178 6306 : nsJSID::ToString(char **_retval)
179 : {
180 6306 : if (mName && mName != gNoString)
181 182 : return GetName(_retval);
182 :
183 6124 : return GetNumber(_retval);
184 : }
185 :
186 : const nsID&
187 779318 : nsJSID::GetInvalidIID() const
188 : {
189 : // {BB1F47B0-D137-11d2-9841-006008962422}
190 : static nsID invalid = {0xbb1f47b0, 0xd137, 0x11d2,
191 : {0x98, 0x41, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22}};
192 779318 : return invalid;
193 : }
194 :
195 : //static
196 : nsJSID*
197 0 : nsJSID::NewID(const char* str)
198 : {
199 0 : if (!str) {
200 0 : NS_ERROR("no string");
201 0 : return nsnull;
202 : }
203 :
204 0 : nsJSID* idObj = new nsJSID();
205 0 : if (idObj) {
206 0 : NS_ADDREF(idObj);
207 0 : if (NS_FAILED(idObj->Initialize(str)))
208 0 : NS_RELEASE(idObj);
209 : }
210 0 : return idObj;
211 : }
212 :
213 : //static
214 : nsJSID*
215 166223 : nsJSID::NewID(const nsID& id)
216 : {
217 166223 : nsJSID* idObj = new nsJSID();
218 166223 : if (idObj) {
219 166223 : NS_ADDREF(idObj);
220 166223 : idObj->mID = id;
221 166223 : idObj->mName = nsnull;
222 166223 : idObj->mNumber = nsnull;
223 : }
224 166223 : return idObj;
225 : }
226 :
227 :
228 : /***************************************************************************/
229 : // Class object support so that we can share prototypes of wrapper
230 :
231 : // This class exists just so we can have a shared scriptable helper for
232 : // the nsJSIID class. The instances implement their own helpers. But we
233 : // needed to be able to indicate to the shared prototypes this single flag:
234 : // nsIXPCScriptable::DONT_ENUM_STATIC_PROPS. And having a class to do it is
235 : // the only means we have. Setting this flag on any given instance scriptable
236 : // helper is not sufficient to convey the information that we don't want
237 : // static properties enumerated on the shared proto.
238 :
239 : class SharedScriptableHelperForJSIID : public nsIXPCScriptable
240 : {
241 : public:
242 : NS_DECL_ISUPPORTS
243 : NS_DECL_NSIXPCSCRIPTABLE
244 1391 : SharedScriptableHelperForJSIID() {}
245 : };
246 :
247 193674 : NS_INTERFACE_MAP_BEGIN(SharedScriptableHelperForJSIID)
248 193674 : NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
249 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
250 0 : NS_INTERFACE_MAP_END_THREADSAFE
251 :
252 297401 : NS_IMPL_THREADSAFE_ADDREF(SharedScriptableHelperForJSIID)
253 298752 : NS_IMPL_THREADSAFE_RELEASE(SharedScriptableHelperForJSIID)
254 :
255 : // The nsIXPCScriptable map declaration that will generate stubs for us...
256 : #define XPC_MAP_CLASSNAME SharedScriptableHelperForJSIID
257 : #define XPC_MAP_QUOTED_CLASSNAME "JSIID"
258 : #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
259 : nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
260 : #include "xpc_map_end.h" /* This will #undef the above */
261 :
262 : static nsIXPCScriptable* gSharedScriptableHelperForJSIID;
263 : static bool gClassObjectsWereInited = false;
264 :
265 91338 : static void EnsureClassObjectsInitialized()
266 : {
267 91338 : if (!gClassObjectsWereInited) {
268 1391 : gSharedScriptableHelperForJSIID = new SharedScriptableHelperForJSIID();
269 1391 : NS_ADDREF(gSharedScriptableHelperForJSIID);
270 :
271 1391 : gClassObjectsWereInited = true;
272 : }
273 91338 : }
274 :
275 91338 : NS_METHOD GetSharedScriptableHelperForJSIID(PRUint32 language,
276 : nsISupports **helper)
277 : {
278 91338 : EnsureClassObjectsInitialized();
279 91338 : if (language == nsIProgrammingLanguage::JAVASCRIPT) {
280 91338 : NS_IF_ADDREF(gSharedScriptableHelperForJSIID);
281 91338 : *helper = gSharedScriptableHelperForJSIID;
282 : } else
283 0 : *helper = nsnull;
284 91338 : return NS_OK;
285 : }
286 :
287 : /******************************************************/
288 :
289 : #define NULL_CID \
290 : { 0x00000000, 0x0000, 0x0000, \
291 : { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
292 :
293 : NS_DECL_CI_INTERFACE_GETTER(nsJSIID)
294 : NS_IMPL_CLASSINFO(nsJSIID, GetSharedScriptableHelperForJSIID,
295 : nsIClassInfo::THREADSAFE, NULL_CID)
296 :
297 : NS_DECL_CI_INTERFACE_GETTER(nsJSCID)
298 : NS_IMPL_CLASSINFO(nsJSCID, NULL, nsIClassInfo::THREADSAFE, NULL_CID)
299 :
300 1404 : void xpc_DestroyJSxIDClassObjects()
301 : {
302 1404 : if (gClassObjectsWereInited) {
303 1391 : NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSIID));
304 1391 : NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSCID));
305 1391 : NS_IF_RELEASE(gSharedScriptableHelperForJSIID);
306 :
307 1391 : gClassObjectsWereInited = false;
308 : }
309 1404 : }
310 :
311 : /***************************************************************************/
312 :
313 1571608 : NS_INTERFACE_MAP_BEGIN(nsJSIID)
314 1571608 : NS_INTERFACE_MAP_ENTRY(nsIJSID)
315 1189316 : NS_INTERFACE_MAP_ENTRY(nsIJSIID)
316 993109 : NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
317 719095 : NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
318 699203 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
319 560713 : NS_IMPL_QUERY_CLASSINFO(nsJSIID)
320 469375 : NS_INTERFACE_MAP_END_THREADSAFE
321 :
322 1198125 : NS_IMPL_THREADSAFE_ADDREF(nsJSIID)
323 1197656 : NS_IMPL_THREADSAFE_RELEASE(nsJSIID)
324 1695 : NS_IMPL_CI_INTERFACE_GETTER2(nsJSIID, nsIJSID, nsIJSIID)
325 :
326 : // The nsIXPCScriptable map declaration that will generate stubs for us...
327 : #define XPC_MAP_CLASSNAME nsJSIID
328 : #define XPC_MAP_QUOTED_CLASSNAME "nsJSIID"
329 : #define XPC_MAP_WANT_NEWRESOLVE
330 : #define XPC_MAP_WANT_ENUMERATE
331 : #define XPC_MAP_WANT_HASINSTANCE
332 : #define XPC_MAP_FLAGS nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
333 : nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
334 : #include "xpc_map_end.h" /* This will #undef the above */
335 :
336 :
337 91336 : nsJSIID::nsJSIID(nsIInterfaceInfo* aInfo)
338 91336 : : mInfo(aInfo)
339 : {
340 91336 : }
341 :
342 363512 : nsJSIID::~nsJSIID() {}
343 :
344 : // If mInfo is present we use it and ignore mDetails, else we use mDetails.
345 :
346 12819 : NS_IMETHODIMP nsJSIID::GetName(char * *aName)
347 : {
348 12819 : return mInfo->GetName(aName);
349 : }
350 :
351 1 : NS_IMETHODIMP nsJSIID::GetNumber(char * *aNumber)
352 : {
353 : char str[NSID_LENGTH];
354 : const nsIID* id;
355 1 : mInfo->GetIIDShared(&id);
356 1 : id->ToProvidedString(str);
357 1 : *aNumber = (char*) nsMemory::Clone(str, NSID_LENGTH);
358 1 : return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
359 : }
360 :
361 635170 : NS_IMETHODIMP_(const nsID*) nsJSIID::GetID()
362 : {
363 : const nsIID* id;
364 635170 : mInfo->GetIIDShared(&id);
365 635170 : return id;
366 : }
367 :
368 0 : NS_IMETHODIMP nsJSIID::GetValid(bool *aValid)
369 : {
370 0 : *aValid = true;
371 0 : return NS_OK;
372 : }
373 :
374 109454 : NS_IMETHODIMP nsJSIID::Equals(nsIJSID *other, bool *_retval)
375 : {
376 109454 : if (!_retval)
377 0 : return NS_ERROR_NULL_POINTER;
378 :
379 109454 : if (!other) {
380 0 : *_retval = false;
381 0 : return NS_OK;
382 : }
383 :
384 109454 : mInfo->IsIID(other->GetID(), _retval);
385 109454 : return NS_OK;
386 : }
387 :
388 0 : NS_IMETHODIMP nsJSIID::Initialize(const char *idString)
389 : {
390 0 : return NS_ERROR_FAILURE;
391 : }
392 :
393 26400 : NS_IMETHODIMP nsJSIID::ToString(char **_retval)
394 : {
395 26400 : return mInfo->GetName(_retval);
396 : }
397 :
398 : // static
399 : nsJSIID*
400 91336 : nsJSIID::NewID(nsIInterfaceInfo* aInfo)
401 : {
402 91336 : if (!aInfo) {
403 0 : NS_ERROR("no info");
404 0 : return nsnull;
405 : }
406 :
407 : bool canScript;
408 91336 : if (NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)
409 0 : return nsnull;
410 :
411 91336 : nsJSIID* idObj = new nsJSIID(aInfo);
412 91336 : NS_IF_ADDREF(idObj);
413 91336 : return idObj;
414 : }
415 :
416 :
417 : /* bool resolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id); */
418 : NS_IMETHODIMP
419 20658 : nsJSIID::NewResolve(nsIXPConnectWrappedNative *wrapper,
420 : JSContext * cx, JSObject * obj,
421 : jsid id, PRUint32 flags,
422 : JSObject * *objp, bool *_retval)
423 : {
424 41316 : XPCCallContext ccx(JS_CALLER, cx);
425 :
426 41316 : AutoMarkingNativeInterfacePtr iface(ccx);
427 :
428 : const nsIID* iid;
429 20658 : mInfo->GetIIDShared(&iid);
430 :
431 20658 : iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
432 :
433 20658 : if (!iface)
434 0 : return NS_OK;
435 :
436 20658 : XPCNativeMember* member = iface->FindMember(id);
437 20658 : if (member && member->IsConstant()) {
438 : jsval val;
439 13719 : if (!member->GetConstantValue(ccx, iface, &val))
440 0 : return NS_ERROR_OUT_OF_MEMORY;
441 :
442 13719 : *objp = obj;
443 : *_retval = JS_DefinePropertyById(cx, obj, id, val, nsnull, nsnull,
444 : JSPROP_ENUMERATE | JSPROP_READONLY |
445 13719 : JSPROP_PERMANENT);
446 : }
447 :
448 20658 : return NS_OK;
449 : }
450 :
451 : /* bool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */
452 : NS_IMETHODIMP
453 0 : nsJSIID::Enumerate(nsIXPConnectWrappedNative *wrapper,
454 : JSContext * cx, JSObject * obj, bool *_retval)
455 : {
456 : // In this case, let's just eagerly resolve...
457 :
458 0 : XPCCallContext ccx(JS_CALLER, cx);
459 :
460 0 : AutoMarkingNativeInterfacePtr iface(ccx);
461 :
462 : const nsIID* iid;
463 0 : mInfo->GetIIDShared(&iid);
464 :
465 0 : iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
466 :
467 0 : if (!iface)
468 0 : return NS_OK;
469 :
470 0 : PRUint16 count = iface->GetMemberCount();
471 0 : for (PRUint16 i = 0; i < count; i++) {
472 0 : XPCNativeMember* member = iface->GetMemberAt(i);
473 0 : if (member && member->IsConstant() &&
474 0 : !xpc_ForcePropertyResolve(cx, obj, member->GetName())) {
475 0 : return NS_ERROR_UNEXPECTED;
476 : }
477 : }
478 0 : return NS_OK;
479 : }
480 :
481 : /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
482 : NS_IMETHODIMP
483 165302 : nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
484 : JSContext * cx, JSObject * obj,
485 : const jsval &val, bool *bp, bool *_retval)
486 : {
487 165302 : *bp = false;
488 165302 : nsresult rv = NS_OK;
489 :
490 165302 : if (!JSVAL_IS_PRIMITIVE(val)) {
491 : // we have a JSObject
492 62400 : JSObject* obj = JSVAL_TO_OBJECT(val);
493 :
494 62400 : NS_ASSERTION(obj, "when is an object not an object?");
495 :
496 : // is this really a native xpcom object with a wrapper?
497 : const nsIID* iid;
498 62400 : mInfo->GetIIDShared(&iid);
499 :
500 62400 : if (IS_SLIM_WRAPPER(obj)) {
501 8764 : XPCWrappedNativeProto* proto = GetSlimWrapperProto(obj);
502 8764 : if (proto->GetSet()->HasInterfaceWithAncestor(iid)) {
503 3763 : *bp = true;
504 3763 : return NS_OK;
505 : }
506 :
507 : #ifdef DEBUG_slimwrappers
508 : char foo[NSID_LENGTH];
509 : iid->ToProvidedString(foo);
510 : SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, foo);
511 : #endif
512 5001 : if (!MorphSlimWrapper(cx, obj))
513 0 : return NS_ERROR_FAILURE;
514 : }
515 :
516 58637 : if (mozilla::dom::binding::instanceIsProxy(obj)) {
517 : nsISupports *identity =
518 12 : static_cast<nsISupports*>(js::GetProxyPrivate(obj).toPrivate());
519 24 : nsCOMPtr<nsIClassInfo> ci = do_QueryInterface(identity);
520 :
521 24 : XPCCallContext ccx(JS_CALLER, cx);
522 :
523 24 : AutoMarkingNativeSetPtr set(ccx);
524 12 : set = XPCNativeSet::GetNewOrUsed(ccx, ci);
525 12 : if (!set)
526 0 : return NS_ERROR_FAILURE;
527 12 : *bp = set->HasInterfaceWithAncestor(iid);
528 12 : return NS_OK;
529 : }
530 :
531 : XPCWrappedNative* other_wrapper =
532 58625 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
533 :
534 58625 : if (!other_wrapper)
535 69 : return NS_OK;
536 :
537 : // We'll trust the interface set of the wrapper if this is known
538 : // to be an interface that the objects *expects* to be able to
539 : // handle.
540 58556 : if (other_wrapper->HasInterfaceNoQI(*iid)) {
541 37294 : *bp = true;
542 37294 : return NS_OK;
543 : }
544 :
545 : // Otherwise, we'll end up Querying the native object to be sure.
546 42524 : XPCCallContext ccx(JS_CALLER, cx);
547 :
548 42524 : AutoMarkingNativeInterfacePtr iface(ccx);
549 21262 : iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
550 :
551 21262 : nsresult findResult = NS_OK;
552 21262 : if (iface && other_wrapper->FindTearOff(ccx, iface, false, &findResult))
553 15102 : *bp = true;
554 21262 : if (NS_FAILED(findResult) && findResult != NS_ERROR_NO_INTERFACE)
555 0 : rv = findResult;
556 : }
557 124164 : return rv;
558 : }
559 :
560 : /* string canCreateWrapper (in nsIIDPtr iid); */
561 : NS_IMETHODIMP
562 19892 : nsJSIID::CanCreateWrapper(const nsIID * iid, char **_retval)
563 : {
564 : // We let anyone do this...
565 19892 : *_retval = xpc_CloneAllAccess();
566 19892 : return NS_OK;
567 : }
568 :
569 : /* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
570 : NS_IMETHODIMP
571 0 : nsJSIID::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
572 : {
573 : static const char* allowed[] = {"equals", "toString", nsnull};
574 :
575 0 : *_retval = xpc_CheckAccessList(methodName, allowed);
576 0 : return NS_OK;
577 : }
578 :
579 : /* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
580 : NS_IMETHODIMP
581 0 : nsJSIID::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
582 : {
583 : static const char* allowed[] = {"name", "number", "valid", nsnull};
584 0 : *_retval = xpc_CheckAccessList(propertyName, allowed);
585 0 : return NS_OK;
586 : }
587 :
588 : /* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
589 : NS_IMETHODIMP
590 0 : nsJSIID::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
591 : {
592 : // If you have to ask, then the answer is NO
593 0 : *_retval = nsnull;
594 0 : return NS_OK;
595 : }
596 :
597 : /***************************************************************************/
598 :
599 631579 : NS_INTERFACE_MAP_BEGIN(nsJSCID)
600 631579 : NS_INTERFACE_MAP_ENTRY(nsIJSID)
601 631577 : NS_INTERFACE_MAP_ENTRY(nsIJSCID)
602 519167 : NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
603 391487 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
604 301777 : NS_IMPL_QUERY_CLASSINFO(nsJSCID)
605 259217 : NS_INTERFACE_MAP_END_THREADSAFE
606 :
607 421062 : NS_IMPL_THREADSAFE_ADDREF(nsJSCID)
608 420863 : NS_IMPL_THREADSAFE_RELEASE(nsJSCID)
609 1768 : NS_IMPL_CI_INTERFACE_GETTER2(nsJSCID, nsIJSID, nsIJSCID)
610 :
611 : // The nsIXPCScriptable map declaration that will generate stubs for us...
612 : #define XPC_MAP_CLASSNAME nsJSCID
613 : #define XPC_MAP_QUOTED_CLASSNAME "nsJSCID"
614 : #define XPC_MAP_WANT_CONSTRUCT
615 : #define XPC_MAP_WANT_HASINSTANCE
616 : #define XPC_MAP_FLAGS 0
617 : #include "xpc_map_end.h" /* This will #undef the above */
618 :
619 44144 : nsJSCID::nsJSCID() {}
620 175780 : nsJSCID::~nsJSCID() {}
621 :
622 0 : NS_IMETHODIMP nsJSCID::GetName(char * *aName)
623 0 : {ResolveName(); return mDetails.GetName(aName);}
624 :
625 0 : NS_IMETHODIMP nsJSCID::GetNumber(char * *aNumber)
626 0 : {return mDetails.GetNumber(aNumber);}
627 :
628 1390 : NS_IMETHODIMP_(const nsID*) nsJSCID::GetID()
629 1390 : {return &mDetails.ID();}
630 :
631 0 : NS_IMETHODIMP nsJSCID::GetValid(bool *aValid)
632 0 : {return mDetails.GetValid(aValid);}
633 :
634 1 : NS_IMETHODIMP nsJSCID::Equals(nsIJSID *other, bool *_retval)
635 1 : {return mDetails.Equals(other, _retval);}
636 :
637 2 : NS_IMETHODIMP nsJSCID::Initialize(const char *idString)
638 2 : {return mDetails.Initialize(idString);}
639 :
640 182 : NS_IMETHODIMP nsJSCID::ToString(char **_retval)
641 182 : {ResolveName(); return mDetails.ToString(_retval);}
642 :
643 : void
644 182 : nsJSCID::ResolveName()
645 : {
646 182 : if (!mDetails.NameIsSet())
647 0 : mDetails.SetNameToNoString();
648 182 : }
649 :
650 : //static
651 : nsJSCID*
652 44144 : nsJSCID::NewID(const char* str)
653 : {
654 44144 : if (!str) {
655 0 : NS_ERROR("no string");
656 0 : return nsnull;
657 : }
658 :
659 44144 : nsJSCID* idObj = new nsJSCID();
660 44144 : if (idObj) {
661 44144 : bool success = false;
662 44144 : NS_ADDREF(idObj);
663 :
664 44144 : if (str[0] == '{') {
665 2 : if (NS_SUCCEEDED(idObj->Initialize(str)))
666 2 : success = true;
667 : } else {
668 88284 : nsCOMPtr<nsIComponentRegistrar> registrar;
669 44142 : NS_GetComponentRegistrar(getter_AddRefs(registrar));
670 44142 : if (registrar) {
671 : nsCID *cid;
672 44142 : if (NS_SUCCEEDED(registrar->ContractIDToCID(str, &cid))) {
673 42558 : success = idObj->mDetails.InitWithName(*cid, str);
674 42558 : nsMemory::Free(cid);
675 : }
676 : }
677 : }
678 44144 : if (!success)
679 1584 : NS_RELEASE(idObj);
680 : }
681 44144 : return idObj;
682 : }
683 :
684 : static const nsID*
685 169176 : GetIIDArg(PRUint32 argc, const JS::Value& val, JSContext* cx)
686 : {
687 : const nsID* iid;
688 :
689 : // If an IID was passed in then use it
690 169176 : if (argc) {
691 : JSObject* iidobj;
692 161981 : if (JSVAL_IS_PRIMITIVE(val) ||
693 : !(iidobj = JSVAL_TO_OBJECT(val)) ||
694 : !(iid = xpc_JSObjectToID(cx, iidobj))) {
695 0 : return nsnull;
696 : }
697 : } else
698 7195 : iid = &NS_GET_IID(nsISupports);
699 :
700 169176 : return iid;
701 : }
702 :
703 : static JSObject*
704 169176 : GetWrapperObject()
705 : {
706 169176 : nsXPConnect* xpc = nsXPConnect::GetXPConnect();
707 169176 : if (!xpc)
708 0 : return NULL;
709 :
710 169176 : nsAXPCNativeCallContext *ccxp = NULL;
711 169176 : xpc->GetCurrentNativeCallContext(&ccxp);
712 169176 : if (!ccxp)
713 0 : return NULL;
714 :
715 338352 : nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
716 169176 : ccxp->GetCalleeWrapper(getter_AddRefs(wrapper));
717 : JSObject* obj;
718 169176 : wrapper->GetJSObject(&obj);
719 169176 : return obj;
720 : }
721 :
722 : /* nsISupports createInstance (); */
723 : NS_IMETHODIMP
724 100743 : nsJSCID::CreateInstance(const JS::Value& iidval, JSContext* cx,
725 : PRUint8 optionalArgc, JS::Value* retval)
726 : {
727 100743 : if (!mDetails.IsValid())
728 0 : return NS_ERROR_XPC_BAD_CID;
729 :
730 100743 : JSObject* obj = GetWrapperObject();
731 100743 : if (!obj) {
732 0 : return NS_ERROR_UNEXPECTED;
733 : }
734 :
735 : // Do the security check if necessary
736 100743 : XPCContext* xpcc = XPCContext::GetXPCContext(cx);
737 :
738 : nsIXPCSecurityManager* sm;
739 100743 : sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
740 100743 : if (sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID()))) {
741 0 : NS_ERROR("how are we not being called from chrome here?");
742 0 : return NS_OK;
743 : }
744 :
745 : // If an IID was passed in then use it
746 100743 : const nsID* iid = GetIIDArg(optionalArgc, iidval, cx);
747 100743 : if (!iid)
748 0 : return NS_ERROR_XPC_BAD_IID;
749 :
750 201486 : nsCOMPtr<nsIComponentManager> compMgr;
751 100743 : nsresult rv = NS_GetComponentManager(getter_AddRefs(compMgr));
752 100743 : if (NS_FAILED(rv))
753 0 : return NS_ERROR_UNEXPECTED;
754 :
755 201486 : nsCOMPtr<nsISupports> inst;
756 100743 : rv = compMgr->CreateInstance(mDetails.ID(), nsnull, *iid, getter_AddRefs(inst));
757 100743 : NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!");
758 :
759 100743 : if (NS_FAILED(rv) || !inst)
760 1 : return NS_ERROR_XPC_CI_RETURNED_FAILURE;
761 :
762 100742 : rv = nsXPConnect::GetXPConnect()->WrapNativeToJSVal(cx, obj, inst, nsnull, iid, true, retval, nsnull);
763 100742 : if (NS_FAILED(rv) || JSVAL_IS_PRIMITIVE(*retval))
764 0 : return NS_ERROR_XPC_CANT_CREATE_WN;
765 100742 : return NS_OK;
766 : }
767 :
768 : /* nsISupports getService (); */
769 : NS_IMETHODIMP
770 68433 : nsJSCID::GetService(const JS::Value& iidval, JSContext* cx,
771 : PRUint8 optionalArgc, JS::Value* retval)
772 : {
773 68433 : if (!mDetails.IsValid())
774 0 : return NS_ERROR_XPC_BAD_CID;
775 :
776 68433 : JSObject* obj = GetWrapperObject();
777 68433 : if (!obj) {
778 0 : return NS_ERROR_UNEXPECTED;
779 : }
780 :
781 : // Do the security check if necessary
782 68433 : XPCContext* xpcc = XPCContext::GetXPCContext(cx);
783 :
784 : nsIXPCSecurityManager* sm;
785 68433 : sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_GET_SERVICE);
786 68433 : if (sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID()))) {
787 0 : NS_ASSERTION(JS_IsExceptionPending(cx),
788 : "security manager vetoed GetService without setting exception");
789 0 : return NS_OK;
790 : }
791 :
792 : // If an IID was passed in then use it
793 68433 : const nsID* iid = GetIIDArg(optionalArgc, iidval, cx);
794 68433 : if (!iid)
795 0 : return NS_ERROR_XPC_BAD_IID;
796 :
797 136866 : nsCOMPtr<nsIServiceManager> svcMgr;
798 68433 : nsresult rv = NS_GetServiceManager(getter_AddRefs(svcMgr));
799 68433 : if (NS_FAILED(rv))
800 0 : return rv;
801 :
802 136866 : nsCOMPtr<nsISupports> srvc;
803 68433 : rv = svcMgr->GetService(mDetails.ID(), *iid, getter_AddRefs(srvc));
804 68433 : NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!");
805 68433 : if (NS_FAILED(rv) || !srvc)
806 11 : return NS_ERROR_XPC_GS_RETURNED_FAILURE;
807 :
808 : JSObject* instJSObj;
809 136844 : nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
810 68422 : rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj, srvc, *iid, getter_AddRefs(holder));
811 68422 : if (NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
812 0 : return NS_ERROR_XPC_CANT_CREATE_WN;
813 :
814 68422 : *retval = OBJECT_TO_JSVAL(instJSObj);
815 68422 : return NS_OK;
816 : }
817 :
818 : /* bool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
819 : NS_IMETHODIMP
820 0 : nsJSCID::Construct(nsIXPConnectWrappedNative *wrapper,
821 : JSContext * cx, JSObject * obj,
822 : PRUint32 argc, jsval * argv, jsval * vp,
823 : bool *_retval)
824 : {
825 0 : XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
826 0 : if (!rt)
827 0 : return NS_ERROR_FAILURE;
828 :
829 : // 'push' a call context and call on it
830 : XPCCallContext ccx(JS_CALLER, cx, obj, nsnull,
831 : rt->GetStringID(XPCJSRuntime::IDX_CREATE_INSTANCE),
832 0 : argc, argv, vp);
833 :
834 0 : *_retval = XPCWrappedNative::CallMethod(ccx);
835 0 : return NS_OK;
836 : }
837 :
838 : /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
839 : NS_IMETHODIMP
840 0 : nsJSCID::HasInstance(nsIXPConnectWrappedNative *wrapper,
841 : JSContext * cx, JSObject * obj,
842 : const jsval &val, bool *bp, bool *_retval)
843 : {
844 0 : *bp = false;
845 0 : nsresult rv = NS_OK;
846 :
847 0 : if (!JSVAL_IS_PRIMITIVE(val)) {
848 : // we have a JSObject
849 0 : JSObject* obj = JSVAL_TO_OBJECT(val);
850 :
851 0 : NS_ASSERTION(obj, "when is an object not an object?");
852 :
853 : // is this really a native xpcom object with a wrapper?
854 : JSObject* obj2;
855 : XPCWrappedNative* other_wrapper =
856 0 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, nsnull, &obj2);
857 :
858 0 : if (!other_wrapper && !obj2)
859 0 : return NS_OK;
860 :
861 : nsIClassInfo* ci = other_wrapper ?
862 : other_wrapper->GetClassInfo() :
863 0 : GetSlimWrapperProto(obj2)->GetClassInfo();
864 :
865 : // We consider CID equality to be the thing that matters here.
866 : // This is perhaps debatable.
867 0 : if (ci) {
868 : nsID cid;
869 0 : if (NS_SUCCEEDED(ci->GetClassIDNoAlloc(&cid)))
870 0 : *bp = cid.Equals(mDetails.ID());
871 : }
872 : }
873 0 : return rv;
874 : }
875 :
876 : /***************************************************************************/
877 : // additional utilities...
878 :
879 : JSObject *
880 166223 : xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID)
881 : {
882 166223 : JSObject *obj = nsnull;
883 :
884 : nsCOMPtr<nsIJSID> iid =
885 332446 : dont_AddRef(static_cast<nsIJSID*>(nsJSID::NewID(aID)));
886 166223 : if (iid) {
887 166223 : nsXPConnect* xpc = nsXPConnect::GetXPConnect();
888 166223 : if (xpc) {
889 332446 : nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
890 : nsresult rv = xpc->WrapNative(cx, jsobj,
891 166223 : static_cast<nsISupports*>(iid),
892 : NS_GET_IID(nsIJSID),
893 332446 : getter_AddRefs(holder));
894 166223 : if (NS_SUCCEEDED(rv) && holder) {
895 166223 : holder->GetJSObject(&obj);
896 : }
897 : }
898 : }
899 166223 : return obj;
900 : }
901 :
902 : // note: returned pointer is only valid while |obj| remains alive!
903 : const nsID*
904 286304 : xpc_JSObjectToID(JSContext *cx, JSObject* obj)
905 : {
906 286304 : if (!cx || !obj)
907 0 : return nsnull;
908 :
909 : // NOTE: this call does NOT addref
910 : XPCWrappedNative* wrapper =
911 286304 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
912 572480 : if (wrapper &&
913 285670 : (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) ||
914 253 : wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
915 253 : wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID)))) {
916 285417 : return ((nsIJSID*)wrapper->GetIdentityObject())->GetID();
917 : }
918 887 : return nsnull;
919 : }
920 :
921 : JSBool
922 99 : xpc_JSObjectIsID(JSContext *cx, JSObject* obj)
923 : {
924 99 : NS_ASSERTION(cx && obj, "bad param");
925 : // NOTE: this call does NOT addref
926 : XPCWrappedNative* wrapper =
927 99 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
928 : return wrapper &&
929 3 : (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) ||
930 3 : wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
931 105 : wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID)));
932 : }
933 :
934 :
|