Back to index

lightning-sunbird  0.9+nobinonly
xpccomponents.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * vim: set ts=8 sw=4 et tw=78:
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is Mozilla Communicator client code, released
00018  * March 31, 1998.
00019  *
00020  * The Initial Developer of the Original Code is
00021  * Netscape Communications Corporation.
00022  * Portions created by the Initial Developer are Copyright (C) 1998
00023  * the Initial Developer. All Rights Reserved.
00024  *
00025  * Contributor(s):
00026  *   John Bandhauer <jband@netscape.com> (original author)
00027  *   Pierre Phaneuf <pp@ludusdesign.com>
00028  *
00029  * Alternatively, the contents of this file may be used under the terms of
00030  * either of the GNU General Public License Version 2 or later (the "GPL"),
00031  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00032  * in which case the provisions of the GPL or the LGPL are applicable instead
00033  * of those above. If you wish to allow use of your version of this file only
00034  * under the terms of either the GPL or the LGPL, and not to allow others to
00035  * use your version of this file under the terms of the MPL, indicate your
00036  * decision by deleting the provisions above and replace them with the notice
00037  * and other provisions required by the GPL or the LGPL. If you do not delete
00038  * the provisions above, a recipient may use your version of this file under
00039  * the terms of any one of the MPL, the GPL or the LGPL.
00040  *
00041  * ***** END LICENSE BLOCK ***** */
00042 
00043 /* The "Components" xpcom objects for JavaScript. */
00044 
00045 #include "xpcprivate.h"
00046 #include "nsReadableUtils.h"
00047 #include "nsIScriptObjectPrincipal.h"
00048 #include "nsIDOMWindow.h"
00049 
00050 /***************************************************************************/
00051 // stuff used by all
00052 
00053 static nsresult ThrowAndFail(uintN errNum, JSContext* cx, JSBool* retval)
00054 {
00055     XPCThrower::Throw(errNum, cx);
00056     *retval = JS_FALSE;
00057     return NS_OK;
00058 }
00059 
00060 static JSBool
00061 JSValIsInterfaceOfType(JSContext *cx, jsval v, REFNSIID iid)
00062 {
00063     nsCOMPtr<nsIXPConnect> xpc;
00064     nsCOMPtr<nsIXPConnectWrappedNative> wn;
00065     nsCOMPtr<nsISupports> sup;
00066     nsISupports* iface;
00067     if(!JSVAL_IS_PRIMITIVE(v) &&
00068        nsnull != (xpc = nsXPConnect::GetXPConnect()) &&
00069        NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(v),
00070                             getter_AddRefs(wn))) && wn &&
00071        NS_SUCCEEDED(wn->Native()->QueryInterface(iid, (void**)&iface)) && iface)
00072     {
00073         NS_RELEASE(iface);
00074         return JS_TRUE;
00075     }
00076     return JS_FALSE;
00077 }
00078 
00079 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00080 char* xpc_CloneAllAccess()
00081 {
00082     static const char allAccess[] = "AllAccess";
00083     return (char*)nsMemory::Clone(allAccess, sizeof(allAccess));
00084 }
00085 
00086 char * xpc_CheckAccessList(const PRUnichar* wideName, const char* list[])
00087 {
00088     nsCAutoString asciiName;
00089     CopyUTF16toUTF8(nsDependentString(wideName), asciiName);
00090 
00091     for(const char** p = list; *p; p++)
00092         if(!strcmp(*p, asciiName.get()))
00093             return xpc_CloneAllAccess();
00094 
00095     return nsnull;
00096 }
00097 #endif
00098 
00099 /***************************************************************************/
00100 
00101 nsXPCComponents_Interfaces::nsXPCComponents_Interfaces()
00102 {
00103     mManager = dont_AddRef(XPTI_GetInterfaceInfoManager());
00104 }
00105 
00106 nsXPCComponents_Interfaces::~nsXPCComponents_Interfaces()
00107 {
00108     // empty
00109 }
00110 
00111 
00112 /* [noscript] attribute nsIInterfaceInfoManager manager; */
00113 NS_IMETHODIMP nsXPCComponents_Interfaces::GetManager(nsIInterfaceInfoManager * *aManager)
00114 {
00115     *aManager = mManager;
00116     NS_IF_ADDREF(*aManager);
00117     return NS_OK;
00118 }
00119 NS_IMETHODIMP nsXPCComponents_Interfaces::SetManager(nsIInterfaceInfoManager * aManager)
00120 {
00121     mManager = aManager;
00122     return NS_OK;
00123 }
00124 
00125 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces)
00126   NS_INTERFACE_MAP_ENTRY(nsIScriptableInterfaces)
00127   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00128 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00129   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
00130 #endif
00131   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptableInterfaces)
00132 NS_INTERFACE_MAP_END_THREADSAFE
00133 
00134 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Interfaces)
00135 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Interfaces)
00136 
00137 // The nsIXPCScriptable map declaration that will generate stubs for us...
00138 #define XPC_MAP_CLASSNAME           nsXPCComponents_Interfaces
00139 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Interfaces"
00140 #define                             XPC_MAP_WANT_NEWRESOLVE
00141 #define                             XPC_MAP_WANT_NEWENUMERATE
00142 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
00143                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
00144 #include "xpc_map_end.h" /* This will #undef the above */
00145 
00146 
00147 /* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */
00148 NS_IMETHODIMP
00149 nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
00150                                          JSContext * cx, JSObject * obj,
00151                                          PRUint32 enum_op, jsval * statep,
00152                                          jsid * idp, PRBool *_retval)
00153 {
00154     nsIEnumerator* e;
00155 
00156     switch(enum_op)
00157     {
00158         case JSENUMERATE_INIT:
00159         {
00160             if(!mManager ||
00161                NS_FAILED(mManager->EnumerateInterfaces(&e)) || !e ||
00162                NS_FAILED(e->First()))
00163 
00164             {
00165                 *statep = JSVAL_NULL;
00166                 return NS_ERROR_UNEXPECTED;
00167             }
00168 
00169             *statep = PRIVATE_TO_JSVAL(e);
00170             if(idp)
00171                 *idp = JSVAL_ZERO; // indicate that we don't know the count
00172             return NS_OK;
00173         }
00174         case JSENUMERATE_NEXT:
00175         {
00176             nsCOMPtr<nsISupports> isup;
00177 
00178             e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
00179 
00180             while(1)
00181             {
00182                 if(NS_ENUMERATOR_FALSE == e->IsDone() &&
00183                    NS_SUCCEEDED(e->CurrentItem(getter_AddRefs(isup))) && isup)
00184                 {
00185                     e->Next();
00186                     nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(isup));
00187                     if(iface)
00188                     {
00189                         JSString* idstr;
00190                         const char* name;
00191                         PRBool scriptable;
00192 
00193                         if(NS_SUCCEEDED(iface->IsScriptable(&scriptable)) &&
00194                            !scriptable)
00195                         {
00196                             continue;
00197                         }
00198 
00199                         if(NS_SUCCEEDED(iface->GetNameShared(&name)) && name &&
00200                            nsnull != (idstr = JS_NewStringCopyZ(cx, name)) &&
00201                            JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp))
00202                         {
00203                             return NS_OK;
00204                         }
00205                     }
00206                 }
00207                 // else...
00208                 break;
00209             }
00210             // FALL THROUGH
00211         }
00212 
00213         case JSENUMERATE_DESTROY:
00214         default:
00215             e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
00216             NS_IF_RELEASE(e);
00217             *statep = JSVAL_NULL;
00218             return NS_OK;
00219     }
00220 }
00221 
00222 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
00223 NS_IMETHODIMP
00224 nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper,
00225                                        JSContext * cx, JSObject * obj,
00226                                        jsval id, PRUint32 flags,
00227                                        JSObject * *objp, PRBool *_retval)
00228 {
00229     const char* name = nsnull;
00230 
00231     if(mManager &&
00232        JSVAL_IS_STRING(id) &&
00233        nsnull != (name = JS_GetStringBytes(JSVAL_TO_STRING(id))) &&
00234        name[0] != '{') // we only allow interfaces by name here
00235     {
00236         nsCOMPtr<nsIInterfaceInfo> info;
00237         mManager->GetInfoForName(name, getter_AddRefs(info));
00238         if(!info)
00239             return NS_OK;
00240 
00241         nsCOMPtr<nsIJSIID> nsid =
00242             dont_AddRef(NS_STATIC_CAST(nsIJSIID*, nsJSIID::NewID(info)));
00243 
00244         if(nsid)
00245         {
00246             nsCOMPtr<nsIXPConnect> xpc;
00247             wrapper->GetXPConnect(getter_AddRefs(xpc));
00248             if(xpc)
00249             {
00250                 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00251                 if(NS_SUCCEEDED(xpc->WrapNative(cx, obj,
00252                                                 NS_STATIC_CAST(nsIJSIID*,nsid),
00253                                                 NS_GET_IID(nsIJSIID),
00254                                                 getter_AddRefs(holder))))
00255                 {
00256                     JSObject* idobj;
00257                     if(holder && NS_SUCCEEDED(holder->GetJSObject(&idobj)))
00258                     {
00259                         jsid idid;
00260 
00261                         *objp = obj;
00262                         *_retval = JS_ValueToId(cx, id, &idid) &&
00263                                    OBJ_DEFINE_PROPERTY(cx, obj, idid,
00264                                                        OBJECT_TO_JSVAL(idobj),
00265                                                        nsnull, nsnull,
00266                                                        JSPROP_ENUMERATE |
00267                                                        JSPROP_READONLY |
00268                                                        JSPROP_PERMANENT,
00269                                                        nsnull);
00270                     }
00271                 }
00272             }
00273         }
00274     }
00275     return NS_OK;
00276 }
00277 
00278 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00279 /* string canCreateWrapper (in nsIIDPtr iid); */
00280 NS_IMETHODIMP
00281 nsXPCComponents_Interfaces::CanCreateWrapper(const nsIID * iid, char **_retval)
00282 {
00283     // We let anyone do this...
00284     *_retval = xpc_CloneAllAccess();
00285     return NS_OK;
00286 }
00287 
00288 /* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
00289 NS_IMETHODIMP
00290 nsXPCComponents_Interfaces::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
00291 {
00292     // If you have to ask, then the answer is NO
00293     *_retval = nsnull;
00294     return NS_OK;
00295 }
00296 
00297 /* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
00298 NS_IMETHODIMP
00299 nsXPCComponents_Interfaces::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
00300 {
00301     // If you have to ask, then the answer is NO
00302     *_retval = nsnull;
00303     return NS_OK;
00304 }
00305 
00306 /* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
00307 NS_IMETHODIMP
00308 nsXPCComponents_Interfaces::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
00309 {
00310     // If you have to ask, then the answer is NO
00311     *_retval = nsnull;
00312     return NS_OK;
00313 }
00314 #endif
00315 
00316 /***************************************************************************/
00317 /***************************************************************************/
00318 /***************************************************************************/
00319 
00320 class nsXPCComponents_InterfacesByID :
00321             public nsIScriptableInterfacesByID,
00322             public nsIXPCScriptable
00323 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00324           , public nsISecurityCheckedComponent
00325 #endif
00326 {
00327 public:
00328     // all the interface method declarations...
00329     NS_DECL_ISUPPORTS
00330     NS_DECL_NSISCRIPTABLEINTERFACESBYID
00331     NS_DECL_NSIXPCSCRIPTABLE
00332 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00333     NS_DECL_NSISECURITYCHECKEDCOMPONENT
00334 #endif
00335 
00336 public:
00337     nsXPCComponents_InterfacesByID();
00338     virtual ~nsXPCComponents_InterfacesByID();
00339 
00340 private:
00341     nsCOMPtr<nsIInterfaceInfoManager> mManager;
00342 };
00343 
00344 
00345 nsXPCComponents_InterfacesByID::nsXPCComponents_InterfacesByID()
00346 {
00347     mManager = dont_AddRef(XPTI_GetInterfaceInfoManager());
00348 }
00349 
00350 nsXPCComponents_InterfacesByID::~nsXPCComponents_InterfacesByID()
00351 {
00352     // empty
00353 }
00354 
00355 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID)
00356   NS_INTERFACE_MAP_ENTRY(nsIScriptableInterfacesByID)
00357   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00358 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00359   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
00360 #endif
00361   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptableInterfacesByID)
00362 NS_INTERFACE_MAP_END_THREADSAFE
00363 
00364 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_InterfacesByID)
00365 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_InterfacesByID)
00366 
00367 // The nsIXPCScriptable map declaration that will generate stubs for us...
00368 #define XPC_MAP_CLASSNAME           nsXPCComponents_InterfacesByID
00369 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_InterfacesByID"
00370 #define                             XPC_MAP_WANT_NEWRESOLVE
00371 #define                             XPC_MAP_WANT_NEWENUMERATE
00372 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
00373                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
00374 #include "xpc_map_end.h" /* This will #undef the above */
00375 
00376 /* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */
00377 NS_IMETHODIMP
00378 nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
00379                                              JSContext * cx, JSObject * obj,
00380                                              PRUint32 enum_op, jsval * statep,
00381                                              jsid * idp, PRBool *_retval)
00382 {
00383     nsIEnumerator* e;
00384 
00385     switch(enum_op)
00386     {
00387         case JSENUMERATE_INIT:
00388         {
00389             if(!mManager ||
00390                NS_FAILED(mManager->EnumerateInterfaces(&e)) || !e ||
00391                NS_FAILED(e->First()))
00392 
00393             {
00394                 *statep = JSVAL_NULL;
00395                 return NS_ERROR_UNEXPECTED;
00396             }
00397 
00398             *statep = PRIVATE_TO_JSVAL(e);
00399             if(idp)
00400                 *idp = JSVAL_ZERO; // indicate that we don't know the count
00401             return NS_OK;
00402         }
00403         case JSENUMERATE_NEXT:
00404         {
00405             nsCOMPtr<nsISupports> isup;
00406 
00407             e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
00408 
00409             while(1)
00410             {
00411                 if(NS_ENUMERATOR_FALSE == e->IsDone() &&
00412                    NS_SUCCEEDED(e->CurrentItem(getter_AddRefs(isup))) && isup)
00413                 {
00414                     e->Next();
00415                     nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(isup));
00416                     if(iface)
00417                     {
00418                         nsIID const *iid;
00419                         char* idstr;
00420                         JSString* jsstr;
00421                         PRBool scriptable;
00422 
00423                         if(NS_SUCCEEDED(iface->IsScriptable(&scriptable)) &&
00424                            !scriptable)
00425                         {
00426                             continue;
00427                         }
00428 
00429                         if(NS_SUCCEEDED(iface->GetIIDShared(&iid)) &&
00430                            nsnull != (idstr = iid->ToString()))
00431                         {
00432                             jsstr = JS_NewStringCopyZ(cx, idstr);
00433                             nsMemory::Free(idstr);
00434                             if (jsstr &&
00435                                 JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp))
00436                             {
00437                                 return NS_OK;
00438                             }
00439                         }
00440                     }
00441                 }
00442                 // else...
00443                 break;
00444             }
00445             // FALL THROUGH
00446         }
00447 
00448         case JSENUMERATE_DESTROY:
00449         default:
00450             e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
00451             NS_IF_RELEASE(e);
00452             *statep = JSVAL_NULL;
00453             return NS_OK;
00454     }
00455 }
00456 
00457 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
00458 NS_IMETHODIMP
00459 nsXPCComponents_InterfacesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
00460                                            JSContext * cx, JSObject * obj,
00461                                            jsval id, PRUint32 flags,
00462                                            JSObject * *objp, PRBool *_retval)
00463 {
00464     const jschar* name = nsnull;
00465 
00466     if(mManager &&
00467        JSVAL_IS_STRING(id) &&
00468        38 == JS_GetStringLength(JSVAL_TO_STRING(id)) &&
00469        nsnull != (name = JS_GetStringChars(JSVAL_TO_STRING(id))))
00470     {
00471         nsID iid;
00472         if (!iid.Parse(NS_ConvertUCS2toUTF8(NS_REINTERPRET_CAST(const PRUnichar*,
00473 name)).get()))
00474             return NS_OK;
00475 
00476         nsCOMPtr<nsIInterfaceInfo> info;
00477         mManager->GetInfoForIID(&iid, getter_AddRefs(info));
00478         if(!info)
00479             return NS_OK;
00480 
00481         nsCOMPtr<nsIJSIID> nsid =
00482             dont_AddRef(NS_STATIC_CAST(nsIJSIID*, nsJSIID::NewID(info)));
00483 
00484         if (!nsid)
00485             return NS_ERROR_OUT_OF_MEMORY;
00486 
00487         nsCOMPtr<nsIXPConnect> xpc;
00488         wrapper->GetXPConnect(getter_AddRefs(xpc));
00489         if(xpc)
00490         {
00491             nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00492             if(NS_SUCCEEDED(xpc->WrapNative(cx, obj,
00493                                             NS_STATIC_CAST(nsIJSIID*,nsid),
00494                                             NS_GET_IID(nsIJSIID),
00495                                             getter_AddRefs(holder))))
00496             {
00497                 JSObject* idobj;
00498                 if(holder && NS_SUCCEEDED(holder->GetJSObject(&idobj)))
00499                 {
00500                     jsid idid;
00501 
00502                     *objp = obj;
00503                     *_retval = JS_ValueToId(cx, id, &idid) &&
00504                         OBJ_DEFINE_PROPERTY(cx, obj, idid,
00505                                             OBJECT_TO_JSVAL(idobj),
00506                                             nsnull, nsnull,
00507                                             JSPROP_ENUMERATE |
00508                                             JSPROP_READONLY |
00509                                             JSPROP_PERMANENT,
00510                                             nsnull);
00511                 }
00512             }
00513         }
00514     }
00515     return NS_OK;
00516 }
00517 
00518 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
00519 /* string canCreateWrapper (in nsIIDPtr iid); */
00520 NS_IMETHODIMP
00521 nsXPCComponents_InterfacesByID::CanCreateWrapper(const nsIID * iid, char **_retval)
00522 {
00523     // We let anyone do this...
00524     *_retval = xpc_CloneAllAccess();
00525     return NS_OK;
00526 }
00527 
00528 /* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
00529 NS_IMETHODIMP
00530 nsXPCComponents_InterfacesByID::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
00531 {
00532     // If you have to ask, then the answer is NO
00533     *_retval = nsnull;
00534     return NS_OK;
00535 }
00536 
00537 /* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
00538 NS_IMETHODIMP
00539 nsXPCComponents_InterfacesByID::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
00540 {
00541     // If you have to ask, then the answer is NO
00542     *_retval = nsnull;
00543     return NS_OK;
00544 }
00545 
00546 /* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
00547 NS_IMETHODIMP
00548 nsXPCComponents_InterfacesByID::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
00549 {
00550     // If you have to ask, then the answer is NO
00551     *_retval = nsnull;
00552     return NS_OK;
00553 }
00554 #endif
00555 
00556 /***************************************************************************/
00557 /***************************************************************************/
00558 /***************************************************************************/
00559 
00560 
00561 
00562 class nsXPCComponents_Classes : public nsIXPCComponents_Classes, public nsIXPCScriptable
00563 {
00564 public:
00565     // all the interface method declarations...
00566     NS_DECL_ISUPPORTS
00567     NS_DECL_NSIXPCCOMPONENTS_CLASSES
00568     NS_DECL_NSIXPCSCRIPTABLE
00569 
00570 public:
00571     nsXPCComponents_Classes();
00572     virtual ~nsXPCComponents_Classes();
00573 };
00574 
00575 nsXPCComponents_Classes::nsXPCComponents_Classes()
00576 {
00577 }
00578 
00579 nsXPCComponents_Classes::~nsXPCComponents_Classes()
00580 {
00581     // empty
00582 }
00583 
00584 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Classes)
00585   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Classes)
00586   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00587   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Classes)
00588 NS_INTERFACE_MAP_END_THREADSAFE
00589 
00590 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Classes)
00591 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Classes)
00592 
00593 // The nsIXPCScriptable map declaration that will generate stubs for us...
00594 #define XPC_MAP_CLASSNAME           nsXPCComponents_Classes
00595 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Classes"
00596 #define                             XPC_MAP_WANT_NEWRESOLVE
00597 #define                             XPC_MAP_WANT_NEWENUMERATE
00598 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
00599                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
00600 #include "xpc_map_end.h" /* This will #undef the above */
00601 
00602 
00603 /* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */
00604 NS_IMETHODIMP
00605 nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
00606                                       JSContext * cx, JSObject * obj,
00607                                       PRUint32 enum_op, jsval * statep,
00608                                       jsid * idp, PRBool *_retval)
00609 {
00610     nsISimpleEnumerator* e;
00611 
00612     switch(enum_op)
00613     {
00614         case JSENUMERATE_INIT:
00615         {
00616             nsCOMPtr<nsIComponentRegistrar> compMgr;
00617             if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
00618                NS_FAILED(compMgr->EnumerateContractIDs(&e)) || !e )
00619             {
00620                 *statep = JSVAL_NULL;
00621                 return NS_ERROR_UNEXPECTED;
00622             }
00623 
00624             *statep = PRIVATE_TO_JSVAL(e);
00625             if(idp)
00626                 *idp = JSVAL_ZERO; // indicate that we don't know the count
00627             return NS_OK;
00628         }
00629         case JSENUMERATE_NEXT:
00630         {
00631             nsCOMPtr<nsISupports> isup;
00632             PRBool hasMore;
00633             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
00634 
00635             if(NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
00636                NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup)
00637             {
00638                 nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
00639                 if(holder)
00640                 {
00641                     nsCAutoString name;
00642                     if(NS_SUCCEEDED(holder->GetData(name)))
00643                     {
00644                         JSString* idstr = JS_NewStringCopyN(cx, name.get(), name.Length());
00645                         if(idstr &&
00646                            JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp))
00647                         {
00648                             return NS_OK;
00649                         }
00650                     }
00651                 }
00652             }
00653             // else... FALL THROUGH
00654         }
00655 
00656         case JSENUMERATE_DESTROY:
00657         default:
00658             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
00659             NS_IF_RELEASE(e);
00660             *statep = JSVAL_NULL;
00661             return NS_OK;
00662     }
00663 }
00664 
00665 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
00666 NS_IMETHODIMP
00667 nsXPCComponents_Classes::NewResolve(nsIXPConnectWrappedNative *wrapper,
00668                                     JSContext * cx, JSObject * obj,
00669                                     jsval id, PRUint32 flags,
00670                                     JSObject * *objp, PRBool *_retval)
00671 
00672 {
00673     const char* name = nsnull;
00674 
00675     if(JSVAL_IS_STRING(id) &&
00676        nsnull != (name = JS_GetStringBytes(JSVAL_TO_STRING(id))) &&
00677        name[0] != '{') // we only allow contractids here
00678     {
00679         nsCOMPtr<nsIJSCID> nsid =
00680             dont_AddRef(NS_STATIC_CAST(nsIJSCID*,nsJSCID::NewID(name)));
00681         if(nsid)
00682         {
00683             nsCOMPtr<nsIXPConnect> xpc;
00684             wrapper->GetXPConnect(getter_AddRefs(xpc));
00685             if(xpc)
00686             {
00687                 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00688                 if(NS_SUCCEEDED(xpc->WrapNative(cx, obj,
00689                                                 NS_STATIC_CAST(nsIJSCID*,nsid),
00690                                                 NS_GET_IID(nsIJSCID),
00691                                                 getter_AddRefs(holder))))
00692                 {
00693                     JSObject* idobj;
00694                     if(holder && NS_SUCCEEDED(holder->GetJSObject(&idobj)))
00695                     {
00696                         jsid idid;
00697 
00698                         *objp = obj;
00699                         *_retval = JS_ValueToId(cx, id, &idid) &&
00700                                    OBJ_DEFINE_PROPERTY(cx, obj, idid,
00701                                                        OBJECT_TO_JSVAL(idobj),
00702                                                        nsnull, nsnull,
00703                                                        JSPROP_ENUMERATE |
00704                                                        JSPROP_READONLY |
00705                                                        JSPROP_PERMANENT,
00706                                                        nsnull);
00707                     }
00708                 }
00709             }
00710         }
00711     }
00712     return NS_OK;
00713 }
00714 
00715 /***************************************************************************/
00716 /***************************************************************************/
00717 /***************************************************************************/
00718 
00719 class nsXPCComponents_ClassesByID : public nsIXPCComponents_ClassesByID, public nsIXPCScriptable
00720 {
00721 public:
00722     // all the interface method declarations...
00723     NS_DECL_ISUPPORTS
00724     NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID
00725     NS_DECL_NSIXPCSCRIPTABLE
00726 
00727 public:
00728     nsXPCComponents_ClassesByID();
00729     virtual ~nsXPCComponents_ClassesByID();
00730 };
00731 
00732 nsXPCComponents_ClassesByID::nsXPCComponents_ClassesByID()
00733 {
00734 }
00735 
00736 nsXPCComponents_ClassesByID::~nsXPCComponents_ClassesByID()
00737 {
00738     // empty
00739 }
00740 
00741 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ClassesByID)
00742   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ClassesByID)
00743   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00744   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ClassesByID)
00745 NS_INTERFACE_MAP_END_THREADSAFE
00746 
00747 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_ClassesByID)
00748 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_ClassesByID)
00749 
00750 // The nsIXPCScriptable map declaration that will generate stubs for us...
00751 #define XPC_MAP_CLASSNAME           nsXPCComponents_ClassesByID
00752 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ClassesByID"
00753 #define                             XPC_MAP_WANT_NEWRESOLVE
00754 #define                             XPC_MAP_WANT_NEWENUMERATE
00755 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
00756                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
00757 #include "xpc_map_end.h" /* This will #undef the above */
00758 
00759 /* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */
00760 NS_IMETHODIMP
00761 nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
00762                                           JSContext * cx, JSObject * obj,
00763                                           PRUint32 enum_op, jsval * statep,
00764                                           jsid * idp, PRBool *_retval)
00765 {
00766     nsISimpleEnumerator* e;
00767 
00768     switch(enum_op)
00769     {
00770         case JSENUMERATE_INIT:
00771         {
00772             nsCOMPtr<nsIComponentRegistrar> compMgr;
00773             if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
00774                NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e )
00775             {
00776                 *statep = JSVAL_NULL;
00777                 return NS_ERROR_UNEXPECTED;
00778             }
00779 
00780             *statep = PRIVATE_TO_JSVAL(e);
00781             if(idp)
00782                 *idp = JSVAL_ZERO; // indicate that we don't know the count
00783             return NS_OK;
00784         }
00785         case JSENUMERATE_NEXT:
00786         {
00787             nsCOMPtr<nsISupports> isup;
00788             PRBool hasMore;
00789             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
00790 
00791             if(NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
00792                NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup)
00793             {
00794                 nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
00795                 if(holder)
00796                 {
00797                     char* name;
00798                     if(NS_SUCCEEDED(holder->ToString(&name)) && name)
00799                     {
00800                         JSString* idstr = JS_NewStringCopyZ(cx, name);
00801                         nsMemory::Free(name);
00802                         if(idstr &&
00803                            JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp))
00804                         {
00805                             return NS_OK;
00806                         }
00807                     }
00808                 }
00809             }
00810             // else... FALL THROUGH
00811         }
00812 
00813         case JSENUMERATE_DESTROY:
00814         default:
00815             e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
00816             NS_IF_RELEASE(e);
00817             *statep = JSVAL_NULL;
00818             return NS_OK;
00819     }
00820 }
00821 
00822 static PRBool
00823 IsRegisteredCLSID(const char* str)
00824 {
00825     PRBool registered;
00826     nsID id;
00827 
00828     if(!id.Parse(str))
00829         return PR_FALSE;
00830 
00831     nsCOMPtr<nsIComponentRegistrar> compMgr;
00832     if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
00833        NS_FAILED(compMgr->IsCIDRegistered(id, &registered)))
00834         return PR_FALSE;
00835 
00836     return registered;
00837 }
00838 
00839 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
00840 NS_IMETHODIMP
00841 nsXPCComponents_ClassesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
00842                                         JSContext * cx, JSObject * obj,
00843                                         jsval id, PRUint32 flags,
00844                                         JSObject * *objp, PRBool *_retval)
00845 {
00846     const char* name = nsnull;
00847 
00848     if(JSVAL_IS_STRING(id) &&
00849        nsnull != (name = JS_GetStringBytes(JSVAL_TO_STRING(id))) &&
00850        name[0] == '{' &&
00851        IsRegisteredCLSID(name)) // we only allow canonical CLSIDs here
00852     {
00853         nsCOMPtr<nsIJSCID> nsid =
00854             dont_AddRef(NS_STATIC_CAST(nsIJSCID*,nsJSCID::NewID(name)));
00855         if(nsid)
00856         {
00857             nsCOMPtr<nsIXPConnect> xpc;
00858             wrapper->GetXPConnect(getter_AddRefs(xpc));
00859             if(xpc)
00860             {
00861                 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00862                 if(NS_SUCCEEDED(xpc->WrapNative(cx, obj,
00863                                                 NS_STATIC_CAST(nsIJSCID*,nsid),
00864                                                 NS_GET_IID(nsIJSCID),
00865                                                 getter_AddRefs(holder))))
00866                 {
00867                     JSObject* idobj;
00868                     if(holder && NS_SUCCEEDED(holder->GetJSObject(&idobj)))
00869                     {
00870                         jsid idid;
00871 
00872                         *objp = obj;
00873                         *_retval = JS_ValueToId(cx, id, &idid) &&
00874                                    OBJ_DEFINE_PROPERTY(cx, obj, idid,
00875                                                        OBJECT_TO_JSVAL(idobj),
00876                                                        nsnull, nsnull,
00877                                                        JSPROP_ENUMERATE |
00878                                                        JSPROP_READONLY |
00879                                                        JSPROP_PERMANENT,
00880                                                        nsnull);
00881                     }
00882                 }
00883             }
00884         }
00885     }
00886     return NS_OK;
00887 }
00888 
00889 
00890 /***************************************************************************/
00891 
00892 // Currently the possible results do not change at runtime, so they are only
00893 // cached once (unlike ContractIDs, CLSIDs, and IIDs)
00894 
00895 class nsXPCComponents_Results : public nsIXPCComponents_Results, public nsIXPCScriptable
00896 {
00897 public:
00898     // all the interface method declarations...
00899     NS_DECL_ISUPPORTS
00900     NS_DECL_NSIXPCCOMPONENTS_RESULTS
00901     NS_DECL_NSIXPCSCRIPTABLE
00902 
00903 public:
00904     nsXPCComponents_Results();
00905     virtual ~nsXPCComponents_Results();
00906 };
00907 
00908 nsXPCComponents_Results::nsXPCComponents_Results()
00909 {
00910 }
00911 
00912 nsXPCComponents_Results::~nsXPCComponents_Results()
00913 {
00914     // empty
00915 }
00916 
00917 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Results)
00918   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Results)
00919   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
00920   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Results)
00921 NS_INTERFACE_MAP_END_THREADSAFE
00922 
00923 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Results)
00924 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Results)
00925 
00926 // The nsIXPCScriptable map declaration that will generate stubs for us...
00927 #define XPC_MAP_CLASSNAME           nsXPCComponents_Results
00928 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Results"
00929 #define                             XPC_MAP_WANT_NEWRESOLVE
00930 #define                             XPC_MAP_WANT_NEWENUMERATE
00931 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
00932                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
00933 #include "xpc_map_end.h" /* This will #undef the above */
00934 
00935 /* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */
00936 NS_IMETHODIMP
00937 nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
00938                                       JSContext * cx, JSObject * obj,
00939                                       PRUint32 enum_op, jsval * statep,
00940                                       jsid * idp, PRBool *_retval)
00941 {
00942     void** iter;
00943 
00944     switch(enum_op)
00945     {
00946         case JSENUMERATE_INIT:
00947         {
00948             if(idp)
00949                 *idp = INT_TO_JSVAL(nsXPCException::GetNSResultCount());
00950 
00951             void** space = (void**) new char[sizeof(void*)];
00952             *space = nsnull;
00953             *statep = PRIVATE_TO_JSVAL(space);
00954             return NS_OK;
00955         }
00956         case JSENUMERATE_NEXT:
00957         {
00958             const char* name;
00959             iter = (void**) JSVAL_TO_PRIVATE(*statep);
00960             if(nsXPCException::IterateNSResults(nsnull, &name, nsnull, iter))
00961             {
00962                 JSString* idstr = JS_NewStringCopyZ(cx, name);
00963                 if(idstr && JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp))
00964                     return NS_OK;
00965             }
00966             // else... FALL THROUGH
00967         }
00968 
00969         case JSENUMERATE_DESTROY:
00970         default:
00971             iter = (void**) JSVAL_TO_PRIVATE(*statep);
00972             delete [] (char*) iter;
00973             *statep = JSVAL_NULL;
00974             return NS_OK;
00975     }
00976 }
00977 
00978 
00979 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
00980 NS_IMETHODIMP
00981 nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper,
00982                                     JSContext * cx, JSObject * obj,
00983                                     jsval id, PRUint32 flags,
00984                                     JSObject * *objp, PRBool *_retval)
00985 {
00986     const char* name = nsnull;
00987 
00988     if(JSVAL_IS_STRING(id) &&
00989        nsnull != (name = JS_GetStringBytes(JSVAL_TO_STRING(id))))
00990     {
00991         const char* rv_name;
00992         void* iter = nsnull;
00993         nsresult rv;
00994         while(nsXPCException::IterateNSResults(&rv, &rv_name, nsnull, &iter))
00995         {
00996             if(!strcmp(name, rv_name))
00997             {
00998                 jsid idid;
00999                 jsval val;
01000 
01001                 *objp = obj;
01002                 if(!JS_NewNumberValue(cx, (jsdouble)rv, &val) ||
01003                    !JS_ValueToId(cx, id, &idid) ||
01004                    !OBJ_DEFINE_PROPERTY(cx, obj, idid, val,
01005                                         nsnull, nsnull,
01006                                         JSPROP_ENUMERATE |
01007                                         JSPROP_READONLY |
01008                                         JSPROP_PERMANENT,
01009                                         nsnull))
01010                 {
01011                     return NS_ERROR_UNEXPECTED;
01012                 }
01013             }
01014         }
01015     }
01016     return NS_OK;
01017 }
01018 
01019 /***************************************************************************/
01020 // JavaScript Constructor for nsIJSID objects (Components.ID)
01021 
01022 class nsXPCComponents_ID : public nsIXPCComponents_ID, public nsIXPCScriptable
01023 {
01024 public:
01025     // all the interface method declarations...
01026     NS_DECL_ISUPPORTS
01027     NS_DECL_NSIXPCCOMPONENTS_ID
01028     NS_DECL_NSIXPCSCRIPTABLE
01029 
01030 
01031 public:
01032     nsXPCComponents_ID();
01033     virtual ~nsXPCComponents_ID();
01034 
01035 private:
01036     NS_METHOD CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01037                               JSContext * cx, JSObject * obj,
01038                               PRUint32 argc, jsval * argv,
01039                               jsval * vp, PRBool *_retval);
01040 };
01041 
01042 nsXPCComponents_ID::nsXPCComponents_ID()
01043 {
01044 }
01045 
01046 nsXPCComponents_ID::~nsXPCComponents_ID()
01047 {
01048     // empty
01049 }
01050 
01051 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ID)
01052   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ID)
01053   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
01054   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ID)
01055 NS_INTERFACE_MAP_END_THREADSAFE
01056 
01057 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_ID)
01058 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_ID)
01059 
01060 // The nsIXPCScriptable map declaration that will generate stubs for us...
01061 #define XPC_MAP_CLASSNAME           nsXPCComponents_ID
01062 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ID"
01063 #define                             XPC_MAP_WANT_CALL
01064 #define                             XPC_MAP_WANT_CONSTRUCT
01065 #define                             XPC_MAP_WANT_HASINSTANCE
01066 #define XPC_MAP_FLAGS               0
01067 #include "xpc_map_end.h" /* This will #undef the above */
01068 
01069 
01070 /* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01071 NS_IMETHODIMP
01072 nsXPCComponents_ID::Call(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01073 {
01074     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01075 
01076 }
01077 
01078 /* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01079 NS_IMETHODIMP
01080 nsXPCComponents_ID::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01081 {
01082     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01083 }
01084 
01085 NS_METHOD
01086 nsXPCComponents_ID::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01087                                     JSContext * cx, JSObject * obj,
01088                                     PRUint32 argc, jsval * argv,
01089                                     jsval * vp, PRBool *_retval)
01090 {
01091     // make sure we have at least one arg
01092 
01093     if(!argc)
01094         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
01095 
01096     XPCCallContext ccx(JS_CALLER, cx);
01097     if(!ccx.IsValid())
01098         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01099 
01100     XPCContext* xpcc = ccx.GetXPCContext();
01101 
01102     // Do the security check if necessary
01103 
01104     nsIXPCSecurityManager* sm =
01105             xpcc->GetAppropriateSecurityManager(
01106                         nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
01107     if(sm && NS_FAILED(sm->CanCreateInstance(cx, nsJSID::GetCID())))
01108     {
01109         // the security manager vetoed. It should have set an exception.
01110         *_retval = JS_FALSE;
01111         return NS_OK;
01112     }
01113 
01114     // convert the first argument into a string and see if it looks like an id
01115 
01116     JSString* jsstr;
01117     const char* str;
01118     nsID id;
01119 
01120     if(!(jsstr = JS_ValueToString(cx, argv[0])) ||
01121        !(str = JS_GetStringBytes(jsstr)) ||
01122        ! id.Parse(str))
01123     {
01124         return ThrowAndFail(NS_ERROR_XPC_BAD_ID_STRING, cx, _retval);
01125     }
01126 
01127     // make the new object and return it.
01128 
01129     JSObject* newobj = xpc_NewIDObject(cx, obj, id);
01130 
01131     if(vp)
01132         *vp = OBJECT_TO_JSVAL(newobj);
01133 
01134     return NS_OK;
01135 }
01136 
01137 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
01138 NS_IMETHODIMP
01139 nsXPCComponents_ID::HasInstance(nsIXPConnectWrappedNative *wrapper,
01140                                 JSContext * cx, JSObject * obj,
01141                                 jsval val, PRBool *bp, PRBool *_retval)
01142 {
01143     if(bp)
01144         *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIJSID));
01145     return NS_OK;
01146 }
01147 
01148 /***************************************************************************/
01149 // JavaScript Constructor for nsIXPCException objects (Components.Exception)
01150 
01151 class nsXPCComponents_Exception : public nsIXPCComponents_Exception, public nsIXPCScriptable
01152 {
01153 public:
01154     // all the interface method declarations...
01155     NS_DECL_ISUPPORTS
01156     NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
01157     NS_DECL_NSIXPCSCRIPTABLE
01158 
01159 
01160 public:
01161     nsXPCComponents_Exception();
01162     virtual ~nsXPCComponents_Exception();
01163 
01164 private:
01165     NS_METHOD CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01166                               JSContext * cx, JSObject * obj,
01167                               PRUint32 argc, jsval * argv,
01168                               jsval * vp, PRBool *_retval);
01169 };
01170 
01171 nsXPCComponents_Exception::nsXPCComponents_Exception()
01172 {
01173 }
01174 
01175 nsXPCComponents_Exception::~nsXPCComponents_Exception()
01176 {
01177     // empty
01178 }
01179 
01180 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Exception)
01181   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Exception)
01182   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
01183   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Exception)
01184 NS_INTERFACE_MAP_END_THREADSAFE
01185 
01186 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Exception)
01187 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Exception)
01188 
01189 // The nsIXPCScriptable map declaration that will generate stubs for us...
01190 #define XPC_MAP_CLASSNAME           nsXPCComponents_Exception
01191 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Exception"
01192 #define                             XPC_MAP_WANT_CALL
01193 #define                             XPC_MAP_WANT_CONSTRUCT
01194 #define                             XPC_MAP_WANT_HASINSTANCE
01195 #define XPC_MAP_FLAGS               0
01196 #include "xpc_map_end.h" /* This will #undef the above */
01197 
01198 
01199 /* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01200 NS_IMETHODIMP
01201 nsXPCComponents_Exception::Call(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01202 {
01203     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01204 
01205 }
01206 
01207 /* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01208 NS_IMETHODIMP
01209 nsXPCComponents_Exception::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01210 {
01211     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01212 }
01213 
01214 NS_METHOD
01215 nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01216                                            JSContext * cx, JSObject * obj,
01217                                            PRUint32 argc, jsval * argv,
01218                                            jsval * vp, PRBool *_retval)
01219 {
01220     XPCCallContext ccx(JS_CALLER, cx);
01221     if(!ccx.IsValid())
01222         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01223 
01224     nsXPConnect* xpc = ccx.GetXPConnect();
01225     XPCContext* xpcc = ccx.GetXPCContext();
01226 
01227     // Do the security check if necessary
01228 
01229     nsIXPCSecurityManager* sm =
01230             xpcc->GetAppropriateSecurityManager(
01231                         nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
01232     if(sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCException::GetCID())))
01233     {
01234         // the security manager vetoed. It should have set an exception.
01235         *_retval = JS_FALSE;
01236         return NS_OK;
01237     }
01238 
01239     // initialization params for the exception object we will create
01240     const char*             eMsg = "exception";
01241     nsresult                eResult = NS_ERROR_FAILURE;
01242     nsCOMPtr<nsIStackFrame> eStack;
01243     nsCOMPtr<nsISupports>   eData;
01244 
01245     // all params are optional - grab any passed in
01246     switch(argc)
01247     {
01248         default:    // more than 4 - ignore extra
01249             // ...fall through...
01250         case 4:     // argv[3] is object for eData
01251             if(JSVAL_IS_NULL(argv[3]))
01252             {
01253                 // do nothing, leave eData as null
01254             }
01255             else
01256             {
01257                 if(JSVAL_IS_PRIMITIVE(argv[3]) ||
01258                    NS_FAILED(xpc->WrapJS(cx, JSVAL_TO_OBJECT(argv[3]),
01259                                          NS_GET_IID(nsISupports),
01260                                          (void**)getter_AddRefs(eData))))
01261                     return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
01262             }
01263             // ...fall through...
01264         case 3:     // argv[2] is object for eStack
01265             if(JSVAL_IS_NULL(argv[2]))
01266             {
01267                 // do nothing, leave eStack as null
01268             }
01269             else
01270             {
01271                 if(JSVAL_IS_PRIMITIVE(argv[2]) ||
01272                    NS_FAILED(xpc->WrapJS(cx, JSVAL_TO_OBJECT(argv[2]),
01273                                          NS_GET_IID(nsIStackFrame),
01274                                          (void**)getter_AddRefs(eStack))))
01275                     return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
01276             }
01277             // fall through...
01278         case 2:     // argv[1] is nsresult for eResult
01279             if(!JS_ValueToECMAInt32(cx, argv[1], (int32*) &eResult))
01280                 return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
01281             // ...fall through...
01282         case 1:     // argv[0] is string for eMsg
01283             {
01284                 JSString* str = JS_ValueToString(cx, argv[0]);
01285                 if(!str || !(eMsg = JS_GetStringBytes(str)))
01286                     return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
01287             }
01288             // ...fall through...
01289         case 0: // this case required so that 'default' does not include zero.
01290             ;   // -- do nothing --
01291     }
01292 
01293     nsCOMPtr<nsIException> e;
01294     nsXPCException::NewException(eMsg, eResult, eStack, eData, getter_AddRefs(e));
01295     if(!e)
01296         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01297 
01298     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
01299     JSObject* newObj = nsnull;
01300 
01301     if(NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
01302                  getter_AddRefs(holder))) || !holder ||
01303        NS_FAILED(holder->GetJSObject(&newObj)) || !newObj)
01304     {
01305         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
01306     }
01307 
01308     if(vp)
01309         *vp = OBJECT_TO_JSVAL(newObj);
01310 
01311     return NS_OK;
01312 }
01313 
01314 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
01315 NS_IMETHODIMP
01316 nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper,
01317                                        JSContext * cx, JSObject * obj,
01318                                        jsval val, PRBool *bp,
01319                                        PRBool *_retval)
01320 {
01321     if(bp)
01322         *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIException));
01323     return NS_OK;
01324 }
01325 
01326 /***************************************************************************/
01327 // This class is for the thing returned by "new Component.Constructor".
01328 
01329 // XXXjband we use this CID for security check, but security system can't see
01330 // it since it has no registed factory. Security really kicks in when we try
01331 // to build a wrapper around an instance.
01332 
01333 // {B4A95150-E25A-11d3-8F61-0010A4E73D9A}
01334 #define NS_XPCCONSTRUCTOR_CID  \
01335 { 0xb4a95150, 0xe25a, 0x11d3, \
01336     { 0x8f, 0x61, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
01337 
01338 class nsXPCConstructor : public nsIXPCConstructor, public nsIXPCScriptable
01339 {
01340 public:
01341     NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID)
01342 public:
01343     // all the interface method declarations...
01344     NS_DECL_ISUPPORTS
01345     NS_DECL_NSIXPCCONSTRUCTOR
01346     NS_DECL_NSIXPCSCRIPTABLE
01347 
01348 public:
01349     nsXPCConstructor(); // not implemented
01350     nsXPCConstructor(nsIJSCID* aClassID,
01351                      nsIJSIID* aInterfaceID,
01352                      const char* aInitializer);
01353     virtual ~nsXPCConstructor();
01354 
01355 private:
01356     NS_METHOD CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01357                               JSContext * cx, JSObject * obj,
01358                               PRUint32 argc, jsval * argv,
01359                               jsval * vp, PRBool *_retval);
01360 private:
01361     nsIJSCID* mClassID;
01362     nsIJSIID* mInterfaceID;
01363     char*     mInitializer;
01364 };
01365 
01366 nsXPCConstructor::nsXPCConstructor(nsIJSCID* aClassID,
01367                                    nsIJSIID* aInterfaceID,
01368                                    const char* aInitializer)
01369 {
01370     NS_IF_ADDREF(mClassID = aClassID);
01371     NS_IF_ADDREF(mInterfaceID = aInterfaceID);
01372     mInitializer = aInitializer ?
01373         (char*) nsMemory::Clone(aInitializer, strlen(aInitializer)+1) :
01374         nsnull;
01375 }
01376 
01377 nsXPCConstructor::~nsXPCConstructor()
01378 {
01379     NS_IF_RELEASE(mClassID);
01380     NS_IF_RELEASE(mInterfaceID);
01381     if(mInitializer)
01382         nsMemory::Free(mInitializer);
01383 }
01384 
01385 /* readonly attribute nsIJSCID classID; */
01386 NS_IMETHODIMP
01387 nsXPCConstructor::GetClassID(nsIJSCID * *aClassID)
01388 {
01389     NS_IF_ADDREF(*aClassID = mClassID);
01390     return NS_OK;
01391 }
01392 
01393 /* readonly attribute nsIJSIID interfaceID; */
01394 NS_IMETHODIMP
01395 nsXPCConstructor::GetInterfaceID(nsIJSIID * *aInterfaceID)
01396 {
01397     NS_IF_ADDREF(*aInterfaceID = mInterfaceID);
01398     return NS_OK;
01399 }
01400 
01401 /* readonly attribute string initializer; */
01402 NS_IMETHODIMP
01403 nsXPCConstructor::GetInitializer(char * *aInitializer)
01404 {
01405     XPC_STRING_GETTER_BODY(aInitializer, mInitializer);
01406 }
01407 
01408 NS_INTERFACE_MAP_BEGIN(nsXPCConstructor)
01409   NS_INTERFACE_MAP_ENTRY(nsIXPCConstructor)
01410   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
01411   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCConstructor)
01412 NS_INTERFACE_MAP_END_THREADSAFE
01413 
01414 NS_IMPL_THREADSAFE_ADDREF(nsXPCConstructor)
01415 NS_IMPL_THREADSAFE_RELEASE(nsXPCConstructor)
01416 
01417 // The nsIXPCScriptable map declaration that will generate stubs for us...
01418 #define XPC_MAP_CLASSNAME           nsXPCConstructor
01419 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCConstructor"
01420 #define                             XPC_MAP_WANT_CALL
01421 #define                             XPC_MAP_WANT_CONSTRUCT
01422 #define XPC_MAP_FLAGS               0
01423 #include "xpc_map_end.h" /* This will #undef the above */
01424 
01425 
01426 /* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01427 NS_IMETHODIMP
01428 nsXPCConstructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01429 {
01430     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01431 
01432 }
01433 
01434 /* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01435 NS_IMETHODIMP
01436 nsXPCConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01437 {
01438     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01439 }
01440 
01441 NS_METHOD
01442 nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01443                                   JSContext * cx, JSObject * obj,
01444                                   PRUint32 argc, jsval * argv,
01445                                   jsval * vp, PRBool *_retval)
01446 {
01447     XPCCallContext ccx(JS_CALLER, cx);
01448     if(!ccx.IsValid())
01449         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01450 
01451     nsXPConnect* xpc = ccx.GetXPConnect();
01452 
01453     // security check not required because we are going to call through the
01454     // code which is reflected into JS which will do that for us later.
01455 
01456     nsCOMPtr<nsIXPConnectJSObjectHolder> cidHolder;
01457     nsCOMPtr<nsIXPConnectJSObjectHolder> iidHolder;
01458     JSObject* cidObj;
01459     JSObject* iidObj;
01460 
01461     if(NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID),
01462                  getter_AddRefs(cidHolder))) || !cidHolder ||
01463        NS_FAILED(cidHolder->GetJSObject(&cidObj)) || !cidObj ||
01464        NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID),
01465                  getter_AddRefs(iidHolder))) || !iidHolder ||
01466        NS_FAILED(iidHolder->GetJSObject(&iidObj)) || !iidObj)
01467     {
01468         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
01469     }
01470 
01471     jsval ctorArgs[1] = {OBJECT_TO_JSVAL(iidObj)};
01472     jsval val;
01473 
01474     if(!JS_CallFunctionName(cx, cidObj, "createInstance", 1, ctorArgs, &val) ||
01475        JSVAL_IS_PRIMITIVE(val))
01476     {
01477         // createInstance will have thrown an exception
01478         *_retval = JS_FALSE;
01479         return NS_OK;
01480     }
01481 
01482     // root the result
01483     if(vp)
01484         *vp = val;
01485 
01486     // call initializer method if supplied
01487     if(mInitializer)
01488     {
01489         JSObject* newObj = JSVAL_TO_OBJECT(val);
01490         jsval fun;
01491         jsval ignored;
01492 
01493         // first check existence of function property for better error reporting
01494         if(!JS_GetProperty(cx, newObj, mInitializer, &fun) ||
01495            JSVAL_IS_PRIMITIVE(fun))
01496         {
01497             return ThrowAndFail(NS_ERROR_XPC_BAD_INITIALIZER_NAME, cx, _retval);
01498         }
01499 
01500         if(!JS_CallFunctionValue(cx, newObj, fun, argc, argv, &ignored))
01501         {
01502             // function should have thrown an exception
01503             *_retval = JS_FALSE;
01504             return NS_OK;
01505         }
01506     }
01507 
01508     return NS_OK;
01509 }
01510 
01511 /*******************************************************/
01512 // JavaScript Constructor for nsIXPCConstructor objects (Components.Constructor)
01513 
01514 class nsXPCComponents_Constructor : public nsIXPCComponents_Constructor, public nsIXPCScriptable
01515 {
01516 public:
01517     // all the interface method declarations...
01518     NS_DECL_ISUPPORTS
01519     NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
01520     NS_DECL_NSIXPCSCRIPTABLE
01521 
01522 public:
01523     nsXPCComponents_Constructor();
01524     virtual ~nsXPCComponents_Constructor();
01525 
01526 private:
01527     NS_METHOD CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01528                               JSContext * cx, JSObject * obj,
01529                               PRUint32 argc, jsval * argv,
01530                               jsval * vp, PRBool *_retval);
01531 };
01532 
01533 nsXPCComponents_Constructor::nsXPCComponents_Constructor()
01534 {
01535 }
01536 
01537 nsXPCComponents_Constructor::~nsXPCComponents_Constructor()
01538 {
01539     // empty
01540 }
01541 
01542 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Constructor)
01543   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Constructor)
01544   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
01545   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Constructor)
01546 NS_INTERFACE_MAP_END_THREADSAFE
01547 
01548 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Constructor)
01549 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Constructor)
01550 
01551 // The nsIXPCScriptable map declaration that will generate stubs for us...
01552 #define XPC_MAP_CLASSNAME           nsXPCComponents_Constructor
01553 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Constructor"
01554 #define                             XPC_MAP_WANT_CALL
01555 #define                             XPC_MAP_WANT_CONSTRUCT
01556 #define                             XPC_MAP_WANT_HASINSTANCE
01557 #define XPC_MAP_FLAGS               0
01558 #include "xpc_map_end.h" /* This will #undef the above */
01559 
01560 
01561 /* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01562 NS_IMETHODIMP
01563 nsXPCComponents_Constructor::Call(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01564 {
01565     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01566 }
01567 
01568 /* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
01569 NS_IMETHODIMP
01570 nsXPCComponents_Constructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval)
01571 {
01572     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
01573 }
01574 
01575 NS_METHOD
01576 nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01577                                              JSContext * cx, JSObject * obj,
01578                                              PRUint32 argc, jsval * argv,
01579                                              jsval * vp, PRBool *_retval)
01580 {
01581     // make sure we have at least one arg
01582 
01583     if(!argc)
01584         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
01585 
01586     // get the various other object pointers we need
01587 
01588     XPCCallContext ccx(JS_CALLER, cx);
01589     if(!ccx.IsValid())
01590         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01591 
01592     nsXPConnect* xpc = ccx.GetXPConnect();
01593     XPCContext* xpcc = ccx.GetXPCContext();
01594     XPCWrappedNativeScope* scope =
01595         XPCWrappedNativeScope::FindInJSObjectScope(ccx, obj);
01596     nsXPCComponents* comp;
01597 
01598     if(!xpc || !xpcc || !scope || !(comp = scope->GetComponents()))
01599         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01600 
01601     // Do the security check if necessary
01602 
01603     nsIXPCSecurityManager* sm =
01604             xpcc->GetAppropriateSecurityManager(
01605                         nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
01606     if(sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCConstructor::GetCID())))
01607     {
01608         // the security manager vetoed. It should have set an exception.
01609         *_retval = JS_FALSE;
01610         return NS_OK;
01611     }
01612 
01613     // initialization params for the Constructor object we will create
01614     nsCOMPtr<nsIJSCID> cClassID;
01615     nsCOMPtr<nsIJSIID> cInterfaceID;
01616     const char*        cInitializer = nsnull;
01617 
01618     if(argc >= 3)
01619     {
01620         // argv[2] is an initializer function or property name
01621         JSString* str = JS_ValueToString(cx, argv[2]);
01622         if(!str || !(cInitializer = JS_GetStringBytes(str)))
01623             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
01624     }
01625 
01626     if(argc >= 2)
01627     {
01628         // argv[1] is an iid name string
01629         // XXXjband support passing "Components.interfaces.foo"?
01630 
01631         nsCOMPtr<nsIScriptableInterfaces> ifaces;
01632         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
01633         JSObject* ifacesObj = nsnull;
01634 
01635         // we do the lookup by asking the Components.interfaces object
01636         // for the property with this name - i.e. we let its caching of these
01637         // nsIJSIID objects work for us.
01638 
01639         if(NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
01640            NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
01641                                      NS_GET_IID(nsIScriptableInterfaces),
01642                                      getter_AddRefs(holder))) || !holder ||
01643            NS_FAILED(holder->GetJSObject(&ifacesObj)) || !ifacesObj)
01644         {
01645             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01646         }
01647 
01648         JSString* str = JS_ValueToString(cx, argv[1]);
01649         if(!str)
01650             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
01651 
01652         jsval val;
01653         if(!JS_GetProperty(cx, ifacesObj, JS_GetStringBytes(str), &val) ||
01654            JSVAL_IS_PRIMITIVE(val))
01655         {
01656             return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
01657         }
01658 
01659         nsCOMPtr<nsIXPConnectWrappedNative> wn;
01660         if(NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val),
01661                                 getter_AddRefs(wn))) || !wn ||
01662            !(cInterfaceID = do_QueryWrappedNative(wn)))
01663         {
01664             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01665         }
01666     }
01667     else
01668     {
01669         nsCOMPtr<nsIInterfaceInfo> info;
01670         xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info));
01671 
01672         if(info)
01673         {
01674             cInterfaceID =
01675                 dont_AddRef(
01676                     NS_STATIC_CAST(nsIJSIID*, nsJSIID::NewID(info)));
01677         }
01678         if(!cInterfaceID)
01679             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01680     }
01681 
01682     // a new scope to avoid warnings about shadowed names
01683     {
01684         // argv[0] is a contractid name string
01685         // XXXjband support passing "Components.classes.foo"?
01686 
01687         // we do the lookup by asking the Components.classes object
01688         // for the property with this name - i.e. we let its caching of these
01689         // nsIJSCID objects work for us.
01690 
01691         nsCOMPtr<nsIXPCComponents_Classes> classes;
01692         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
01693         JSObject* classesObj = nsnull;
01694 
01695         if(NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
01696            NS_FAILED(xpc->WrapNative(cx, obj, classes,
01697                                      NS_GET_IID(nsIXPCComponents_Classes),
01698                                      getter_AddRefs(holder))) || !holder ||
01699            NS_FAILED(holder->GetJSObject(&classesObj)) || !classesObj)
01700         {
01701             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01702         }
01703 
01704         JSString* str = JS_ValueToString(cx, argv[0]);
01705         if(!str)
01706             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
01707 
01708         jsval val;
01709         if(!JS_GetProperty(cx, classesObj, JS_GetStringBytes(str), &val) ||
01710            JSVAL_IS_PRIMITIVE(val))
01711         {
01712             return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
01713         }
01714 
01715         nsCOMPtr<nsIXPConnectWrappedNative> wn;
01716         if(NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val),
01717                                 getter_AddRefs(wn))) || !wn ||
01718            !(cClassID = do_QueryWrappedNative(wn)))
01719         {
01720             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01721         }
01722     }
01723 
01724     nsCOMPtr<nsIXPCConstructor> ctor =
01725         NS_STATIC_CAST(nsIXPCConstructor*,
01726             new nsXPCConstructor(cClassID, cInterfaceID, cInitializer));
01727     if(!ctor)
01728         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
01729 
01730     nsCOMPtr<nsIXPConnectJSObjectHolder> holder2;
01731     JSObject* newObj = nsnull;
01732 
01733     if(NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor),
01734                  getter_AddRefs(holder2))) || !holder2 ||
01735        NS_FAILED(holder2->GetJSObject(&newObj)) || !newObj)
01736     {
01737         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
01738     }
01739 
01740     if(vp)
01741         *vp = OBJECT_TO_JSVAL(newObj);
01742 
01743     return NS_OK;
01744 }
01745 
01746 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
01747 NS_IMETHODIMP
01748 nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
01749                                          JSContext * cx, JSObject * obj,
01750                                          jsval val, PRBool *bp,
01751                                          PRBool *_retval)
01752 {
01753     if(bp)
01754         *bp = JSValIsInterfaceOfType(cx, val, NS_GET_IID(nsIXPCConstructor));
01755     return NS_OK;
01756 }
01757 
01758 /***************************************************************************/
01759 // Javascript constructor for the sandbox object
01760 class nsXPCComponents_utils_Sandbox : public nsIXPCComponents_utils_Sandbox,
01761                                       public nsIXPCScriptable
01762 {
01763 public:
01764     // Aren't macros nice?
01765     NS_DECL_ISUPPORTS
01766     NS_DECL_NSIXPCCOMPONENTS_UTILS_SANDBOX
01767     NS_DECL_NSIXPCSCRIPTABLE
01768 
01769 public:
01770     nsXPCComponents_utils_Sandbox();
01771     virtual ~nsXPCComponents_utils_Sandbox();
01772 
01773 private:
01774     NS_METHOD CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
01775                               JSContext * cx, JSObject * obj,
01776                               PRUint32 argc, jsval * argv,
01777                               jsval * vp, PRBool *_retval);
01778 };
01779 
01780 class nsXPCComponents_Utils :
01781             public nsIXPCComponents_Utils,
01782             public nsIXPCScriptable
01783 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
01784           , public nsISecurityCheckedComponent
01785 #endif
01786 {
01787 public:
01788     // all the interface method declarations...
01789     NS_DECL_ISUPPORTS
01790     NS_DECL_NSIXPCSCRIPTABLE
01791 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
01792     NS_DECL_NSISECURITYCHECKEDCOMPONENT
01793 #endif
01794     NS_DECL_NSIXPCCOMPONENTS_UTILS
01795 
01796 public:
01797     nsXPCComponents_Utils() { }
01798     virtual ~nsXPCComponents_Utils() { }
01799 
01800 private:
01801     nsCOMPtr<nsIXPCComponents_utils_Sandbox> mSandbox;
01802 };
01803 
01804 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils)
01805   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils)
01806   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
01807 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
01808   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
01809 #endif
01810   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils)
01811 NS_INTERFACE_MAP_END_THREADSAFE
01812 
01813 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Utils)
01814 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Utils)
01815 
01816 // The nsIXPCScriptable map declaration that will generate stubs for us...
01817 #define XPC_MAP_CLASSNAME           nsXPCComponents_Utils
01818 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Utils"
01819 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
01820 #include "xpc_map_end.h" /* This will #undef the above */
01821 
01822 NS_IMETHODIMP
01823 nsXPCComponents_Utils::GetSandbox(nsIXPCComponents_utils_Sandbox **aSandbox)
01824 {
01825     NS_ENSURE_ARG_POINTER(aSandbox);
01826     if (!mSandbox && !(mSandbox = new nsXPCComponents_utils_Sandbox())) {
01827         *aSandbox = nsnull;
01828         return NS_ERROR_OUT_OF_MEMORY;
01829     }
01830     NS_ADDREF(*aSandbox = mSandbox);
01831     return NS_OK;
01832 }
01833 
01834 /* void lookupMethod (); */
01835 NS_IMETHODIMP
01836 nsXPCComponents_Utils::LookupMethod()
01837 {
01838     nsresult rv;
01839 
01840     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
01841     if(NS_FAILED(rv))
01842         return NS_ERROR_FAILURE;
01843 
01844     // get the xpconnect native call context
01845     nsCOMPtr<nsIXPCNativeCallContext> cc;
01846     xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
01847     if(!cc)
01848         return NS_ERROR_FAILURE;
01849 
01850 // Check disabled until deprecated Components.lookupMethod removed.
01851 #undef CHECK_FOR_INDIRECT_CALL
01852 #ifdef CHECK_FOR_INDIRECT_CALL
01853     // verify that we are being called from JS (i.e. the current call is
01854     // to this object - though we don't verify that it is to this exact method)
01855     nsCOMPtr<nsISupports> callee;
01856     cc->GetCallee(getter_AddRefs(callee));
01857     if(!callee || callee.get() !=
01858                   NS_STATIC_CAST(const nsISupports*,
01859                                  NS_STATIC_CAST(const nsIXPCComponents_Utils*,this)))
01860         return NS_ERROR_FAILURE;
01861 #endif
01862 
01863     // Get JSContext of current call
01864     JSContext* cx;
01865     rv = cc->GetJSContext(&cx);
01866     if(NS_FAILED(rv) || !cx)
01867         return NS_ERROR_FAILURE;
01868 
01869     // get place for return value
01870     jsval *retval = nsnull;
01871     rv = cc->GetRetValPtr(&retval);
01872     if(NS_FAILED(rv) || !retval)
01873         return NS_ERROR_FAILURE;
01874 
01875     // get argc and argv and verify arg count
01876     PRUint32 argc;
01877     rv = cc->GetArgc(&argc);
01878     if(NS_FAILED(rv))
01879         return NS_ERROR_FAILURE;
01880 
01881     if(argc < 2)
01882         return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
01883 
01884     jsval* argv;
01885     rv = cc->GetArgvPtr(&argv);
01886     if(NS_FAILED(rv) || !argv)
01887         return NS_ERROR_FAILURE;
01888 
01889     // first param must be a JSObject
01890     if(JSVAL_IS_PRIMITIVE(argv[0]))
01891         return NS_ERROR_XPC_BAD_CONVERT_JS;
01892 
01893     JSObject* obj = JSVAL_TO_OBJECT(argv[0]);
01894 
01895     // Can't use the macro OBJ_TO_INNER_OBJECT here due to it using
01896     // the non-exported function js_GetSlotThreadSafe().
01897     {
01898         JSClass *clasp = JS_GET_CLASS(cx, obj);
01899         if (clasp->flags & JSCLASS_IS_EXTENDED) {
01900             JSExtendedClass *xclasp = (JSExtendedClass*)clasp;
01901             if (xclasp->innerObject)
01902                 obj = xclasp->innerObject(cx, obj);
01903         }
01904     }
01905 
01906     // second param must be a string
01907     if(!JSVAL_IS_STRING(argv[1]))
01908         return NS_ERROR_XPC_BAD_CONVERT_JS;
01909 
01910     // Make sure the name (argv[1]) that we use for looking up the
01911     // method/property is atomized.
01912 
01913     jsid name_id;
01914     if(!JS_ValueToId(cx, argv[1], &name_id) ||
01915        !JS_IdToValue(cx, name_id, &argv[1]))
01916         return NS_ERROR_XPC_BAD_CONVERT_JS;
01917 
01918     // this will do verification and the method lookup for us
01919     // Note that if |obj| is an XPCNativeWrapper this will all still work.
01920     // We'll hand back the same method that we'd hand back for the underlying
01921     // XPCWrappedNative.  This means no deep wrapping, unfortunately, but we
01922     // can't keep track of both the underlying function and the
01923     // XPCNativeWrapper at once in a single parent slot...
01924     XPCCallContext inner_cc(JS_CALLER, cx, obj, nsnull, argv[1]);
01925 
01926     // was our jsobject really a wrapped native at all?
01927     XPCWrappedNative* wrapper = inner_cc.GetWrapper();
01928     if(!wrapper || !wrapper->IsValid())
01929         return NS_ERROR_XPC_BAD_CONVERT_JS;
01930 
01931     // did we find a method/attribute by that name?
01932     XPCNativeMember* member = inner_cc.GetMember();
01933     if(!member || member->IsConstant())
01934         return NS_ERROR_XPC_BAD_CONVERT_JS;
01935 
01936     // it would a be a big surprise if there is a member without an interface :)
01937     XPCNativeInterface* iface = inner_cc.GetInterface();
01938     if(!iface)
01939         return NS_ERROR_XPC_BAD_CONVERT_JS;
01940 
01941     // get (and perhaps lazily create) the member's cloneable function
01942     jsval funval;
01943     if(!member->GetValue(inner_cc, iface, &funval))
01944         return NS_ERROR_XPC_BAD_CONVERT_JS;
01945 
01946     // Make sure the function we're cloning doesn't go away while
01947     // we're cloning it.
01948     AUTO_MARK_JSVAL(inner_cc, funval);
01949 
01950     // clone a function we can use for this object
01951     JSObject* funobj = xpc_CloneJSFunction(inner_cc, JSVAL_TO_OBJECT(funval),
01952                                            wrapper->GetFlatJSObject());
01953     if(!funobj)
01954         return NS_ERROR_XPC_BAD_CONVERT_JS;
01955 
01956     // return the function and let xpconnect know we did so
01957     *retval = OBJECT_TO_JSVAL(funobj);
01958     cc->SetReturnValueWasSet(PR_TRUE);
01959 
01960     return NS_OK;
01961 }
01962 
01963 /* void reportError (); */
01964 NS_IMETHODIMP
01965 nsXPCComponents_Utils::ReportError()
01966 {
01967     // This function shall never fail! Silently eat any failure conditions.
01968     nsresult rv;
01969 
01970     nsCOMPtr<nsIConsoleService> console(
01971       do_GetService(NS_CONSOLESERVICE_CONTRACTID));
01972 
01973     nsCOMPtr<nsIScriptError> scripterr(new nsScriptError());
01974 
01975     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
01976     if(!scripterr || !console || !xpc)
01977         return NS_OK;
01978 
01979     // get the xpconnect native call context
01980     nsCOMPtr<nsIXPCNativeCallContext> cc;
01981     xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
01982     if(!cc)
01983         return NS_OK;
01984 
01985 // Check disabled until deprecated Components.reportError removed.
01986 #undef CHECK_FOR_INDIRECT_CALL
01987 #ifdef CHECK_FOR_INDIRECT_CALL
01988     // verify that we are being called from JS (i.e. the current call is
01989     // to this object - though we don't verify that it is to this exact method)
01990     nsCOMPtr<nsISupports> callee;
01991     cc->GetCallee(getter_AddRefs(callee));
01992     if(!callee || callee.get() !=
01993                   NS_STATIC_CAST(const nsISupports*,
01994                                  NS_STATIC_CAST(const nsIXPCComponents_Utils*,this))) {
01995         NS_ERROR("reportError() must only be called from JS!");
01996         return NS_ERROR_FAILURE;
01997     }
01998 #endif
01999 
02000     // Get JSContext of current call
02001     JSContext* cx;
02002     rv = cc->GetJSContext(&cx);
02003     if(NS_FAILED(rv) || !cx)
02004         return NS_OK;
02005 
02006     // get argc and argv and verify arg count
02007     PRUint32 argc;
02008     rv = cc->GetArgc(&argc);
02009     if(NS_FAILED(rv))
02010         return NS_OK;
02011 
02012     if(argc < 1)
02013         return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
02014 
02015     jsval* argv;
02016     rv = cc->GetArgvPtr(&argv);
02017     if(NS_FAILED(rv) || !argv)
02018         return NS_OK;
02019 
02020     JSErrorReport* err = JS_ErrorFromException(cx, argv[0]);
02021     if(err)
02022     {
02023         // It's a proper JS Error
02024         nsAutoString fileUni;
02025         CopyUTF8toUTF16(err->filename, fileUni);
02026 
02027         PRUint32 column = err->uctokenptr - err->uclinebuf;
02028 
02029         rv = scripterr->Init(NS_REINTERPRET_CAST(const PRUnichar*,
02030                                                  err->ucmessage),
02031                              fileUni.get(),
02032                              NS_REINTERPRET_CAST(const PRUnichar*,
02033                                                  err->uclinebuf),
02034                              err->lineno,
02035                              column,
02036                              err->flags,
02037                              "XPConnect JavaScript");
02038         if(NS_FAILED(rv))
02039             return NS_OK;
02040 
02041         console->LogMessage(scripterr);
02042         return NS_OK;
02043     }
02044 
02045     // It's not a JS Error object, so we synthesize as best we're able
02046     JSString* msgstr = JS_ValueToString(cx, argv[0]);
02047     if(msgstr)
02048     {
02049         // Root the string during scripterr->Init
02050         argv[0] = STRING_TO_JSVAL(msgstr);
02051 
02052         nsCOMPtr<nsIStackFrame> frame;
02053         nsXPConnect* xpc = nsXPConnect::GetXPConnect();
02054         if(xpc)
02055             xpc->GetCurrentJSStack(getter_AddRefs(frame));
02056 
02057         nsXPIDLCString fileName;
02058         PRInt32 lineNo = 0;
02059         if(frame)
02060         {
02061             frame->GetFilename(getter_Copies(fileName));
02062             frame->GetLineNumber(&lineNo);
02063         }
02064 
02065         rv = scripterr->Init(NS_REINTERPRET_CAST(const PRUnichar*,
02066                                                  JS_GetStringChars(msgstr)),
02067                              NS_ConvertUTF8toUTF16(fileName).get(),
02068                              nsnull,
02069                              lineNo, 0,
02070                              0, "XPConnect JavaScript");
02071         if(NS_SUCCEEDED(rv))
02072             console->LogMessage(scripterr);
02073     }
02074 
02075     return NS_OK;
02076 }
02077 
02078 #ifndef XPCONNECT_STANDALONE
02079 #include "nsIScriptSecurityManager.h"
02080 #include "nsIURL.h"
02081 #include "nsIStandardURL.h"
02082 #include "nsNetUtil.h"
02083 const char kScriptSecurityManagerContractID[] = NS_SCRIPTSECURITYMANAGER_CONTRACTID;
02084 const char kStandardURLContractID[] = "@mozilla.org/network/standard-url;1";
02085 
02086 #define PRINCIPALHOLDER_IID \
02087 {0xbf109f49, 0xf94a, 0x43d8, {0x93, 0xdb, 0xe4, 0x66, 0x49, 0xc5, 0xd9, 0x7d}}
02088 
02089 class PrincipalHolder : public nsIScriptObjectPrincipal
02090 {
02091 public:
02092     NS_DEFINE_STATIC_IID_ACCESSOR(PRINCIPALHOLDER_IID)
02093 
02094     PrincipalHolder(nsIPrincipal *holdee)
02095         : mHoldee(holdee)
02096     {
02097     }
02098     virtual ~PrincipalHolder() { }
02099 
02100     NS_DECL_ISUPPORTS
02101 
02102     nsIPrincipal *GetPrincipal();
02103 
02104 private:
02105     nsCOMPtr<nsIPrincipal> mHoldee;
02106 };
02107 
02108 NS_IMPL_ISUPPORTS1(PrincipalHolder, nsIScriptObjectPrincipal)
02109 
02110 nsIPrincipal *
02111 PrincipalHolder::GetPrincipal()
02112 {
02113     return mHoldee;
02114 }
02115 
02116 JS_STATIC_DLL_CALLBACK(JSBool)
02117 SandboxDump(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
02118 {
02119     JSString *str;
02120     if (!argc)
02121         return JS_TRUE;
02122 
02123     str = JS_ValueToString(cx, argv[0]);
02124     if (!str)
02125         return JS_FALSE;
02126 
02127     char *bytes = JS_GetStringBytes(str);
02128     if (!bytes)
02129         return JS_FALSE;
02130 
02131     fputs(bytes, stderr);
02132     return JS_TRUE;
02133 }
02134 
02135 JS_STATIC_DLL_CALLBACK(JSBool)
02136 SandboxDebug(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
02137 {
02138 #ifdef DEBUG
02139     return SandboxDump(cx, obj, argc, argv, rval);
02140 #else
02141     return JS_TRUE;
02142 #endif
02143 }
02144 
02145 JS_STATIC_DLL_CALLBACK(JSBool)
02146 SandboxFunForwarder(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
02147                     jsval *rval)
02148 {
02149     jsval v;
02150     if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &v) ||
02151         !JS_CallFunctionValue(cx, obj, v, argc, argv, rval)) {
02152         return JS_FALSE;
02153     }
02154 
02155     if (JSVAL_IS_PRIMITIVE(*rval))
02156         return JS_TRUE; // nothing more to do.
02157     
02158     XPCThrower::Throw(NS_ERROR_NOT_IMPLEMENTED, cx);
02159     return JS_FALSE;
02160 }
02161 
02162 JS_STATIC_DLL_CALLBACK(JSBool)
02163 SandboxImport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
02164               jsval *rval)
02165 {
02166     JSFunction *fun = JS_ValueToFunction(cx, argv[0]);
02167     if (!fun) {
02168         XPCThrower::Throw(NS_ERROR_INVALID_ARG, cx);
02169         return JS_FALSE;
02170     }
02171 
02172     JSString *funname;
02173     if (argc > 1) {
02174         // Use the second parameter as the function name.
02175         funname = JS_ValueToString(cx, argv[1]);
02176         if (!funname)
02177             return JS_FALSE;
02178         argv[1] = STRING_TO_JSVAL(funname);
02179     } else {
02180         // Use the actual function name as the name.
02181         funname = JS_GetFunctionId(fun);
02182         if (!funname) {
02183             XPCThrower::Throw(NS_ERROR_INVALID_ARG, cx);
02184             return JS_FALSE;
02185         }
02186     }
02187 
02188     nsresult rv = NS_ERROR_FAILURE;
02189     JSObject *oldfunobj = JS_GetFunctionObject(fun);
02190     nsXPConnect *xpc = nsXPConnect::GetXPConnect();
02191 
02192     if (xpc && oldfunobj) {
02193         nsIXPCSecurityManager *secman = xpc->GetDefaultSecurityManager();
02194         if (secman) {
02195             rv = secman->CanAccess(nsIXPCSecurityManager::ACCESS_CALL_METHOD,
02196                                    nsnull, cx, oldfunobj, nsnull, nsnull,
02197                                    STRING_TO_JSVAL(funname), nsnull);
02198         }
02199     }
02200 
02201     if (NS_FAILED(rv)) {
02202         if (rv == NS_ERROR_FAILURE)
02203             XPCThrower::Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
02204         return JS_FALSE;
02205     }
02206 
02207     JSFunction *newfun = JS_DefineUCFunction(cx, obj,
02208             JS_GetStringChars(funname), JS_GetStringLength(funname),
02209             SandboxFunForwarder, JS_GetFunctionArity(fun), 0);
02210 
02211     if (!newfun)
02212         return JS_FALSE;
02213 
02214     JSObject *newfunobj = JS_GetFunctionObject(newfun);
02215     if (!newfunobj)
02216         return JS_FALSE;
02217 
02218     // Functions come with two extra reserved slots on them. Use the 0-th slot
02219     // to communicate the wrapped function to our forwarder.
02220     return JS_SetReservedSlot(cx, newfunobj, 0, argv[0]);
02221 }
02222 
02223 JS_STATIC_DLL_CALLBACK(JSBool)
02224 sandbox_enumerate(JSContext *cx, JSObject *obj)
02225 {
02226     return JS_EnumerateStandardClasses(cx, obj);
02227 }
02228 
02229 JS_STATIC_DLL_CALLBACK(JSBool)
02230 sandbox_resolve(JSContext *cx, JSObject *obj, jsval id)
02231 {
02232     JSBool resolved;
02233     return JS_ResolveStandardClass(cx, obj, id, &resolved);
02234 }
02235 
02236 JS_STATIC_DLL_CALLBACK(void)
02237 sandbox_finalize(JSContext *cx, JSObject *obj)
02238 {
02239     nsIScriptObjectPrincipal *sop =
02240         (nsIScriptObjectPrincipal *)JS_GetPrivate(cx, obj);
02241     NS_IF_RELEASE(sop);
02242 }
02243 
02244 static JSClass SandboxClass = {
02245     "Sandbox", JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS,
02246     JS_PropertyStub,   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
02247     sandbox_enumerate, sandbox_resolve, JS_ConvertStub,  sandbox_finalize,
02248     JSCLASS_NO_OPTIONAL_MEMBERS
02249 };
02250 
02251 static JSFunctionSpec SandboxFunctions[] = {
02252     {"dump", SandboxDump, 1},
02253     {"debug", SandboxDebug, 1},
02254     {"importFunction", SandboxImport, 1},
02255     {0}
02256 };
02257 
02258 #endif /* !XPCONNECT_STANDALONE */
02259 
02260 /***************************************************************************/
02261 nsXPCComponents_utils_Sandbox::nsXPCComponents_utils_Sandbox()
02262 {
02263 }
02264 
02265 nsXPCComponents_utils_Sandbox::~nsXPCComponents_utils_Sandbox()
02266 {
02267 }
02268 
02269 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_utils_Sandbox)
02270   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_utils_Sandbox)
02271   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
02272   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_utils_Sandbox)
02273 NS_INTERFACE_MAP_END_THREADSAFE
02274 
02275 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_utils_Sandbox)
02276 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_utils_Sandbox)
02277 
02278 // We use the nsIXPScriptable macros to generate lots of stuff for us.
02279 #define XPC_MAP_CLASSNAME           nsXPCComponents_utils_Sandbox
02280 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_utils_Sandbox"
02281 #define                             XPC_MAP_WANT_CALL
02282 #define                             XPC_MAP_WANT_CONSTRUCT
02283 #define XPC_MAP_FLAGS               0
02284 #include "xpc_map_end.h" /* This #undef's the above. */
02285 
02286 #ifndef XPCONNECT_STANDALONE
02287 nsresult
02288 xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop)
02289 {
02290     // Create the sandbox global object
02291     nsresult rv;
02292     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
02293     if(NS_FAILED(rv))
02294         return NS_ERROR_XPC_UNEXPECTED;
02295 
02296     XPCAutoJSContext tempcx(JS_NewContext(JS_GetRuntime(cx), 1024), PR_FALSE);
02297     if (!tempcx)
02298         return NS_ERROR_OUT_OF_MEMORY;
02299 
02300     AutoJSRequestWithNoCallContext req(tempcx);
02301     JSObject *sandbox = JS_NewObject(tempcx, &SandboxClass, nsnull, nsnull);
02302     if (!sandbox)
02303         return NS_ERROR_XPC_UNEXPECTED;
02304 
02305     JS_SetGlobalObject(tempcx, sandbox);
02306 
02307     nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(prinOrSop));
02308 
02309     if (!sop) {
02310         nsCOMPtr<nsIPrincipal> principal(do_QueryInterface(prinOrSop));
02311 
02312         if (!principal) {
02313             // Create a mostly unique URI that has access to
02314             // nothing other itself.
02315             static PRBool doneSeed = PR_FALSE;
02316 
02317             if (!doneSeed) {
02318                 srand((int)(PR_Now() & 0xffffffff));
02319 
02320                 doneSeed = PR_TRUE;
02321             }
02322 
02323             char buf[128];
02324             sprintf(buf, "about:noaccess-%ul", rand());
02325 
02326             nsCOMPtr<nsIURI> uri;
02327             rv = NS_NewURI(getter_AddRefs(uri), buf);
02328             NS_ENSURE_SUCCESS(rv, rv);
02329 
02330             nsCOMPtr<nsIScriptSecurityManager> secman =
02331                 do_GetService(kScriptSecurityManagerContractID);
02332             NS_ENSURE_TRUE(secman, NS_ERROR_UNEXPECTED);
02333 
02334             rv = secman->GetCodebasePrincipal(uri, getter_AddRefs(principal));
02335 
02336             if (!principal || NS_FAILED(rv)) {
02337                 if (NS_SUCCEEDED(rv))
02338                     rv = NS_ERROR_FAILURE;
02339                 
02340                 return rv;
02341             }
02342         }
02343 
02344         sop = new PrincipalHolder(principal);
02345         if (!sop)
02346             return NS_ERROR_OUT_OF_MEMORY;
02347     }
02348 
02349     // Pass on ownership of sop to |sandbox|.
02350 
02351     {
02352         nsIScriptObjectPrincipal *tmp = sop;
02353 
02354         if (!JS_SetPrivate(cx, sandbox, tmp)) {
02355             return NS_ERROR_XPC_UNEXPECTED;
02356         }
02357 
02358         NS_ADDREF(tmp);
02359     }
02360 
02361     rv = xpc->InitClasses(cx, sandbox);
02362     if (NS_SUCCEEDED(rv) &&
02363         !JS_DefineFunctions(cx, sandbox, SandboxFunctions)) {
02364         rv = NS_ERROR_FAILURE;
02365     }
02366     if (NS_FAILED(rv))
02367         return NS_ERROR_XPC_UNEXPECTED;
02368 
02369     if (vp)
02370         *vp = OBJECT_TO_JSVAL(sandbox);
02371 
02372     return NS_OK;
02373 }
02374 #endif /* !XPCONNECT_STANDALONE */
02375 
02376 /* PRBool call(in nsIXPConnectWrappedNative wrapper,
02377                in JSContextPtr cx,
02378                in JSObjectPtr obj,
02379                in PRUint32 argc,
02380                in JSValPtr argv,
02381                in JSValPtr vp);
02382 */
02383 NS_IMETHODIMP
02384 nsXPCComponents_utils_Sandbox::Call(nsIXPConnectWrappedNative *wrapper,
02385                                     JSContext * cx,
02386                                     JSObject * obj,
02387                                     PRUint32 argc,
02388                                     jsval * argv,
02389                                     jsval * vp,
02390                                     PRBool *_retval)
02391 {
02392     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
02393 }
02394 
02395 /* PRBool construct(in nsIXPConnectWrappedNative wrapper,
02396                     in JSContextPtr cx,
02397                     in JSObjectPtr obj,
02398                     in PRUint32 argc,
02399                     in JSValPtr argv,
02400                     in JSValPtr vp);
02401 */
02402 NS_IMETHODIMP
02403 nsXPCComponents_utils_Sandbox::Construct(nsIXPConnectWrappedNative *wrapper,
02404                                          JSContext * cx,
02405                                          JSObject * obj,
02406                                          PRUint32 argc,
02407                                          jsval * argv,
02408                                          jsval * vp,
02409                                          PRBool *_retval)
02410 {
02411     return CallOrConstruct(wrapper, cx, obj, argc, argv, vp, _retval);
02412 }
02413 
02414 NS_IMETHODIMP
02415 nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
02416                                                JSContext * cx, JSObject * obj,
02417                                                PRUint32 argc, jsval * argv,
02418                                                jsval * vp, PRBool *_retval)
02419 {
02420 #ifdef XPCONNECT_STANDALONE
02421     return NS_ERROR_NOT_AVAILABLE;
02422 #else /* XPCONNECT_STANDALONE */
02423     if (argc < 1)
02424         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
02425 
02426     nsresult rv;
02427 
02428     // Make sure to set up principals on the sandbox before initing classes
02429     nsCOMPtr<nsIScriptObjectPrincipal> sop;
02430     nsCOMPtr<nsIPrincipal> principal;
02431     nsISupports *prinOrSop = nsnull;
02432     if (JSVAL_IS_STRING(argv[0])) {
02433         JSString *codebasestr = JSVAL_TO_STRING(argv[0]);
02434         nsCAutoString codebase(JS_GetStringBytes(codebasestr),
02435                                JS_GetStringLength(codebasestr));
02436         nsCOMPtr<nsIURL> iURL;
02437         nsCOMPtr<nsIStandardURL> stdUrl =
02438             do_CreateInstance(kStandardURLContractID, &rv);
02439         if (!stdUrl ||
02440             NS_FAILED(rv = stdUrl->Init(nsIStandardURL::URLTYPE_STANDARD, 80,
02441                                         codebase, nsnull, nsnull)) ||
02442             !(iURL = do_QueryInterface(stdUrl, &rv))) {
02443             if (NS_SUCCEEDED(rv))
02444                 rv = NS_ERROR_FAILURE;
02445             return ThrowAndFail(rv, cx, _retval);
02446         }
02447 
02448         nsCOMPtr<nsIScriptSecurityManager> secman =
02449             do_GetService(kScriptSecurityManagerContractID);
02450         if (!secman ||
02451             NS_FAILED(rv = secman->GetCodebasePrincipal(iURL, getter_AddRefs(principal))) ||
02452             !principal) {
02453             if (NS_SUCCEEDED(rv))
02454                 rv = NS_ERROR_FAILURE;
02455             return ThrowAndFail(rv, cx, _retval);
02456         }
02457 
02458         prinOrSop = principal;
02459     } else {
02460         if (!JSVAL_IS_PRIMITIVE(argv[0])) {
02461             nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
02462             if(!xpc)
02463                 return NS_ERROR_XPC_UNEXPECTED;
02464             nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
02465             xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(argv[0]),
02466                                             getter_AddRefs(wrapper));
02467 
02468             if (wrapper) {
02469                 sop = do_QueryWrappedNative(wrapper);
02470 
02471                 prinOrSop = sop;
02472             }
02473         }
02474 
02475         if (!prinOrSop)
02476             return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
02477     }
02478 
02479     rv = xpc_CreateSandboxObject(cx, vp, prinOrSop);
02480 
02481     if (NS_FAILED(rv)) {
02482         return ThrowAndFail(rv, cx, _retval);
02483     }
02484 
02485     *_retval = PR_TRUE;
02486 
02487     return rv;
02488 #endif /* XPCONNECT_STANDALONE */
02489 }
02490 
02491 
02492 /*
02493  * Throw an exception on caller_cx that is made from message and report,
02494  * which were reported as uncaught on cx.
02495  */
02496 static void
02497 SandboxErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
02498 
02499 class ContextHolder : public nsISupports
02500 {
02501 public:
02502     ContextHolder(JSContext *aOuterCx, JSObject *aSandbox);
02503 
02504     JSContext *GetJSContext()
02505     {
02506         return mJSContext;
02507     }
02508     JSContext *GetOuterContext()
02509     {
02510         NS_ASSERTION(mOuterContext, "GetOuterContext called late");
02511         return mOuterContext;
02512     }
02513 
02514     void DidEval()
02515     {
02516         JS_SetErrorReporter(mJSContext, nsnull);
02517         mOuterContext = nsnull;
02518     }
02519 
02520     NS_DECL_ISUPPORTS
02521 
02522 private:
02523     static JSBool JS_DLL_CALLBACK ContextHolderBranchCallback(JSContext *cx,
02524                                                               JSScript *script);
02525     
02526     XPCAutoJSContext mJSContext;
02527     JSBranchCallback mOrigBranchCallback;
02528     JSContext *mOuterContext;
02529 };
02530 
02531 NS_IMPL_ISUPPORTS0(ContextHolder)
02532 
02533 ContextHolder::ContextHolder(JSContext *aOuterCx, JSObject *aSandbox)
02534     : mJSContext(JS_NewContext(JS_GetRuntime(aOuterCx), 1024), JS_FALSE),
02535       mOrigBranchCallback(nsnull),
02536       mOuterContext(aOuterCx)
02537 {
02538     if (mJSContext) {
02539         JS_SetOptions(mJSContext, JSOPTION_PRIVATE_IS_NSISUPPORTS);
02540         JS_SetGlobalObject(mJSContext, aSandbox);
02541         JS_SetContextPrivate(mJSContext, this);
02542         JS_SetErrorReporter(mJSContext, SandboxErrorReporter);
02543 
02544         // Now cache the original branch callback
02545         mOrigBranchCallback = JS_SetBranchCallback(aOuterCx, nsnull);
02546         JS_SetBranchCallback(aOuterCx, mOrigBranchCallback);
02547 
02548         if (mOrigBranchCallback) {
02549             JS_SetBranchCallback(mJSContext, ContextHolderBranchCallback);
02550         }
02551     }
02552 }
02553 
02554 JSBool JS_DLL_CALLBACK
02555 ContextHolder::ContextHolderBranchCallback(JSContext *cx, JSScript *script)
02556 {
02557     ContextHolder* thisObject =
02558         NS_STATIC_CAST(ContextHolder*, JS_GetContextPrivate(cx));
02559     NS_ASSERTION(thisObject, "How did that happen?");
02560 
02561     if (thisObject->mOrigBranchCallback) {
02562         return (thisObject->mOrigBranchCallback)(thisObject->mOuterContext,
02563                                                  script);
02564     }
02565 
02566     return JS_TRUE;
02567 }
02568 
02569 static void
02570 SandboxErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
02571 {
02572     ContextHolder *ch = NS_STATIC_CAST(ContextHolder*, JS_GetContextPrivate(cx));
02573     JS_ThrowReportedError(ch->GetOuterContext(), message, report);
02574 }
02575 
02576 /***************************************************************************/
02577 
02578 /* void evalInSandbox(in AString source, in nativeobj sandbox); */
02579 NS_IMETHODIMP
02580 nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
02581 {
02582 #ifdef XPCONNECT_STANDALONE
02583     return NS_ERROR_NOT_AVAILABLE;
02584 #else /* XPCONNECT_STANDALONE */
02585     nsresult rv;
02586 
02587     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
02588     if(NS_FAILED(rv))
02589         return rv;
02590 
02591     // get the xpconnect native call context
02592     nsCOMPtr<nsIXPCNativeCallContext> cc;
02593     xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
02594     if(!cc)
02595         return NS_ERROR_FAILURE;
02596 
02597     // Get JSContext of current call
02598     JSContext* cx;
02599     rv = cc->GetJSContext(&cx);
02600     if(NS_FAILED(rv) || !cx)
02601         return NS_ERROR_FAILURE;
02602 
02603     // get place for return value
02604     jsval *rval = nsnull;
02605     rv = cc->GetRetValPtr(&rval);
02606     if(NS_FAILED(rv) || !rval)
02607         return NS_ERROR_FAILURE;
02608 
02609     // get argc and argv and verify arg count
02610     PRUint32 argc;
02611     rv = cc->GetArgc(&argc);
02612     if(NS_FAILED(rv))
02613         return rv;
02614 
02615     if (argc < 2)
02616         return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
02617 
02618     // The second argument is the sandbox object. It is required.
02619     jsval *argv;
02620     rv = cc->GetArgvPtr(&argv);
02621     if (NS_FAILED(rv))
02622         return rv;
02623     if (JSVAL_IS_PRIMITIVE(argv[1]))
02624         return NS_ERROR_INVALID_ARG;
02625     JSObject *sandbox = JSVAL_TO_OBJECT(argv[1]);
02626 
02627     // Get the current source info from xpc.
02628     nsXPIDLCString filename;
02629     PRInt32 lineNo = 0;
02630     {
02631         nsCOMPtr<nsIStackFrame> frame;
02632         xpc->GetCurrentJSStack(getter_AddRefs(frame));
02633         if (frame) {
02634             frame->GetFilename(getter_Copies(filename));
02635             frame->GetLineNumber(&lineNo);
02636         }
02637     }
02638 
02639     rv = xpc_EvalInSandbox(cx, sandbox, source, filename.get(), lineNo,
02640                            PR_FALSE, rval);
02641 
02642     if (NS_SUCCEEDED(rv)) {
02643         if (JS_IsExceptionPending(cx)) {
02644             cc->SetExceptionWasThrown(PR_TRUE);
02645         } else {
02646             cc->SetReturnValueWasSet(PR_TRUE);
02647         }
02648     }
02649 
02650     return rv;
02651 #endif /* XPCONNECT_STANDALONE */
02652 }
02653 
02654 #ifndef XPCONNECT_STANDALONE
02655 nsresult
02656 xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
02657                   const char *filename, PRInt32 lineNo,
02658                   PRBool returnStringOnly, jsval *rval)
02659 {
02660     if (JS_GetClass(cx, sandbox) != &SandboxClass)
02661         return NS_ERROR_INVALID_ARG;
02662 
02663     nsIScriptObjectPrincipal *sop =
02664         (nsIScriptObjectPrincipal*)JS_GetPrivate(cx, sandbox);
02665     NS_ASSERTION(sop, "Invalid sandbox passed");
02666     nsCOMPtr<nsIPrincipal> prin = sop->GetPrincipal();
02667 
02668     JSPrincipals *jsPrincipals;
02669 
02670     if (!prin ||
02671         NS_FAILED(prin->GetJSPrincipals(cx, &jsPrincipals)) ||
02672         !jsPrincipals) {
02673         return NS_ERROR_FAILURE;
02674     }
02675 
02676     nsRefPtr<ContextHolder> sandcx = new ContextHolder(cx, sandbox);
02677     if(!sandcx || !sandcx->GetJSContext()) {
02678         JS_ReportError(cx, "Can't prepare context for evalInSandbox");
02679         JSPRINCIPALS_DROP(cx, jsPrincipals);
02680         return NS_ERROR_OUT_OF_MEMORY;
02681     }
02682 
02683     XPCPerThreadData *data = XPCPerThreadData::GetData();
02684     XPCJSContextStack *stack = nsnull;
02685     if (data && (stack = data->GetJSContextStack())) {
02686         if (NS_FAILED(stack->Push(sandcx->GetJSContext()))) {
02687             JS_ReportError(cx,
02688                     "Unable to initialize XPConnect with the sandbox context");
02689             JSPRINCIPALS_DROP(cx, jsPrincipals);
02690             return NS_ERROR_FAILURE;
02691         }
02692     }
02693 
02694 
02695     // Push a fake frame onto sandcx so that we can properly propagate uncaught
02696     // exceptions.
02697     JSStackFrame frame;
02698     memset(&frame, 0, sizeof frame);
02699 
02700     sandcx->GetJSContext()->fp = &frame;
02701 
02702     if (!filename) {
02703         // Default the filename to the codebase.
02704         filename = jsPrincipals->codebase;
02705         lineNo = 1;
02706     }
02707 
02708     nsresult rv = NS_OK;
02709 
02710     JSString *str = nsnull;
02711     if (!JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox,
02712                                           jsPrincipals,
02713                                           NS_REINTERPRET_CAST(const jschar *,
02714                                               PromiseFlatString(source).get()),
02715                                           source.Length(), filename, lineNo,
02716                                           rval) ||
02717         (returnStringOnly &&
02718          !JSVAL_IS_VOID(*rval) &&
02719          !(str = JS_ValueToString(sandcx->GetJSContext(), *rval)))) {
02720         jsval exn;
02721         if (JS_GetPendingException(sandcx->GetJSContext(), &exn)) {
02722             // Stash the exception in |cx| so we can execute code on
02723             // sandcx without a pending exception.
02724             JS_SetPendingException(cx, exn);
02725             JS_ClearPendingException(sandcx->GetJSContext());
02726             if (returnStringOnly) {
02727                 // The caller asked for strings only, convert the
02728                 // exception into a string.
02729                 str = JS_ValueToString(sandcx->GetJSContext(), exn);
02730 
02731                 if (str) {
02732                     // We converted the exception to a string. Use that
02733                     // as the value exception.
02734                     JS_SetPendingException(cx, STRING_TO_JSVAL(str));
02735                 } else {
02736                     JS_ClearPendingException(cx);
02737                     rv = NS_ERROR_FAILURE;
02738                 }
02739             }
02740 
02741             // Clear str so we don't confuse callers.
02742             str = nsnull;
02743         } else {
02744             rv = NS_ERROR_OUT_OF_MEMORY;
02745         }
02746     }
02747 
02748     if (str) {
02749         *rval = STRING_TO_JSVAL(str);
02750     }
02751 
02752     if (stack) {
02753         stack->Pop(nsnull);
02754     }
02755 
02756     NS_ASSERTION(sandcx->GetJSContext()->fp == &frame, "Dangling frame");
02757     sandcx->GetJSContext()->fp = NULL;
02758 
02759     sandcx->DidEval();
02760 
02761     JSPRINCIPALS_DROP(cx, jsPrincipals);
02762 
02763     return rv;
02764 }
02765 #endif /* !XPCONNECT_STANDALONE */
02766 
02767 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
02768 /* string canCreateWrapper (in nsIIDPtr iid); */
02769 NS_IMETHODIMP
02770 nsXPCComponents_Utils::CanCreateWrapper(const nsIID * iid, char **_retval)
02771 {
02772     // We let anyone do this...
02773     *_retval = xpc_CloneAllAccess();
02774     return NS_OK;
02775 }
02776 
02777 /* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
02778 NS_IMETHODIMP
02779 nsXPCComponents_Utils::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
02780 {
02781     static const char* allowed[] = { "lookupMethod", "evalInSandbox", nsnull };
02782     *_retval = xpc_CheckAccessList(methodName, allowed);
02783     return NS_OK;
02784 }
02785 
02786 /* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
02787 NS_IMETHODIMP
02788 nsXPCComponents_Utils::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
02789 {
02790     *_retval = nsnull;
02791     return NS_OK;
02792 }
02793 
02794 /* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
02795 NS_IMETHODIMP
02796 nsXPCComponents_Utils::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
02797 {
02798     // If you have to ask, then the answer is NO
02799     *_retval = nsnull;
02800     return NS_OK;
02801 }
02802 #endif
02803 
02804 /***************************************************************************/
02805 /***************************************************************************/
02806 /***************************************************************************/
02807 
02808 // XXXjband We ought to cache the wrapper in the object's slots rather than
02809 // re-wrapping on demand
02810 
02811 NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
02812   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
02813   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
02814 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
02815   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
02816 #endif
02817   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents)
02818 NS_INTERFACE_MAP_END_THREADSAFE
02819 
02820 NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents)
02821 NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents)
02822 
02823 nsXPCComponents::nsXPCComponents()
02824     :   mInterfaces(nsnull),
02825         mInterfacesByID(nsnull),
02826         mClasses(nsnull),
02827         mClassesByID(nsnull),
02828         mResults(nsnull),
02829         mID(nsnull),
02830         mException(nsnull),
02831         mConstructor(nsnull),
02832         mUtils(nsnull)
02833 {
02834 }
02835 
02836 nsXPCComponents::~nsXPCComponents()
02837 {
02838     ClearMembers();
02839 }
02840 
02841 void
02842 nsXPCComponents::ClearMembers()
02843 {
02844     NS_IF_RELEASE(mInterfaces);
02845     NS_IF_RELEASE(mInterfacesByID);
02846     NS_IF_RELEASE(mClasses);
02847     NS_IF_RELEASE(mClassesByID);
02848     NS_IF_RELEASE(mResults);
02849     NS_IF_RELEASE(mID);
02850     NS_IF_RELEASE(mException);
02851     NS_IF_RELEASE(mConstructor);
02852     NS_IF_RELEASE(mUtils);
02853 }
02854 
02855 /*******************************************/
02856 #define XPC_IMPL_GET_OBJ_METHOD(_b, _n) \
02857 NS_IMETHODIMP nsXPCComponents::Get##_n(_b##_n * *a##_n) { \
02858     NS_ENSURE_ARG_POINTER(a##_n); \
02859     if(!m##_n) { \
02860         if(!(m##_n = new nsXPCComponents_##_n())) { \
02861             *a##_n = nsnull; \
02862             return NS_ERROR_OUT_OF_MEMORY; \
02863         } \
02864         NS_ADDREF(m##_n); \
02865     } \
02866     NS_ADDREF(m##_n); \
02867     *a##_n = m##_n; \
02868     return NS_OK; \
02869 }
02870 
02871 XPC_IMPL_GET_OBJ_METHOD(nsIScriptable,     Interfaces)
02872 XPC_IMPL_GET_OBJ_METHOD(nsIScriptable,     InterfacesByID)
02873 XPC_IMPL_GET_OBJ_METHOD(nsIXPCComponents_, Classes)
02874 XPC_IMPL_GET_OBJ_METHOD(nsIXPCComponents_, ClassesByID)
02875 XPC_IMPL_GET_OBJ_METHOD(nsIXPCComponents_, Results)
02876 XPC_IMPL_GET_OBJ_METHOD(nsIXPCComponents_, ID)
02877 XPC_IMPL_GET_OBJ_METHOD(nsIXPCComponents_, Exception)
02878 XPC_IMPL_GET_OBJ_METHOD(nsIXPCComponents_, Constructor)
02879 XPC_IMPL_GET_OBJ_METHOD(nsIXPCComponents_, Utils)
02880 
02881 #undef XPC_IMPL_GET_OBJ_METHOD
02882 /*******************************************/
02883 
02884 NS_IMETHODIMP
02885 nsXPCComponents::IsSuccessCode(nsresult result, PRBool *out)
02886 {
02887     *out = NS_SUCCEEDED(result);
02888     return NS_OK;
02889 }
02890 
02891 NS_IMETHODIMP
02892 nsXPCComponents::GetStack(nsIStackFrame * *aStack)
02893 {
02894     nsresult rv;
02895     nsXPConnect* xpc = nsXPConnect::GetXPConnect();
02896     if(!xpc)
02897         return NS_ERROR_FAILURE;
02898     rv = xpc->GetCurrentJSStack(aStack);
02899     return rv;
02900 }
02901 
02902 NS_IMETHODIMP
02903 nsXPCComponents::GetManager(nsIComponentManager * *aManager)
02904 {
02905     NS_ASSERTION(aManager, "bad param");
02906     return NS_GetComponentManager(aManager);
02907 }
02908 
02909 /**********************************************/
02910 
02911 // The nsIXPCScriptable map declaration that will generate stubs for us...
02912 #define XPC_MAP_CLASSNAME           nsXPCComponents
02913 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents"
02914 #define                             XPC_MAP_WANT_NEWRESOLVE
02915 #define                             XPC_MAP_WANT_GETPROPERTY
02916 #define                             XPC_MAP_WANT_SETPROPERTY
02917 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
02918 #include "xpc_map_end.h" /* This will #undef the above */
02919 
02920 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
02921 NS_IMETHODIMP
02922 nsXPCComponents::NewResolve(nsIXPConnectWrappedNative *wrapper,
02923                             JSContext * cx, JSObject * obj,
02924                             jsval id, PRUint32 flags,
02925                             JSObject * *objp, PRBool *_retval)
02926 {
02927     XPCJSRuntime* rt = nsXPConnect::GetRuntime();
02928     if(!rt)
02929         return NS_ERROR_FAILURE;
02930 
02931     jsid idid;
02932     uintN attrs = 0;
02933 
02934     if(id == rt->GetStringJSVal(XPCJSRuntime::IDX_LAST_RESULT))
02935     {
02936         idid = rt->GetStringID(XPCJSRuntime::IDX_LAST_RESULT);
02937         attrs = JSPROP_READONLY;
02938     }
02939     else if(id == rt->GetStringJSVal(XPCJSRuntime::IDX_RETURN_CODE))
02940         idid = rt->GetStringID(XPCJSRuntime::IDX_RETURN_CODE);
02941     else
02942         return NS_OK;
02943 
02944     *objp = obj;
02945     *_retval = OBJ_DEFINE_PROPERTY(cx, obj, idid, JSVAL_VOID,
02946                                    nsnull, nsnull,
02947                                    JSPROP_ENUMERATE | JSPROP_PERMANENT | attrs,
02948                                    nsnull);
02949     return NS_OK;
02950 }
02951 
02952 /* PRBool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
02953 NS_IMETHODIMP
02954 nsXPCComponents::GetProperty(nsIXPConnectWrappedNative *wrapper,
02955                              JSContext * cx, JSObject * obj,
02956                              jsval id, jsval * vp, PRBool *_retval)
02957 {
02958     XPCContext* xpcc = nsXPConnect::GetContext(cx);
02959     if(!xpcc)
02960         return NS_ERROR_FAILURE;
02961 
02962     PRBool doResult = JS_FALSE;
02963     nsresult res;
02964     XPCJSRuntime* rt = xpcc->GetRuntime();
02965     if(id == rt->GetStringJSVal(XPCJSRuntime::IDX_LAST_RESULT))
02966     {
02967         res = xpcc->GetLastResult();
02968         doResult = JS_TRUE;
02969     }
02970     else if(id == rt->GetStringJSVal(XPCJSRuntime::IDX_RETURN_CODE))
02971     {
02972         res = xpcc->GetPendingResult();
02973         doResult = JS_TRUE;
02974     }
02975 
02976     nsresult rv = NS_OK;
02977     if(doResult)
02978     {
02979         if(!JS_NewNumberValue(cx, (jsdouble) res, vp))
02980             return NS_ERROR_OUT_OF_MEMORY;
02981         rv = NS_SUCCESS_I_DID_SOMETHING;
02982     }
02983 
02984     return rv;
02985 }
02986 
02987 /* PRBool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
02988 NS_IMETHODIMP
02989 nsXPCComponents::SetProperty(nsIXPConnectWrappedNative *wrapper,
02990                              JSContext * cx, JSObject * obj, jsval id,
02991                              jsval * vp, PRBool *_retval)
02992 {
02993     XPCContext* xpcc = nsXPConnect::GetContext(cx);
02994     if(!xpcc)
02995         return NS_ERROR_FAILURE;
02996 
02997     XPCJSRuntime* rt = xpcc->GetRuntime();
02998     if(!rt)
02999         return NS_ERROR_FAILURE;
03000 
03001     if(id == rt->GetStringJSVal(XPCJSRuntime::IDX_RETURN_CODE))
03002     {
03003         nsresult rv;
03004         if(JS_ValueToECMAUint32(cx, *vp, (uint32*)&rv))
03005         {
03006             xpcc->SetPendingResult(rv);
03007             xpcc->SetLastResult(rv);
03008             return NS_SUCCESS_I_DID_SOMETHING;
03009         }
03010         return NS_ERROR_FAILURE;
03011     }
03012 
03013     return NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN;
03014 }
03015 
03016 // static
03017 JSBool
03018 nsXPCComponents::AttachNewComponentsObject(XPCCallContext& ccx,
03019                                            XPCWrappedNativeScope* aScope,
03020                                            JSObject* aGlobal)
03021 {
03022     if(!aGlobal)
03023         return JS_FALSE;
03024 
03025     nsXPCComponents* components = new nsXPCComponents();
03026     if(!components)
03027         return JS_FALSE;
03028 
03029     nsCOMPtr<nsIXPCComponents> cholder(components);
03030 
03031     AutoMarkingNativeInterfacePtr iface(ccx);
03032     iface = XPCNativeInterface::GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCComponents));
03033 
03034     if(!iface)
03035         return JS_FALSE;
03036 
03037     nsCOMPtr<XPCWrappedNative> wrapper;
03038     XPCWrappedNative::GetNewOrUsed(ccx, cholder, aScope, iface,
03039                                    OBJ_IS_NOT_GLOBAL, getter_AddRefs(wrapper));
03040     if(!wrapper)
03041         return JS_FALSE;
03042 
03043     aScope->SetComponents(components);
03044 
03045     jsid id = ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_COMPONENTS);
03046     JSObject* obj;
03047 
03048     return NS_SUCCEEDED(wrapper->GetJSObject(&obj)) &&
03049            obj && OBJ_DEFINE_PROPERTY(ccx,
03050                                       aGlobal, id, OBJECT_TO_JSVAL(obj),
03051                                       nsnull, nsnull,
03052                                       JSPROP_PERMANENT | JSPROP_READONLY,
03053                                       nsnull);
03054 }
03055 
03056 /* void lookupMethod (); */
03057 NS_IMETHODIMP nsXPCComponents::LookupMethod()
03058 {
03059     nsresult rv;
03060     nsCOMPtr<nsIXPCComponents_Utils> utils;
03061 
03062     NS_WARNING("Components.lookupMethod deprecated, use Components.utils.lookupMethod");
03063     rv = GetUtils(getter_AddRefs(utils));
03064     if (NS_FAILED(rv))
03065         return rv;
03066 
03067     return utils->LookupMethod();
03068 }
03069 
03070 /* void reportError (); */
03071 NS_IMETHODIMP nsXPCComponents::ReportError()
03072 {
03073     nsresult rv;
03074     nsCOMPtr<nsIXPCComponents_Utils> utils;
03075 
03076     NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
03077     rv = GetUtils(getter_AddRefs(utils));
03078     if (NS_FAILED(rv))
03079         return rv;
03080 
03081     return utils->ReportError();
03082 }
03083 
03084 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
03085 /* string canCreateWrapper (in nsIIDPtr iid); */
03086 NS_IMETHODIMP
03087 nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval)
03088 {
03089     // We let anyone do this...
03090     *_retval = xpc_CloneAllAccess();
03091     return NS_OK;
03092 }
03093 
03094 /* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
03095 NS_IMETHODIMP
03096 nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
03097 {
03098     static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
03099     *_retval = xpc_CheckAccessList(methodName, allowed);
03100     return NS_OK;
03101 }
03102 
03103 /* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
03104 NS_IMETHODIMP
03105 nsXPCComponents::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
03106 {
03107     static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
03108     *_retval = xpc_CheckAccessList(propertyName, allowed);
03109     return NS_OK;
03110 }
03111 
03112 /* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
03113 NS_IMETHODIMP
03114 nsXPCComponents::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
03115 {
03116     // If you have to ask, then the answer is NO
03117     *_retval = nsnull;
03118     return NS_OK;
03119 }
03120 #endif