Back to index

lightning-sunbird  0.9+nobinonly
xpcjsid.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code, released
00017  * March 31, 1998.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1998
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   John Bandhauer <jband@netscape.com> (original author)
00026  *   Pierre Phaneuf <pp@ludusdesign.com>
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either of the GNU General Public License Version 2 or later (the "GPL"),
00030  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the MPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the MPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 /* An xpcom implementation of the JavaScript nsIID and nsCID objects. */
00043 
00044 #include "xpcprivate.h"
00045 
00046 /***************************************************************************/
00047 // nsJSID
00048 
00049 NS_IMPL_THREADSAFE_ISUPPORTS1(nsJSID, nsIJSID)
00050 
00051 char nsJSID::gNoString[] = "";
00052 
00053 nsJSID::nsJSID()
00054     : mID(GetInvalidIID()), mNumber(gNoString), mName(gNoString)
00055 {
00056 }
00057 
00058 nsJSID::~nsJSID()
00059 {
00060     if(mNumber && mNumber != gNoString)
00061         PR_Free(mNumber);
00062     if(mName && mName != gNoString)
00063         PR_Free(mName);
00064 }
00065 
00066 void nsJSID::Reset()
00067 {
00068     mID = GetInvalidIID();
00069 
00070     if(mNumber && mNumber != gNoString)
00071         PR_Free(mNumber);
00072     if(mName && mName != gNoString)
00073         PR_Free(mName);
00074 
00075     mNumber = mName = nsnull;
00076 }
00077 
00078 PRBool
00079 nsJSID::SetName(const char* name)
00080 {
00081     NS_ASSERTION(!mName || mName == gNoString ,"name already set");
00082     NS_ASSERTION(name,"null name");
00083     int len = strlen(name)+1;
00084     mName = (char*)PR_Malloc(len);
00085     if(!mName)
00086         return PR_FALSE;
00087     memcpy(mName, name, len);
00088     return PR_TRUE;
00089 }
00090 
00091 NS_IMETHODIMP
00092 nsJSID::GetName(char * *aName)
00093 {
00094     if(!aName)
00095         return NS_ERROR_NULL_POINTER;
00096 
00097     if(!NameIsSet())
00098         SetNameToNoString();
00099     NS_ASSERTION(mName, "name not set");
00100     *aName = (char*) nsMemory::Clone(mName, strlen(mName)+1);
00101     return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00102 }
00103 
00104 NS_IMETHODIMP
00105 nsJSID::GetNumber(char * *aNumber)
00106 {
00107     if(!aNumber)
00108         return NS_ERROR_NULL_POINTER;
00109 
00110     if(!mNumber)
00111     {
00112         if(!(mNumber = mID.ToString()))
00113             mNumber = gNoString;
00114     }
00115 
00116     *aNumber = (char*) nsMemory::Clone(mNumber, strlen(mNumber)+1);
00117     return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00118 }
00119 
00120 NS_IMETHODIMP
00121 nsJSID::GetId(nsID* *aId)
00122 {
00123     if(!aId)
00124         return NS_ERROR_NULL_POINTER;
00125 
00126     *aId = (nsID*) nsMemory::Clone(&mID, sizeof(nsID));
00127     return *aId ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00128 }
00129 
00130 NS_IMETHODIMP
00131 nsJSID::GetValid(PRBool *aValid)
00132 {
00133     if(!aValid)
00134         return NS_ERROR_NULL_POINTER;
00135 
00136     *aValid = IsValid();
00137     return NS_OK;
00138 }
00139 
00140 NS_IMETHODIMP
00141 nsJSID::Equals(nsIJSID *other, PRBool *_retval)
00142 {
00143     if(!_retval)
00144         return NS_ERROR_NULL_POINTER;
00145 
00146     *_retval = PR_FALSE;
00147 
00148     if(!other || mID.Equals(GetInvalidIID()))
00149         return NS_OK;
00150 
00151     nsID* otherID;
00152     if(NS_SUCCEEDED(other->GetId(&otherID)))
00153     {
00154         *_retval = mID.Equals(*otherID);
00155         nsMemory::Free(otherID);
00156     }
00157     return NS_OK;
00158 }
00159 
00160 NS_IMETHODIMP
00161 nsJSID::Initialize(const char *idString)
00162 {
00163     if(!idString)
00164         return NS_ERROR_NULL_POINTER;
00165 
00166     PRBool success = PR_FALSE;
00167 
00168     if(strlen(idString) && mID.Equals(GetInvalidIID()))
00169     {
00170         Reset();
00171 
00172         if(idString[0] == '{')
00173         {
00174             nsID id;
00175             if(id.Parse((char*)idString))
00176             {
00177                 mID = id;
00178                 success = PR_TRUE;
00179             }
00180         }
00181     }
00182     return success ? NS_OK : NS_ERROR_FAILURE;
00183 }
00184 
00185 PRBool
00186 nsJSID::InitWithName(const nsID& id, const char *nameString)
00187 {
00188     NS_ASSERTION(nameString, "no name");
00189     Reset();
00190     mID = id;
00191     return SetName(nameString);
00192 }
00193 
00194 // try to use the name, if no name, then use the number
00195 NS_IMETHODIMP
00196 nsJSID::ToString(char **_retval)
00197 {
00198     if(mName != gNoString)
00199     {
00200         char* str;
00201         if(NS_SUCCEEDED(GetName(&str)))
00202         {
00203             if(mName != gNoString)
00204             {
00205                 *_retval = str;
00206                 return NS_OK;
00207             }
00208             else
00209                 nsMemory::Free(str);
00210         }
00211     }
00212     return GetNumber(_retval);
00213 }
00214 
00215 const nsID&
00216 nsJSID::GetInvalidIID() const
00217 {
00218     // {BB1F47B0-D137-11d2-9841-006008962422}
00219     static nsID invalid = {0xbb1f47b0, 0xd137, 0x11d2,
00220                             {0x98, 0x41, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22}};
00221     return invalid;
00222 }
00223 
00224 //static
00225 nsJSID*
00226 nsJSID::NewID(const char* str)
00227 {
00228     if(!str)
00229     {
00230         NS_ASSERTION(0,"no string");
00231         return nsnull;
00232     }
00233 
00234     nsJSID* idObj = new nsJSID();
00235     if(idObj)
00236     {
00237         NS_ADDREF(idObj);
00238         if(NS_FAILED(idObj->Initialize(str)))
00239             NS_RELEASE(idObj);
00240     }
00241     return idObj;
00242 }
00243 
00244 /***************************************************************************/
00245 // Class object support so that we can share prototypes of wrapper
00246 
00247 // This class exists just so we can have a shared scriptable helper for
00248 // the nsJSIID class. The instances implement their own helpers. But we
00249 // needed to be able to indicate to the shared prototypes this single flag:
00250 // nsIXPCScriptable::DONT_ENUM_STATIC_PROPS. And having a class to do it is
00251 // the only means we have. Setting this flag on any given instance scriptable
00252 // helper is not sufficient to convey the information that we don't want
00253 // static properties enumerated on the shared proto.
00254 
00255 class SharedScriptableHelperForJSIID : public nsIXPCScriptable
00256 {
00257 public:
00258     NS_DECL_ISUPPORTS
00259     NS_DECL_NSIXPCSCRIPTABLE
00260     SharedScriptableHelperForJSIID() {}
00261 };
00262 
00263 NS_INTERFACE_MAP_BEGIN(SharedScriptableHelperForJSIID)
00264   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00265   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
00266 NS_INTERFACE_MAP_END_THREADSAFE
00267 
00268 NS_IMPL_THREADSAFE_ADDREF(SharedScriptableHelperForJSIID)
00269 NS_IMPL_THREADSAFE_RELEASE(SharedScriptableHelperForJSIID)
00270 
00271 // The nsIXPCScriptable map declaration that will generate stubs for us...
00272 #define XPC_MAP_CLASSNAME           SharedScriptableHelperForJSIID
00273 #define XPC_MAP_QUOTED_CLASSNAME   "JSIID"
00274 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
00275                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
00276 #include "xpc_map_end.h" /* This will #undef the above */
00277 
00278 static nsIXPCScriptable* gSharedScriptableHelperForJSIID;
00279 
00280 NS_METHOD GetSharedScriptableHelperForJSIID(PRUint32 language,
00281                                             nsISupports **helper)
00282 {
00283     if(language == nsIProgrammingLanguage::JAVASCRIPT)
00284     {
00285         NS_IF_ADDREF(gSharedScriptableHelperForJSIID);
00286         *helper = gSharedScriptableHelperForJSIID;
00287     }
00288     else
00289         *helper = nsnull;
00290     return NS_OK;
00291 }
00292 
00293 /******************************************************/
00294 
00295 static JSBool gClassObjectsWereInited = JS_FALSE;
00296 
00297 NS_DECL_CI_INTERFACE_GETTER(nsJSIID)
00298 // Can't make this static. http://bugzilla.mozilla.org/show_bug.cgi?id=81436
00299 nsIClassInfo* NS_CLASSINFO_NAME(nsJSIID);
00300 static const nsModuleComponentInfo CI_nsJSIID =
00301     {"JSIID",
00302      {0x26ecb8d0, 0x35c9, 0x11d5, { 0x90, 0xb2, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a }},
00303      nsnull, nsnull, nsnull,nsnull, nsnull,
00304      NS_CI_INTERFACE_GETTER_NAME(nsJSIID),
00305      GetSharedScriptableHelperForJSIID,
00306      &NS_CLASSINFO_NAME(nsJSIID), 0};
00307 
00308 NS_DECL_CI_INTERFACE_GETTER(nsJSCID)
00309 // Can't make this static. http://bugzilla.mozilla.org/show_bug.cgi?id=81436
00310 nsIClassInfo* NS_CLASSINFO_NAME(nsJSCID);
00311 static const nsModuleComponentInfo CI_nsJSCID =
00312     {"JSCID",
00313      {0x9255b5b0, 0x35cf, 0x11d5, { 0x90, 0xb2, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a }},
00314      nsnull, nsnull, nsnull,nsnull, nsnull,
00315      NS_CI_INTERFACE_GETTER_NAME(nsJSCID), nsnull,
00316      &NS_CLASSINFO_NAME(nsJSCID), 0};
00317 
00318 JSBool xpc_InitJSxIDClassObjects()
00319 {
00320     if(gClassObjectsWereInited)
00321         return JS_TRUE;
00322 
00323     nsresult rv = NS_OK;
00324 
00325     if(!NS_CLASSINFO_NAME(nsJSIID))
00326     {
00327         nsCOMPtr<nsIGenericFactory> factory;
00328         rv = NS_NewGenericFactory(getter_AddRefs(factory), &CI_nsJSIID);
00329         if(NS_FAILED(rv))
00330             goto return_failure;
00331         rv = factory->QueryInterface(NS_GET_IID(nsIClassInfo),
00332                                      (void**)&NS_CLASSINFO_NAME(nsJSIID));
00333         if(NS_FAILED(rv))
00334             goto return_failure;
00335     }
00336 
00337     if(!NS_CLASSINFO_NAME(nsJSCID))
00338     {
00339         nsCOMPtr<nsIGenericFactory> factory;
00340         rv = NS_NewGenericFactory(getter_AddRefs(factory), &CI_nsJSCID);
00341         if(NS_FAILED(rv))
00342             goto return_failure;
00343         rv = factory->QueryInterface(NS_GET_IID(nsIClassInfo),
00344                                      (void**)&NS_CLASSINFO_NAME(nsJSCID));
00345         if(NS_FAILED(rv))
00346             goto return_failure;
00347     }
00348 
00349     gSharedScriptableHelperForJSIID = new SharedScriptableHelperForJSIID();
00350     if(!gSharedScriptableHelperForJSIID)
00351         goto return_failure;
00352     NS_ADDREF(gSharedScriptableHelperForJSIID);
00353 
00354     gClassObjectsWereInited = JS_TRUE;
00355     return JS_TRUE;
00356 return_failure:
00357     return JS_FALSE;
00358 }
00359 
00360 void xpc_DestroyJSxIDClassObjects()
00361 {
00362     NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSIID));
00363     NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSCID));
00364     NS_IF_RELEASE(gSharedScriptableHelperForJSIID);
00365 
00366     gClassObjectsWereInited = JS_FALSE;
00367 }
00368 
00369 /***************************************************************************/
00370 
00371 NS_INTERFACE_MAP_BEGIN(nsJSIID)
00372   NS_INTERFACE_MAP_ENTRY(nsIJSID)
00373   NS_INTERFACE_MAP_ENTRY(nsIJSIID)
00374   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00375 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00376   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
00377 #endif
00378   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
00379   NS_IMPL_QUERY_CLASSINFO(nsJSIID)
00380 NS_INTERFACE_MAP_END_THREADSAFE
00381 
00382 NS_IMPL_THREADSAFE_ADDREF(nsJSIID)
00383 NS_IMPL_THREADSAFE_RELEASE(nsJSIID)
00384 NS_IMPL_CI_INTERFACE_GETTER2(nsJSIID, nsIJSID, nsIJSIID)
00385 
00386 // The nsIXPCScriptable map declaration that will generate stubs for us...
00387 #define XPC_MAP_CLASSNAME           nsJSIID
00388 #define XPC_MAP_QUOTED_CLASSNAME   "nsJSIID"
00389 #define                             XPC_MAP_WANT_NEWRESOLVE
00390 #define                             XPC_MAP_WANT_ENUMERATE
00391 #define                             XPC_MAP_WANT_HASINSTANCE
00392 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
00393                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
00394 #include "xpc_map_end.h" /* This will #undef the above */
00395 
00396 
00397 nsJSIID::nsJSIID(nsIInterfaceInfo* aInfo)
00398     : mInfo(aInfo)
00399 {
00400 }
00401 
00402 nsJSIID::~nsJSIID() {}
00403 
00404 // If mInfo is present we use it and ignore mDetails, else we use mDetails.
00405 
00406 NS_IMETHODIMP nsJSIID::GetName(char * *aName)
00407 {
00408     return mInfo->GetName(aName);    
00409 }
00410 
00411 NS_IMETHODIMP nsJSIID::GetNumber(char * *aNumber)
00412 {
00413     const nsIID* id;
00414     mInfo->GetIIDShared(&id);
00415     char* str = id->ToString();
00416     if(!str)
00417         return NS_ERROR_OUT_OF_MEMORY;
00418     *aNumber = (char*) nsMemory::Clone(str, strlen(str)+1);
00419     PR_Free(str);
00420     return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00421 }        
00422 
00423 NS_IMETHODIMP nsJSIID::GetId(nsID* *aId)
00424 {
00425     return mInfo->GetInterfaceIID((nsIID**)aId);
00426 }
00427 
00428 NS_IMETHODIMP nsJSIID::GetValid(PRBool *aValid)
00429 {
00430     *aValid = PR_TRUE;
00431     return NS_OK;
00432 }
00433 
00434 NS_IMETHODIMP nsJSIID::Equals(nsIJSID *other, PRBool *_retval)
00435 {
00436     if(!_retval)
00437         return NS_ERROR_NULL_POINTER;
00438 
00439     *_retval = PR_FALSE;
00440 
00441     if(!other)
00442         return NS_OK;
00443 
00444     nsID* otherID;
00445     if(NS_SUCCEEDED(other->GetId(&otherID)))
00446     {
00447         mInfo->IsIID((nsIID*)otherID, _retval);
00448         nsMemory::Free(otherID);
00449     }
00450     return NS_OK;
00451 }
00452 
00453 NS_IMETHODIMP nsJSIID::Initialize(const char *idString)
00454 {
00455     return NS_ERROR_FAILURE;
00456 }
00457 
00458 NS_IMETHODIMP nsJSIID::ToString(char **_retval)
00459 {
00460     return mInfo->GetName(_retval);    
00461 }
00462 
00463 // static 
00464 nsJSIID* 
00465 nsJSIID::NewID(nsIInterfaceInfo* aInfo)
00466 {
00467     if(!aInfo)
00468     {
00469         NS_ERROR("no info");
00470         return nsnull;
00471     }
00472 
00473     PRBool canScript;
00474     if(NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)
00475         return nsnull;
00476 
00477     nsJSIID* idObj = new nsJSIID(aInfo);
00478     NS_IF_ADDREF(idObj);
00479     return idObj;
00480 }
00481 
00482 
00483 /* PRBool resolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id); */
00484 NS_IMETHODIMP
00485 nsJSIID::NewResolve(nsIXPConnectWrappedNative *wrapper,
00486                     JSContext * cx, JSObject * obj,
00487                     jsval id, PRUint32 flags,
00488                     JSObject * *objp, PRBool *_retval)
00489 {
00490     XPCCallContext ccx(JS_CALLER, cx);
00491 
00492     AutoMarkingNativeInterfacePtr iface(ccx);
00493 
00494     const nsIID* iid;
00495     mInfo->GetIIDShared(&iid);
00496 
00497     iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
00498 
00499     if(!iface)
00500         return NS_OK;
00501 
00502     XPCNativeMember* member = iface->FindMember(id);
00503     if(member && member->IsConstant())
00504     {
00505         jsval val;
00506         if(!member->GetValue(ccx, iface, &val))
00507             return NS_ERROR_OUT_OF_MEMORY;
00508 
00509         jsid idid;
00510         if(!JS_ValueToId(cx, id, &idid))
00511             return NS_ERROR_OUT_OF_MEMORY;
00512 
00513         *objp = obj;
00514         *_retval = OBJ_DEFINE_PROPERTY(cx, obj, idid, val,
00515                                        nsnull, nsnull,
00516                                        JSPROP_ENUMERATE |
00517                                        JSPROP_READONLY |
00518                                        JSPROP_PERMANENT,
00519                                        nsnull);
00520     }
00521 
00522     return NS_OK;
00523 }
00524 
00525 /* PRBool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */
00526 NS_IMETHODIMP
00527 nsJSIID::Enumerate(nsIXPConnectWrappedNative *wrapper,
00528                    JSContext * cx, JSObject * obj, PRBool *_retval)
00529 {
00530     // In this case, let's just eagerly resolve...
00531 
00532     XPCCallContext ccx(JS_CALLER, cx);
00533 
00534     AutoMarkingNativeInterfacePtr iface(ccx);
00535 
00536     const nsIID* iid;
00537     mInfo->GetIIDShared(&iid);
00538 
00539     iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
00540 
00541     if(!iface)
00542         return NS_OK;
00543 
00544     PRUint16 count = iface->GetMemberCount();
00545     for(PRUint16 i = 0; i < count; i++)
00546     {
00547         XPCNativeMember* member = iface->GetMemberAt(i);
00548         if(member && member->IsConstant() &&
00549            !xpc_ForcePropertyResolve(cx, obj, member->GetName()))
00550         {
00551             return NS_ERROR_UNEXPECTED;
00552         }
00553     }
00554     return NS_OK;
00555 }
00556 
00557 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
00558 NS_IMETHODIMP
00559 nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
00560                      JSContext * cx, JSObject * obj,
00561                      jsval val, PRBool *bp, PRBool *_retval)
00562 {
00563     *bp = JS_FALSE;
00564     nsresult rv = NS_OK;
00565 
00566     if(!JSVAL_IS_PRIMITIVE(val))
00567     {
00568         // we have a JSObject
00569         JSObject* obj = JSVAL_TO_OBJECT(val);
00570 
00571         NS_ASSERTION(obj, "when is an object not an object?");
00572 
00573         // is this really a native xpcom object with a wrapper?
00574         XPCWrappedNative* other_wrapper =
00575            XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
00576 
00577         if(!other_wrapper)
00578             return NS_OK;
00579 
00580         const nsIID* iid;
00581         mInfo->GetIIDShared(&iid);
00582 
00583         // We'll trust the interface set of the wrapper if this is known
00584         // to be an interface that the objects *expects* to be able to
00585         // handle.
00586         if(other_wrapper->HasInterfaceNoQI(*iid))
00587         {
00588             *bp = JS_TRUE;
00589             return NS_OK;
00590         }
00591 
00592         // Otherwise, we'll end up Querying the native object to be sure.
00593         XPCCallContext ccx(JS_CALLER, cx);
00594 
00595         AutoMarkingNativeInterfacePtr iface(ccx);
00596         iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
00597 
00598         if(iface && other_wrapper->FindTearOff(ccx, iface))
00599             *bp = JS_TRUE;
00600     }
00601     return rv;
00602 }
00603 
00604 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00605 /* string canCreateWrapper (in nsIIDPtr iid); */
00606 NS_IMETHODIMP
00607 nsJSIID::CanCreateWrapper(const nsIID * iid, char **_retval)
00608 {
00609     // We let anyone do this...
00610     *_retval = xpc_CloneAllAccess();
00611     return NS_OK;
00612 }
00613 
00614 /* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
00615 NS_IMETHODIMP
00616 nsJSIID::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
00617 {
00618     static const char* allowed[] = {"equals", "toString", nsnull};
00619 
00620     *_retval = xpc_CheckAccessList(methodName, allowed);
00621     return NS_OK;
00622 }
00623 
00624 /* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
00625 NS_IMETHODIMP
00626 nsJSIID::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
00627 {
00628     static const char* allowed[] = {"name", "number", "valid", nsnull};
00629     *_retval = xpc_CheckAccessList(propertyName, allowed);
00630     return NS_OK;
00631 }
00632 
00633 /* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
00634 NS_IMETHODIMP
00635 nsJSIID::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
00636 {
00637     // If you have to ask, then the answer is NO
00638     *_retval = nsnull;
00639     return NS_OK;
00640 }
00641 #endif
00642 
00643 /***************************************************************************/
00644 
00645 NS_INTERFACE_MAP_BEGIN(nsJSCID)
00646   NS_INTERFACE_MAP_ENTRY(nsIJSID)
00647   NS_INTERFACE_MAP_ENTRY(nsIJSCID)
00648   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00649   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
00650   NS_IMPL_QUERY_CLASSINFO(nsJSCID)
00651 NS_INTERFACE_MAP_END_THREADSAFE
00652 
00653 NS_IMPL_THREADSAFE_ADDREF(nsJSCID)
00654 NS_IMPL_THREADSAFE_RELEASE(nsJSCID)
00655 NS_IMPL_CI_INTERFACE_GETTER2(nsJSCID, nsIJSID, nsIJSCID)
00656 
00657 // The nsIXPCScriptable map declaration that will generate stubs for us...
00658 #define XPC_MAP_CLASSNAME           nsJSCID
00659 #define XPC_MAP_QUOTED_CLASSNAME   "nsJSCID"
00660 #define                             XPC_MAP_WANT_CONSTRUCT
00661 #define                             XPC_MAP_WANT_HASINSTANCE
00662 #define XPC_MAP_FLAGS               0
00663 #include "xpc_map_end.h" /* This will #undef the above */
00664 
00665 nsJSCID::nsJSCID()  {}
00666 nsJSCID::~nsJSCID() {}
00667 
00668 NS_IMETHODIMP nsJSCID::GetName(char * *aName)
00669     {ResolveName(); return mDetails.GetName(aName);}
00670 
00671 NS_IMETHODIMP nsJSCID::GetNumber(char * *aNumber)
00672     {return mDetails.GetNumber(aNumber);}
00673 
00674 NS_IMETHODIMP nsJSCID::GetId(nsID* *aId)
00675     {return mDetails.GetId(aId);}
00676 
00677 NS_IMETHODIMP nsJSCID::GetValid(PRBool *aValid)
00678     {return mDetails.GetValid(aValid);}
00679 
00680 NS_IMETHODIMP nsJSCID::Equals(nsIJSID *other, PRBool *_retval)
00681     {return mDetails.Equals(other, _retval);}
00682 
00683 NS_IMETHODIMP nsJSCID::Initialize(const char *idString)
00684     {return mDetails.Initialize(idString);}
00685 
00686 NS_IMETHODIMP nsJSCID::ToString(char **_retval)
00687     {ResolveName(); return mDetails.ToString(_retval);}
00688 
00689 void
00690 nsJSCID::ResolveName()
00691 {
00692     if(!mDetails.NameIsSet())
00693         mDetails.SetNameToNoString();
00694 }
00695 
00696 //static
00697 nsJSCID*
00698 nsJSCID::NewID(const char* str)
00699 {
00700     if(!str)
00701     {
00702         NS_ASSERTION(0,"no string");
00703         return nsnull;
00704     }
00705 
00706     nsJSCID* idObj = new nsJSCID();
00707     if(idObj)
00708     {
00709         PRBool success = PR_FALSE;
00710         NS_ADDREF(idObj);
00711 
00712         if(str[0] == '{')
00713         {
00714             if(NS_SUCCEEDED(idObj->Initialize(str)))
00715                 success = PR_TRUE;
00716         }
00717         else
00718         {
00719             nsCOMPtr<nsIComponentRegistrar> registrar;
00720             NS_GetComponentRegistrar(getter_AddRefs(registrar));
00721             if (registrar)
00722             {
00723                 nsCID *cid;
00724                 if(NS_SUCCEEDED(registrar->ContractIDToCID(str, &cid)))
00725                 {
00726                     success = idObj->mDetails.InitWithName(*cid, str);
00727                     nsMemory::Free(cid);
00728                 }
00729             }
00730         }
00731         if(!success)
00732             NS_RELEASE(idObj);
00733     }
00734     return idObj;
00735 }
00736 
00737 
00738 /* nsISupports createInstance (); */
00739 NS_IMETHODIMP
00740 nsJSCID::CreateInstance(nsISupports **_retval)
00741 {
00742     if(!mDetails.IsValid())
00743         return NS_ERROR_XPC_BAD_CID;
00744 
00745     nsXPConnect* xpc = nsXPConnect::GetXPConnect();
00746     if(!xpc)
00747         return NS_ERROR_UNEXPECTED;
00748 
00749     nsCOMPtr<nsIXPCNativeCallContext> ccxp;
00750     xpc->GetCurrentNativeCallContext(getter_AddRefs(ccxp));
00751     if(!ccxp)
00752         return NS_ERROR_UNEXPECTED;
00753 
00754     PRUint32 argc;
00755     jsval * argv;
00756     jsval * vp;
00757     JSContext* cx;
00758     JSObject* obj;
00759 
00760     ccxp->GetJSContext(&cx);
00761     ccxp->GetArgc(&argc);
00762     ccxp->GetArgvPtr(&argv);
00763     ccxp->GetRetValPtr(&vp);
00764 
00765     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
00766     ccxp->GetCalleeWrapper(getter_AddRefs(wrapper));
00767     wrapper->GetJSObject(&obj);
00768 
00769     // Do the security check if necessary
00770 
00771     XPCContext* xpcc = nsXPConnect::GetContext(cx);
00772 
00773     nsIXPCSecurityManager* sm;
00774     sm = xpcc->GetAppropriateSecurityManager(
00775                         nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
00776     if(sm && NS_FAILED(sm->CanCreateInstance(cx, *mDetails.GetID())))
00777     {
00778         // the security manager vetoed. It should have set an exception.
00779         ccxp->SetExceptionWasThrown(JS_TRUE);
00780         return NS_OK;
00781     }
00782 
00783     nsID iid;
00784 
00785     // If an IID was passed in then use it
00786     if(argc)
00787     {
00788         JSObject* iidobj;
00789         jsval val = *argv;
00790         nsID* piid = nsnull;
00791         if(JSVAL_IS_PRIMITIVE(val) ||
00792            !(iidobj = JSVAL_TO_OBJECT(val)) ||
00793            !(piid = xpc_JSObjectToID(cx, iidobj)))
00794         {
00795             return NS_ERROR_XPC_BAD_IID;
00796         }
00797         iid = *piid;
00798         nsMemory::Free(piid);
00799     }
00800     else
00801         iid = NS_GET_IID(nsISupports);
00802 
00803     nsCOMPtr<nsIComponentManager> compMgr;
00804     nsresult rv = NS_GetComponentManager(getter_AddRefs(compMgr));
00805     if (NS_FAILED(rv))
00806         return NS_ERROR_UNEXPECTED;
00807 
00808     nsCOMPtr<nsISupports> inst;
00809     rv = compMgr->CreateInstance(*mDetails.GetID(), nsnull, iid, getter_AddRefs(inst));
00810     NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!");
00811 
00812     if(NS_FAILED(rv) || !inst)
00813         return NS_ERROR_XPC_CI_RETURNED_FAILURE;
00814 
00815     JSObject* instJSObj;
00816     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00817     rv = xpc->WrapNative(cx, obj, inst, iid, getter_AddRefs(holder));
00818     if(NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
00819         return NS_ERROR_XPC_CANT_CREATE_WN;
00820 
00821     *vp = OBJECT_TO_JSVAL(instJSObj);
00822     ccxp->SetReturnValueWasSet(JS_TRUE);
00823     return NS_OK;
00824 }
00825 
00826 /* nsISupports getService (); */
00827 NS_IMETHODIMP
00828 nsJSCID::GetService(nsISupports **_retval)
00829 {
00830     if(!mDetails.IsValid())
00831         return NS_ERROR_XPC_BAD_CID;
00832 
00833     nsXPConnect* xpc = nsXPConnect::GetXPConnect();
00834     if(!xpc)
00835         return NS_ERROR_UNEXPECTED;
00836 
00837     nsCOMPtr<nsIXPCNativeCallContext> ccxp;
00838     xpc->GetCurrentNativeCallContext(getter_AddRefs(ccxp));
00839     if(!ccxp)
00840         return NS_ERROR_UNEXPECTED;
00841 
00842     PRUint32 argc;
00843     jsval * argv;
00844     jsval * vp;
00845     JSContext* cx;
00846     JSObject* obj;
00847 
00848     ccxp->GetJSContext(&cx);
00849     ccxp->GetArgc(&argc);
00850     ccxp->GetArgvPtr(&argv);
00851     ccxp->GetRetValPtr(&vp);
00852 
00853     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
00854     ccxp->GetCalleeWrapper(getter_AddRefs(wrapper));
00855     wrapper->GetJSObject(&obj);
00856 
00857     // Do the security check if necessary
00858 
00859     XPCContext* xpcc = nsXPConnect::GetContext(cx);
00860 
00861     nsIXPCSecurityManager* sm;
00862     sm = xpcc->GetAppropriateSecurityManager(
00863                         nsIXPCSecurityManager::HOOK_GET_SERVICE);
00864     if(sm && NS_FAILED(sm->CanCreateInstance(cx, *mDetails.GetID())))
00865     {
00866         // the security manager vetoed. It should have set an exception.
00867         ccxp->SetExceptionWasThrown(JS_TRUE);
00868         return NS_OK;
00869     }
00870 
00871     nsID iid;
00872 
00873     // If an IID was passed in then use it
00874     if(argc)
00875     {
00876         JSObject* iidobj;
00877         jsval val = *argv;
00878         nsID* piid = nsnull;
00879         if(JSVAL_IS_PRIMITIVE(val) ||
00880            !(iidobj = JSVAL_TO_OBJECT(val)) ||
00881            !(piid = xpc_JSObjectToID(cx, iidobj)))
00882         {
00883             return NS_ERROR_XPC_BAD_IID;
00884         }
00885         iid = *piid;
00886         nsMemory::Free(piid);
00887     }
00888     else
00889         iid = NS_GET_IID(nsISupports);
00890 
00891     nsCOMPtr<nsIServiceManager> svcMgr;
00892     nsresult rv = NS_GetServiceManager(getter_AddRefs(svcMgr));
00893     if (NS_FAILED(rv))
00894         return rv;
00895 
00896     nsCOMPtr<nsISupports> srvc;
00897     rv = svcMgr->GetService(*mDetails.GetID(), iid, getter_AddRefs(srvc));
00898     NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!");
00899     if(NS_FAILED(rv) || !srvc)
00900         return NS_ERROR_XPC_GS_RETURNED_FAILURE;
00901 
00902     JSObject* instJSObj;
00903     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00904     rv = xpc->WrapNative(cx, obj, srvc, iid, getter_AddRefs(holder));
00905     if(NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
00906         return NS_ERROR_XPC_CANT_CREATE_WN;
00907 
00908     *vp = OBJECT_TO_JSVAL(instJSObj);
00909     ccxp->SetReturnValueWasSet(JS_TRUE);
00910     return NS_OK;
00911 }
00912 
00913 /* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
00914 NS_IMETHODIMP
00915 nsJSCID::Construct(nsIXPConnectWrappedNative *wrapper,
00916                    JSContext * cx, JSObject * obj,
00917                    PRUint32 argc, jsval * argv, jsval * vp,
00918                    PRBool *_retval)
00919 {
00920     XPCJSRuntime* rt = nsXPConnect::GetRuntime();
00921     if(!rt)
00922         return NS_ERROR_FAILURE;
00923 
00924     // 'push' a call context and call on it
00925     XPCCallContext ccx(JS_CALLER, cx, obj, nsnull,
00926                        rt->GetStringJSVal(XPCJSRuntime::IDX_CREATE_INSTANCE),
00927                        argc, argv, vp);
00928 
00929     *_retval = XPCWrappedNative::CallMethod(ccx);
00930     return NS_OK;
00931 }
00932 
00933 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
00934 NS_IMETHODIMP
00935 nsJSCID::HasInstance(nsIXPConnectWrappedNative *wrapper,
00936                      JSContext * cx, JSObject * obj,
00937                      jsval val, PRBool *bp, PRBool *_retval)
00938 {
00939     *bp = JS_FALSE;
00940     nsresult rv = NS_OK;
00941 
00942     if(!JSVAL_IS_PRIMITIVE(val))
00943     {
00944         // we have a JSObject
00945         JSObject* obj = JSVAL_TO_OBJECT(val);
00946 
00947         NS_ASSERTION(obj, "when is an object not an object?");
00948 
00949         // is this really a native xpcom object with a wrapper?
00950         XPCWrappedNative* other_wrapper =
00951            XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
00952 
00953         if(!other_wrapper)
00954             return NS_OK;
00955 
00956         // We consider CID equality to be the thing that matters here.
00957         // This is perhaps debatable.
00958         nsIClassInfo* ci = other_wrapper->GetClassInfo();
00959         if(ci)
00960         {
00961             nsID cid;
00962             if(NS_SUCCEEDED(ci->GetClassIDNoAlloc(&cid)))
00963                 *bp = cid.Equals(*mDetails.GetID());
00964         }
00965     }
00966     return rv;
00967 }
00968 
00969 /***************************************************************************/
00970 // additional utilities...
00971 
00972 JSObject *
00973 xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID)
00974 {
00975     JSObject *obj = nsnull;
00976 
00977     char* idString = aID.ToString();
00978     if(idString)
00979     {
00980         nsCOMPtr<nsIJSID> iid =
00981             dont_AddRef(NS_STATIC_CAST(nsIJSID*, nsJSID::NewID(idString)));
00982         PR_Free(idString);
00983         if(iid)
00984         {
00985             nsXPConnect* xpc = nsXPConnect::GetXPConnect();
00986             if(xpc)
00987             {
00988                 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00989                 nsresult rv = xpc->WrapNative(cx, jsobj,
00990                                               NS_STATIC_CAST(nsISupports*,iid),
00991                                               NS_GET_IID(nsIJSID),
00992                                               getter_AddRefs(holder));
00993                 if(NS_SUCCEEDED(rv) && holder)
00994                 {
00995                     holder->GetJSObject(&obj);
00996                 }
00997             }
00998         }
00999     }
01000     return obj;
01001 }
01002 
01003 nsID*
01004 xpc_JSObjectToID(JSContext *cx, JSObject* obj)
01005 {
01006     nsID* id = nsnull;
01007     if(!cx || !obj)
01008         return nsnull;
01009 
01010     // NOTE: this call does NOT addref
01011     XPCWrappedNative* wrapper =
01012         XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
01013     if(wrapper &&
01014        (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID))  ||
01015         wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
01016         wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID))))
01017     {
01018         ((nsIJSID*)wrapper->GetIdentityObject())->GetId(&id);
01019     }
01020     return id;
01021 }
01022 
01023 JSBool
01024 xpc_JSObjectIsID(JSContext *cx, JSObject* obj)
01025 {
01026     NS_ASSERTION(cx && obj, "bad param");
01027     // NOTE: this call does NOT addref
01028     XPCWrappedNative* wrapper =
01029         XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
01030     return wrapper &&
01031            (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID))  ||
01032             wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
01033             wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID)));
01034 }
01035 
01036