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 2991381 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsJSID, nsIJSID)
50 :
51 : char nsJSID::gNoString[] = "";
52 :
53 201623 : nsJSID::nsJSID()
54 201623 : : mID(GetInvalidIID()), mNumber(gNoString), mName(gNoString)
55 : {
56 201623 : }
57 :
58 359067 : nsJSID::~nsJSID()
59 : {
60 201411 : if (mNumber && mNumber != gNoString)
61 6089 : NS_Free(mNumber);
62 201411 : if (mName && mName != gNoString)
63 42188 : NS_Free(mName);
64 718134 : }
65 :
66 42390 : void nsJSID::Reset()
67 : {
68 42390 : mID = GetInvalidIID();
69 :
70 42390 : if (mNumber && mNumber != gNoString)
71 0 : NS_Free(mNumber);
72 42390 : if (mName && mName != gNoString)
73 0 : NS_Free(mName);
74 :
75 42390 : mNumber = mName = nsnull;
76 42390 : }
77 :
78 : bool
79 42387 : nsJSID::SetName(const char* name)
80 : {
81 42387 : NS_ASSERTION(!mName || mName == gNoString ,"name already set");
82 42387 : NS_ASSERTION(name,"null name");
83 42387 : mName = NS_strdup(name);
84 42387 : return mName ? true : false;
85 : }
86 :
87 : NS_IMETHODIMP
88 0 : nsJSID::GetName(char * *aName)
89 : {
90 0 : if (!aName)
91 0 : return NS_ERROR_NULL_POINTER;
92 :
93 0 : if (!NameIsSet())
94 0 : SetNameToNoString();
95 0 : NS_ASSERTION(mName, "name not set");
96 0 : *aName = NS_strdup(mName);
97 0 : return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
98 : }
99 :
100 : NS_IMETHODIMP
101 6099 : nsJSID::GetNumber(char * *aNumber)
102 : {
103 6099 : if (!aNumber)
104 0 : return NS_ERROR_NULL_POINTER;
105 :
106 6099 : if (!mNumber) {
107 6096 : if (!(mNumber = mID.ToString()))
108 0 : mNumber = gNoString;
109 : }
110 :
111 6099 : *aNumber = NS_strdup(mNumber);
112 6099 : return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
113 : }
114 :
115 : NS_IMETHODIMP_(const nsID*)
116 106986 : nsJSID::GetID()
117 : {
118 106986 : 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 343444 : nsJSID::Equals(nsIJSID *other, bool *_retval)
133 : {
134 343444 : if (!_retval)
135 0 : return NS_ERROR_NULL_POINTER;
136 :
137 343444 : if (!other || mID.Equals(GetInvalidIID())) {
138 0 : *_retval = false;
139 0 : return NS_OK;
140 : }
141 :
142 343444 : *_retval = other->GetID()->Equals(mID);
143 343444 : return NS_OK;
144 : }
145 :
146 : NS_IMETHODIMP
147 3 : nsJSID::Initialize(const char *idString)
148 : {
149 3 : if (!idString)
150 0 : return NS_ERROR_NULL_POINTER;
151 :
152 3 : if (*idString != '\0' && mID.Equals(GetInvalidIID())) {
153 3 : Reset();
154 :
155 3 : if (idString[0] == '{') {
156 3 : if (mID.Parse(idString)) {
157 3 : 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 42387 : nsJSID::InitWithName(const nsID& id, const char *nameString)
169 : {
170 42387 : NS_ASSERTION(nameString, "no name");
171 42387 : Reset();
172 42387 : mID = id;
173 42387 : return SetName(nameString);
174 : }
175 :
176 : // try to use the name, if no name, then use the number
177 : NS_IMETHODIMP
178 6099 : nsJSID::ToString(char **_retval)
179 : {
180 6099 : if (mName && mName != gNoString)
181 0 : return GetName(_retval);
182 :
183 6099 : return GetNumber(_retval);
184 : }
185 :
186 : const nsID&
187 773698 : 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 773698 : 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 157669 : nsJSID::NewID(const nsID& id)
216 : {
217 157669 : nsJSID* idObj = new nsJSID();
218 157669 : if (idObj) {
219 157669 : NS_ADDREF(idObj);
220 157669 : idObj->mID = id;
221 157669 : idObj->mName = nsnull;
222 157669 : idObj->mNumber = nsnull;
223 : }
224 157669 : 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 1365 : SharedScriptableHelperForJSIID() {}
245 : };
246 :
247 192906 : NS_INTERFACE_MAP_BEGIN(SharedScriptableHelperForJSIID)
248 192906 : NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
249 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
250 0 : NS_INTERFACE_MAP_END_THREADSAFE
251 :
252 296202 : NS_IMPL_THREADSAFE_ADDREF(SharedScriptableHelperForJSIID)
253 297527 : 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 90975 : static void EnsureClassObjectsInitialized()
266 : {
267 90975 : if (!gClassObjectsWereInited) {
268 1365 : gSharedScriptableHelperForJSIID = new SharedScriptableHelperForJSIID();
269 1365 : NS_ADDREF(gSharedScriptableHelperForJSIID);
270 :
271 1365 : gClassObjectsWereInited = true;
272 : }
273 90975 : }
274 :
275 90975 : NS_METHOD GetSharedScriptableHelperForJSIID(PRUint32 language,
276 : nsISupports **helper)
277 : {
278 90975 : EnsureClassObjectsInitialized();
279 90975 : if (language == nsIProgrammingLanguage::JAVASCRIPT) {
280 90975 : NS_IF_ADDREF(gSharedScriptableHelperForJSIID);
281 90975 : *helper = gSharedScriptableHelperForJSIID;
282 : } else
283 0 : *helper = nsnull;
284 90975 : 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 1365 : void xpc_DestroyJSxIDClassObjects()
301 : {
302 1365 : if (gClassObjectsWereInited) {
303 1365 : NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSIID));
304 1365 : NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSCID));
305 1365 : NS_IF_RELEASE(gSharedScriptableHelperForJSIID);
306 :
307 1365 : gClassObjectsWereInited = false;
308 : }
309 1365 : }
310 :
311 : /***************************************************************************/
312 :
313 1555216 : NS_INTERFACE_MAP_BEGIN(nsJSIID)
314 1555216 : NS_INTERFACE_MAP_ENTRY(nsIJSID)
315 1186680 : NS_INTERFACE_MAP_ENTRY(nsIJSIID)
316 991172 : NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
317 718247 : NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
318 698345 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
319 560044 : NS_IMPL_QUERY_CLASSINFO(nsJSIID)
320 469069 : NS_INTERFACE_MAP_END_THREADSAFE
321 :
322 1181667 : NS_IMPL_THREADSAFE_ADDREF(nsJSIID)
323 1181198 : NS_IMPL_THREADSAFE_RELEASE(nsJSIID)
324 1667 : 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 90973 : nsJSIID::nsJSIID(nsIInterfaceInfo* aInfo)
338 90973 : : mInfo(aInfo)
339 : {
340 90973 : }
341 :
342 362060 : nsJSIID::~nsJSIID() {}
343 :
344 : // If mInfo is present we use it and ignore mDetails, else we use mDetails.
345 :
346 12787 : NS_IMETHODIMP nsJSIID::GetName(char * *aName)
347 : {
348 12787 : 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 632211 : NS_IMETHODIMP_(const nsID*) nsJSIID::GetID()
362 : {
363 : const nsIID* id;
364 632211 : mInfo->GetIIDShared(&id);
365 632211 : 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 101000 : NS_IMETHODIMP nsJSIID::Equals(nsIJSID *other, bool *_retval)
375 : {
376 101000 : if (!_retval)
377 0 : return NS_ERROR_NULL_POINTER;
378 :
379 101000 : if (!other) {
380 0 : *_retval = false;
381 0 : return NS_OK;
382 : }
383 :
384 101000 : mInfo->IsIID(other->GetID(), _retval);
385 101000 : return NS_OK;
386 : }
387 :
388 0 : NS_IMETHODIMP nsJSIID::Initialize(const char *idString)
389 : {
390 0 : return NS_ERROR_FAILURE;
391 : }
392 :
393 26336 : NS_IMETHODIMP nsJSIID::ToString(char **_retval)
394 : {
395 26336 : return mInfo->GetName(_retval);
396 : }
397 :
398 : // static
399 : nsJSIID*
400 90973 : nsJSIID::NewID(nsIInterfaceInfo* aInfo)
401 : {
402 90973 : if (!aInfo) {
403 0 : NS_ERROR("no info");
404 0 : return nsnull;
405 : }
406 :
407 : bool canScript;
408 90973 : if (NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)
409 0 : return nsnull;
410 :
411 90973 : nsJSIID* idObj = new nsJSIID(aInfo);
412 90973 : NS_IF_ADDREF(idObj);
413 90973 : return idObj;
414 : }
415 :
416 :
417 : /* bool resolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id); */
418 : NS_IMETHODIMP
419 19155 : nsJSIID::NewResolve(nsIXPConnectWrappedNative *wrapper,
420 : JSContext * cx, JSObject * obj,
421 : jsid id, PRUint32 flags,
422 : JSObject * *objp, bool *_retval)
423 : {
424 38310 : XPCCallContext ccx(JS_CALLER, cx);
425 :
426 38310 : AutoMarkingNativeInterfacePtr iface(ccx);
427 :
428 : const nsIID* iid;
429 19155 : mInfo->GetIIDShared(&iid);
430 :
431 19155 : iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
432 :
433 19155 : if (!iface)
434 0 : return NS_OK;
435 :
436 19155 : XPCNativeMember* member = iface->FindMember(id);
437 19155 : if (member && member->IsConstant()) {
438 : jsval val;
439 13690 : if (!member->GetConstantValue(ccx, iface, &val))
440 0 : return NS_ERROR_OUT_OF_MEMORY;
441 :
442 13690 : *objp = obj;
443 : *_retval = JS_DefinePropertyById(cx, obj, id, val, nsnull, nsnull,
444 : JSPROP_ENUMERATE | JSPROP_READONLY |
445 13690 : JSPROP_PERMANENT);
446 : }
447 :
448 19155 : 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 165335 : nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
484 : JSContext * cx, JSObject * obj,
485 : const jsval &val, bool *bp, bool *_retval)
486 : {
487 165335 : *bp = false;
488 165335 : nsresult rv = NS_OK;
489 :
490 165335 : if (!JSVAL_IS_PRIMITIVE(val)) {
491 : // we have a JSObject
492 62392 : JSObject* obj = JSVAL_TO_OBJECT(val);
493 :
494 62392 : 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 62392 : mInfo->GetIIDShared(&iid);
499 :
500 62392 : 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 58629 : 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 58617 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
533 :
534 58617 : 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 58548 : if (other_wrapper->HasInterfaceNoQI(*iid)) {
541 37281 : *bp = true;
542 37281 : return NS_OK;
543 : }
544 :
545 : // Otherwise, we'll end up Querying the native object to be sure.
546 42534 : XPCCallContext ccx(JS_CALLER, cx);
547 :
548 42534 : AutoMarkingNativeInterfacePtr iface(ccx);
549 21267 : iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
550 :
551 21267 : nsresult findResult = NS_OK;
552 21267 : if (iface && other_wrapper->FindTearOff(ccx, iface, false, &findResult))
553 15107 : *bp = true;
554 21267 : if (NS_FAILED(findResult) && findResult != NS_ERROR_NO_INTERFACE)
555 0 : rv = findResult;
556 : }
557 124210 : return rv;
558 : }
559 :
560 : /* string canCreateWrapper (in nsIIDPtr iid); */
561 : NS_IMETHODIMP
562 19902 : nsJSIID::CanCreateWrapper(const nsIID * iid, char **_retval)
563 : {
564 : // We let anyone do this...
565 19902 : *_retval = xpc_CloneAllAccess();
566 19902 : 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 630958 : NS_INTERFACE_MAP_BEGIN(nsJSCID)
600 630958 : NS_INTERFACE_MAP_ENTRY(nsIJSID)
601 630957 : NS_INTERFACE_MAP_ENTRY(nsIJSCID)
602 518733 : NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
603 391563 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
604 301849 : NS_IMPL_QUERY_CLASSINFO(nsJSCID)
605 259459 : NS_INTERFACE_MAP_END_THREADSAFE
606 :
607 420000 : NS_IMPL_THREADSAFE_ADDREF(nsJSCID)
608 419801 : NS_IMPL_THREADSAFE_RELEASE(nsJSCID)
609 1744 : 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 43954 : nsJSCID::nsJSCID() {}
620 175020 : 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 1369 : NS_IMETHODIMP_(const nsID*) nsJSCID::GetID()
629 1369 : {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 3 : NS_IMETHODIMP nsJSCID::Initialize(const char *idString)
638 3 : {return mDetails.Initialize(idString);}
639 :
640 0 : NS_IMETHODIMP nsJSCID::ToString(char **_retval)
641 0 : {ResolveName(); return mDetails.ToString(_retval);}
642 :
643 : void
644 0 : nsJSCID::ResolveName()
645 : {
646 0 : if (!mDetails.NameIsSet())
647 0 : mDetails.SetNameToNoString();
648 0 : }
649 :
650 : //static
651 : nsJSCID*
652 43954 : nsJSCID::NewID(const char* str)
653 : {
654 43954 : if (!str) {
655 0 : NS_ERROR("no string");
656 0 : return nsnull;
657 : }
658 :
659 43954 : nsJSCID* idObj = new nsJSCID();
660 43954 : if (idObj) {
661 43954 : bool success = false;
662 43954 : NS_ADDREF(idObj);
663 :
664 43954 : if (str[0] == '{') {
665 3 : if (NS_SUCCEEDED(idObj->Initialize(str)))
666 3 : success = true;
667 : } else {
668 87902 : nsCOMPtr<nsIComponentRegistrar> registrar;
669 43951 : NS_GetComponentRegistrar(getter_AddRefs(registrar));
670 43951 : if (registrar) {
671 : nsCID *cid;
672 43951 : if (NS_SUCCEEDED(registrar->ContractIDToCID(str, &cid))) {
673 42387 : success = idObj->mDetails.InitWithName(*cid, str);
674 42387 : nsMemory::Free(cid);
675 : }
676 : }
677 : }
678 43954 : if (!success)
679 1564 : NS_RELEASE(idObj);
680 : }
681 43954 : return idObj;
682 : }
683 :
684 : static const nsID*
685 186238 : 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 186238 : if (argc) {
691 : JSObject* iidobj;
692 179056 : 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 7182 : iid = &NS_GET_IID(nsISupports);
699 :
700 186238 : return iid;
701 : }
702 :
703 : static JSObject*
704 186238 : GetWrapperObject()
705 : {
706 186238 : nsXPConnect* xpc = nsXPConnect::GetXPConnect();
707 186238 : if (!xpc)
708 0 : return NULL;
709 :
710 186238 : nsAXPCNativeCallContext *ccxp = NULL;
711 186238 : xpc->GetCurrentNativeCallContext(&ccxp);
712 186238 : if (!ccxp)
713 0 : return NULL;
714 :
715 372476 : nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
716 186238 : ccxp->GetCalleeWrapper(getter_AddRefs(wrapper));
717 : JSObject* obj;
718 186238 : wrapper->GetJSObject(&obj);
719 186238 : return obj;
720 : }
721 :
722 : /* nsISupports createInstance (); */
723 : NS_IMETHODIMP
724 96906 : nsJSCID::CreateInstance(const JS::Value& iidval, JSContext* cx,
725 : PRUint8 optionalArgc, JS::Value* retval)
726 : {
727 96906 : if (!mDetails.IsValid())
728 0 : return NS_ERROR_XPC_BAD_CID;
729 :
730 96906 : JSObject* obj = GetWrapperObject();
731 96906 : if (!obj) {
732 0 : return NS_ERROR_UNEXPECTED;
733 : }
734 :
735 : // Do the security check if necessary
736 96906 : XPCContext* xpcc = XPCContext::GetXPCContext(cx);
737 :
738 : nsIXPCSecurityManager* sm;
739 96906 : sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
740 96906 : 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 96906 : const nsID* iid = GetIIDArg(optionalArgc, iidval, cx);
747 96906 : if (!iid)
748 0 : return NS_ERROR_XPC_BAD_IID;
749 :
750 193812 : nsCOMPtr<nsIComponentManager> compMgr;
751 96906 : nsresult rv = NS_GetComponentManager(getter_AddRefs(compMgr));
752 96906 : if (NS_FAILED(rv))
753 0 : return NS_ERROR_UNEXPECTED;
754 :
755 193812 : nsCOMPtr<nsISupports> inst;
756 96906 : rv = compMgr->CreateInstance(mDetails.ID(), nsnull, *iid, getter_AddRefs(inst));
757 96906 : NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!");
758 :
759 96906 : if (NS_FAILED(rv) || !inst)
760 1 : return NS_ERROR_XPC_CI_RETURNED_FAILURE;
761 :
762 96905 : rv = nsXPConnect::GetXPConnect()->WrapNativeToJSVal(cx, obj, inst, nsnull, iid, true, retval, nsnull);
763 96905 : if (NS_FAILED(rv) || JSVAL_IS_PRIMITIVE(*retval))
764 0 : return NS_ERROR_XPC_CANT_CREATE_WN;
765 96905 : return NS_OK;
766 : }
767 :
768 : /* nsISupports getService (); */
769 : NS_IMETHODIMP
770 89332 : nsJSCID::GetService(const JS::Value& iidval, JSContext* cx,
771 : PRUint8 optionalArgc, JS::Value* retval)
772 : {
773 89332 : if (!mDetails.IsValid())
774 0 : return NS_ERROR_XPC_BAD_CID;
775 :
776 89332 : JSObject* obj = GetWrapperObject();
777 89332 : if (!obj) {
778 0 : return NS_ERROR_UNEXPECTED;
779 : }
780 :
781 : // Do the security check if necessary
782 89332 : XPCContext* xpcc = XPCContext::GetXPCContext(cx);
783 :
784 : nsIXPCSecurityManager* sm;
785 89332 : sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_GET_SERVICE);
786 89332 : 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 89332 : const nsID* iid = GetIIDArg(optionalArgc, iidval, cx);
794 89332 : if (!iid)
795 0 : return NS_ERROR_XPC_BAD_IID;
796 :
797 178664 : nsCOMPtr<nsIServiceManager> svcMgr;
798 89332 : nsresult rv = NS_GetServiceManager(getter_AddRefs(svcMgr));
799 89332 : if (NS_FAILED(rv))
800 0 : return rv;
801 :
802 178664 : nsCOMPtr<nsISupports> srvc;
803 89332 : rv = svcMgr->GetService(mDetails.ID(), *iid, getter_AddRefs(srvc));
804 89332 : NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!");
805 89332 : if (NS_FAILED(rv) || !srvc)
806 11 : return NS_ERROR_XPC_GS_RETURNED_FAILURE;
807 :
808 : JSObject* instJSObj;
809 178642 : nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
810 89321 : rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj, srvc, *iid, getter_AddRefs(holder));
811 89321 : if (NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
812 0 : return NS_ERROR_XPC_CANT_CREATE_WN;
813 :
814 89321 : *retval = OBJECT_TO_JSVAL(instJSObj);
815 89321 : 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 157669 : xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID)
881 : {
882 157669 : JSObject *obj = nsnull;
883 :
884 : nsCOMPtr<nsIJSID> iid =
885 315338 : dont_AddRef(static_cast<nsIJSID*>(nsJSID::NewID(aID)));
886 157669 : if (iid) {
887 157669 : nsXPConnect* xpc = nsXPConnect::GetXPConnect();
888 157669 : if (xpc) {
889 315338 : nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
890 : nsresult rv = xpc->WrapNative(cx, jsobj,
891 157669 : static_cast<nsISupports*>(iid),
892 : NS_GET_IID(nsIJSID),
893 315338 : getter_AddRefs(holder));
894 157669 : if (NS_SUCCEEDED(rv) && holder) {
895 157669 : holder->GetJSObject(&obj);
896 : }
897 : }
898 : }
899 157669 : return obj;
900 : }
901 :
902 : // note: returned pointer is only valid while |obj| remains alive!
903 : const nsID*
904 297011 : xpc_JSObjectToID(JSContext *cx, JSObject* obj)
905 : {
906 297011 : if (!cx || !obj)
907 0 : return nsnull;
908 :
909 : // NOTE: this call does NOT addref
910 : XPCWrappedNative* wrapper =
911 297011 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
912 593892 : if (wrapper &&
913 296375 : (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) ||
914 253 : wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
915 253 : wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID)))) {
916 296122 : return ((nsIJSID*)wrapper->GetIdentityObject())->GetID();
917 : }
918 889 : 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 :
|