Back to index

lightning-sunbird  0.9+nobinonly
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes
XPCWrappedNative Class Reference

#include <xpcprivate.h>

Inheritance diagram for XPCWrappedNative:
Inheritance graph
[legend]
Collaboration diagram for XPCWrappedNative:
Collaboration graph
[legend]

List of all members.

Public Types

enum  CallMode { CALL_METHOD, CALL_GETTER, CALL_SETTER }

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
JSBool 
IsValid () const
JSBool HasProto () const
XPCWrappedNativeProtoGetProto () const
XPCWrappedNativeScopeGetScope () const
nsISupports * GetIdentityObject () const
JSObjectGetFlatJSObject () const
XPCLockGetLock () const
XPCNativeSetGetSet () const
XPCNativeScriptableInfoGetScriptableInfo () const
nsIXPCScriptableGetScriptableCallback () const
void ** GetSecurityInfoAddr ()
nsIClassInfoGetClassInfo () const
JSBool HasSharedProto () const
JSBool HasMutatedSet () const
XPCJSRuntimeGetRuntime () const
void FlatJSObjectFinalized (JSContext *cx, JSObject *obj)
void SystemIsBeingShutDown (XPCCallContext &ccx)
JSBool HasInterfaceNoQI (XPCNativeInterface *aInterface)
JSBool HasInterfaceNoQI (const nsIID &iid)
XPCWrappedNativeTearOffLocateTearOff (XPCCallContext &ccx, XPCNativeInterface *aInterface)
XPCWrappedNativeTearOffFindTearOff (XPCCallContext &ccx, XPCNativeInterface *aInterface, JSBool needJSObject=JS_FALSE, nsresult *pError=nsnull)
void Mark () const
void MarkBeforeJSFinalize (JSContext *cx)
void AutoMark (JSContext *cx)
void SweepTearOffs ()
char * ToString (XPCCallContext &ccx, XPCWrappedNativeTearOff *to=nsnull) const
JSBool HasExternalReference () const
JSObjectGetNativeWrapper ()
void SetNativeWrapper (JSObject *obj)
nsISupports * Native () const
 Faster access to the native object from C++.
nsIInterfaceInfo FindInterfaceWithMember (in JSVal nameID)
nsIInterfaceInfo FindInterfaceWithName (in JSVal nameID)
void debugDump (in short depth)
void refreshPrototype ()
voidPtrPtr GetSecurityInfoAddress ()

Static Public Member Functions

static JSBool IsTaggedScope (XPCWrappedNativeScope *s)
static XPCWrappedNativeScopeTagScope (XPCWrappedNativeScope *s)
static XPCWrappedNativeScopeUnTagScope (XPCWrappedNativeScope *s)
static nsresult GetNewOrUsed (XPCCallContext &ccx, nsISupports *Object, XPCWrappedNativeScope *Scope, XPCNativeInterface *Interface, JSBool isGlobal, XPCWrappedNative **wrapper)
static nsresult GetUsedOnly (XPCCallContext &ccx, nsISupports *Object, XPCWrappedNativeScope *Scope, XPCNativeInterface *Interface, XPCWrappedNative **wrapper)
static XPCWrappedNativeGetWrappedNativeOfJSObject (JSContext *cx, JSObject *obj, JSObject *funobj=nsnull, JSObject **pobj2=nsnull, XPCWrappedNativeTearOff **pTearOff=nsnull)
static nsresult ReparentWrapperIfFound (XPCCallContext &ccx, XPCWrappedNativeScope *aOldScope, XPCWrappedNativeScope *aNewScope, JSObject *aNewParent, nsISupports *aCOMObj, XPCWrappedNative **aWrapper)
static JSBool CallMethod (XPCCallContext &ccx, CallMode mode=CALL_METHOD)
static JSBool GetAttribute (XPCCallContext &ccx)
static JSBool SetAttribute (XPCCallContext &ccx)
static nsresult GatherProtoScriptableCreateInfo (nsIClassInfo *classInfo, XPCNativeScriptableCreateInfo *sciProto)
static nsresult GatherScriptableCreateInfo (nsISupports *obj, nsIClassInfo *classInfo, XPCNativeScriptableCreateInfo *sciProto, XPCNativeScriptableCreateInfo *sciWrapper)

Public Attributes

readonly attribute nsISupports Native
readonly attribute JSObjectPtr JSObjectPrototype
readonly attribute nsIXPConnect XPConnect
 These are here as an aid to nsIXPCScriptable implementors.
readonly attribute JSObjectPtr JSObject

Protected Member Functions

 XPCWrappedNative ()
 XPCWrappedNative (nsISupports *aIdentity, XPCWrappedNativeProto *aProto)
 XPCWrappedNative (nsISupports *aIdentity, XPCWrappedNativeScope *aScope, XPCNativeSet *aSet)
virtual ~XPCWrappedNative ()

Protected Attributes

nsISupports * mIdentity

Private Member Functions

void SetSet (XPCNativeSet *set)
JSBool Init (XPCCallContext &ccx, JSObject *parent, JSBool isGlobal, const XPCNativeScriptableCreateInfo *sci)
JSBool ExtendSet (XPCCallContext &ccx, XPCNativeInterface *aInterface)
nsresult InitTearOff (XPCCallContext &ccx, XPCWrappedNativeTearOff *aTearOff, XPCNativeInterface *aInterface, JSBool needJSObject)
JSBool InitTearOffJSObject (XPCCallContext &ccx, XPCWrappedNativeTearOff *to)

Private Attributes

union {
XPCWrappedNativeScopemMaybeScope
XPCWrappedNativeProtomMaybeProto
}; 
XPCNativeSetmSet
JSObjectmFlatJSObject
XPCNativeScriptableInfomScriptableInfo
XPCWrappedNativeTearOffChunk mFirstChunk
JSObjectmNativeWrapper

Detailed Description

Definition at line 1822 of file xpcprivate.h.


Member Enumeration Documentation

Enumerator:
CALL_METHOD 
CALL_GETTER 
CALL_SETTER 

Definition at line 1959 of file xpcprivate.h.


Constructor & Destructor Documentation

Here is the caller graph for this function:

XPCWrappedNative::XPCWrappedNative ( nsISupports *  aIdentity,
XPCWrappedNativeProto aProto 
) [protected]

Definition at line 539 of file xpcwrappednative.cpp.

    : mMaybeProto(aProto),
      mSet(aProto->GetSet()),
      mFlatJSObject((JSObject*)JSVAL_ONE), // non-null to pass IsValid() test
      mScriptableInfo(nsnull),
      mNativeWrapper(nsnull)
{
    NS_ADDREF(mIdentity = aIdentity);

    NS_ASSERTION(mMaybeProto, "bad ctor param");
    NS_ASSERTION(mSet, "bad ctor param");

    DEBUG_TrackNewWrapper(this);
}

Here is the call graph for this function:

XPCWrappedNative::XPCWrappedNative ( nsISupports *  aIdentity,
XPCWrappedNativeScope aScope,
XPCNativeSet aSet 
) [protected]

Definition at line 556 of file xpcwrappednative.cpp.

    : mMaybeScope(TagScope(aScope)),
      mSet(aSet),
      mFlatJSObject((JSObject*)JSVAL_ONE), // non-null to pass IsValid() test
      mScriptableInfo(nsnull),
      mNativeWrapper(nsnull)
{
    NS_ADDREF(mIdentity = aIdentity);

    NS_ASSERTION(aScope, "bad ctor param");
    NS_ASSERTION(aSet, "bad ctor param");

    DEBUG_TrackNewWrapper(this);
}

Here is the call graph for this function:

XPCWrappedNative::~XPCWrappedNative ( ) [protected, virtual]

Definition at line 574 of file xpcwrappednative.cpp.

{
    DEBUG_TrackDeleteWrapper(this);

    XPCWrappedNativeProto* proto = GetProto();

    if(mScriptableInfo &&
       (!HasProto() ||
        (proto && proto->GetScriptableInfo() != mScriptableInfo)))
    {
        delete mScriptableInfo;
    }

    Native2WrappedNativeMap* map = GetScope()->GetWrappedNativeMap();
    {   // scoped lock
        XPCAutoLock lock(GetRuntime()->GetMapLock());
        map->Remove(this);
    }

    if(mIdentity)
    {
        XPCJSRuntime* rt = GetRuntime();
        if(rt && rt->GetDeferReleases() && rt->GetDoingFinalization())
        {
            if(!rt->DeferredRelease(mIdentity))
            {
                NS_WARNING("Failed to append object for deferred release.");
                // XXX do we really want to do this???
                NS_RELEASE(mIdentity);
            }
        }
        else
        {
            NS_RELEASE(mIdentity);
        }
    }
}

Here is the call graph for this function:


Member Function Documentation

Definition at line 1998 of file xpcprivate.h.

    {
        // If this got called, we're being kept alive by someone who really
        // needs us alive and whole.  Do not let our mFlatJSObject go away.
        // This is the only time we should be marking our mFlatJSObject;
        // normally we just go away quietly when it does.  Be careful not to
        // mark the bogus JSVAL_ONE value we can have during init, though.
        if(mFlatJSObject && mFlatJSObject != (JSObject*)JSVAL_ONE)
        {
            ::JS_MarkGCThing(cx, mFlatJSObject,
                             "XPCWrappedNative::mFlatJSObject", nsnull);
        }
    }

Here is the call graph for this function:

Definition at line 1724 of file xpcwrappednative.cpp.

{
    NS_ASSERTION(ccx.GetXPCContext()->CallerTypeIsJavaScript(),
                 "Native caller for XPCWrappedNative::CallMethod?");
    
    nsresult rv = ccx.CanCallNow();
    if(NS_FAILED(rv))
    {
        // If the security manager is complaining then this is not really an
        // internal error in xpconnect. So, no reason to botch the assertion.
        NS_ASSERTION(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO, 
                     "hmm? CanCallNow failed in XPCWrappedNative::CallMethod. "
                     "We are finding out about this late!");
        return Throw(rv, ccx);
    }

    DEBUG_TrackWrapperCall(ccx.GetWrapper(), mode);

    // From here on ALL exits are through 'goto done;'

#define PARAM_BUFFER_COUNT     8

    nsXPTCVariant paramBuffer[PARAM_BUFFER_COUNT];

    // Number of nsAutoStrings to construct on the stack for use with method
    // calls that use 'out' AStrings (aka [domstring]). These can save us from 
    // a new/delete of an nsString. But the cost is that the ctor/dtor code 
    // is run for each nsAutoString in the array for each call - whether or not 
    // a specific call actually uses *any* AStrings. Also, we have these
    // large-ish nsAutoString objects using up stack space.
    //
    // Set this to zero to disable use of these auto strings.
#define PARAM_AUTOSTRING_COUNT     1

#if PARAM_AUTOSTRING_COUNT
    nsVoidableString autoStrings[PARAM_AUTOSTRING_COUNT];
    int autoStringIndex = 0;
#endif

    JSBool retval = JS_FALSE;

    nsXPTCVariant* dispatchParams = nsnull;
    uint8 i;
    const nsXPTMethodInfo* methodInfo;
    uint8 requiredArgs;
    uint8 paramCount;
    jsval src;
    nsresult invokeResult;
    nsID param_iid;
    uintN err;
    nsIXPCSecurityManager* sm;
    JSBool foundDependentParam;

    XPCJSRuntime* rt = ccx.GetRuntime();
    XPCContext* xpcc = ccx.GetXPCContext();
    nsISupports* callee = ccx.GetTearOff()->GetNative();
    XPCPerThreadData* tls = ccx.GetThreadData();
    uint16 vtblIndex = ccx.GetMethodIndex();
    nsIInterfaceInfo* ifaceInfo = ccx.GetInterface()->GetInterfaceInfo();
    jsval name = ccx.GetMember()->GetName();
    jsval* argv = ccx.GetArgv();

#ifdef DEBUG_stats_jband
    PRIntervalTime startTime = PR_IntervalNow();
    PRIntervalTime endTime = 0;
    static int totalTime = 0;
    static int count = 0;
    static const int interval = 10;
    if(0 == (++count % interval))
        printf(">>>>>>>> %d calls on XPCWrappedNatives made.  (%d)\n", count, PR_IntervalToMilliseconds(totalTime));
#endif

    ccx.SetRetVal(JSVAL_VOID);

    tls->SetException(nsnull);
    xpcc->SetLastResult(NS_ERROR_UNEXPECTED);

    // set up the method index and do the security check if needed

    PRUint32 secFlag;
    PRUint32 secAction;

    switch(mode)
    {
        case CALL_METHOD:
            secFlag   = nsIXPCSecurityManager::HOOK_CALL_METHOD;
            secAction = nsIXPCSecurityManager::ACCESS_CALL_METHOD;
            break;
        case CALL_GETTER:
            secFlag   = nsIXPCSecurityManager::HOOK_GET_PROPERTY;
            secAction = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
            break;
        case CALL_SETTER:
            secFlag   = nsIXPCSecurityManager::HOOK_SET_PROPERTY;
            secAction = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
            break;
        default:
            NS_ASSERTION(0,"bad value");
            goto done;
    }

    sm = xpcc->GetAppropriateSecurityManager(secFlag);
    if(sm && NS_FAILED(sm->CanAccess(secAction, &ccx, ccx,
                                     ccx.GetFlattenedJSObject(),
                                     ccx.GetWrapper()->GetIdentityObject(),
                                     ccx.GetWrapper()->GetClassInfo(), name,
                                     ccx.GetWrapper()->GetSecurityInfoAddr())))
    {
        // the security manager vetoed. It should have set an exception.
        goto done;
    }

    if(NS_FAILED(ifaceInfo->GetMethodInfo(vtblIndex, &methodInfo)))
    {
        Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, ccx);
        goto done;
    }

    // XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
    paramCount = methodInfo->GetParamCount();
    requiredArgs = paramCount;
    if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
        requiredArgs--;
    if(ccx.GetArgc() < requiredArgs)
    {
        Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
        goto done;
    }

    // setup variant array pointer
    if(paramCount > PARAM_BUFFER_COUNT)
    {
        if(!(dispatchParams = new nsXPTCVariant[paramCount]))
        {
            JS_ReportOutOfMemory(ccx);
            goto done;
        }
    }
    else
        dispatchParams = paramBuffer;

    // iterate through the params to clear flags (for safe cleanup later)
    for(i = 0; i < paramCount; i++)
    {
        nsXPTCVariant* dp = &dispatchParams[i];
        dp->ClearFlags();
        dp->val.p = nsnull;
    }

    // Iterate through the params doing conversions of independent params only.
    // When we later convert the dependent params (if any) we will know that
    // the params upon which they depend will have already been converted -
    // regardless of ordering.
    foundDependentParam = JS_FALSE;
    for(i = 0; i < paramCount; i++)
    {
        JSBool useAllocator = JS_FALSE;
        const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
        const nsXPTType& type = paramInfo.GetType();
        uint8 type_tag = type.TagPart();

        if(type.IsDependent())
        {
            foundDependentParam = JS_TRUE;
            continue;
        }

        nsXPTCVariant* dp = &dispatchParams[i];
        dp->type = type;

        if(type_tag == nsXPTType::T_INTERFACE)
        {
            dp->SetValIsInterface();
        }

        // set 'src' to be the object from which we get the value and
        // prepare for out param

        if(paramInfo.IsOut())
        {
            dp->SetPtrIsData();
            dp->ptr = &dp->val;

            if(!paramInfo.IsRetval() &&
               (JSVAL_IS_PRIMITIVE(argv[i]) ||
                !OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[i]),
                                  rt->GetStringID(XPCJSRuntime::IDX_VALUE),
                                  &src)))
            {
                ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, ccx);
                goto done;
            }

            if(type.IsPointer() &&
               type_tag != nsXPTType::T_INTERFACE &&
               !paramInfo.IsShared())
            {
                useAllocator = JS_TRUE;
                dp->SetValIsAllocated();
            }

            if(!paramInfo.IsIn())
                continue;
        }
        else
        {
            if(type.IsPointer())
            {
                switch(type_tag)
                {
                case nsXPTType::T_IID:
                    dp->SetValIsAllocated();
                    useAllocator = JS_TRUE;
                    break;

                case nsXPTType::T_ASTRING:
                    // Fall through to the T_DOMSTRING case

                case nsXPTType::T_DOMSTRING:
                    if(paramInfo.IsDipper())
                    {
                        // Is an 'out' DOMString. Make a new nsAString
                        // now and then continue in order to skip the call to
                        // JSData2Native

                        // If autoStrings array support is enabld, then use
                        // one of them if they are not already used up.
#if PARAM_AUTOSTRING_COUNT
                        if(autoStringIndex < PARAM_AUTOSTRING_COUNT)
                        {
                            // Don't call SetValIsDOMString because we don't 
                            // want to delete this pointer.
                            dp->val.p = &autoStrings[autoStringIndex++];
                            continue;
                        }
#endif
                        dp->SetValIsDOMString();
                        if(!(dp->val.p = new nsVoidableString()))
                        {
                            JS_ReportOutOfMemory(ccx);
                            goto done;
                        }
                        continue;
                    }
                    // else...

                    // Is an 'in' DOMString. Set 'useAllocator' to indicate
                    // that JSData2Native should allocate a new
                    // nsAString.
                    dp->SetValIsDOMString();
                    useAllocator = JS_TRUE;
                    break;

                case nsXPTType::T_UTF8STRING:                    
                    // Fall through to the C string case for now...                    
                case nsXPTType::T_CSTRING:                    
                    dp->SetValIsCString();
                    if(paramInfo.IsDipper())
                    {
                        // Is an 'out' CString.
                        if(!(dp->val.p = new nsCString()))
                        {
                            JS_ReportOutOfMemory(ccx);
                            goto done;
                        }
                        continue;
                    }
                    // else ...
                    // Is an 'in' CString.
                    useAllocator = JS_TRUE;
                    break;
                }
            }

            // Do this *after* the above because in the case where we have a
            // "T_DOMSTRING && IsDipper()" then argv might be null since this
            // is really an 'out' param masquerading as an 'in' param.
            src = argv[i];
        }

        if(type_tag == nsXPTType::T_INTERFACE &&
           NS_FAILED(ifaceInfo->GetIIDForParamNoAlloc(vtblIndex, &paramInfo,
                                               &param_iid)))
        {
            ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, i, ccx);
            goto done;
        }

        if(!XPCConvert::JSData2Native(ccx, &dp->val, src, type,
                                      useAllocator, &param_iid, &err))
        {
            ThrowBadParam(err, i, ccx);
            goto done;
        }
    }

    // if any params were dependent, then we must iterate again to convert them.
    if(foundDependentParam)
    {
        for(i = 0; i < paramCount; i++)
        {
            const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
            const nsXPTType& type = paramInfo.GetType();

            if(!type.IsDependent())
                continue;

            nsXPTType datum_type;
            JSUint32 array_count;
            JSUint32 array_capacity;
            JSBool useAllocator = JS_FALSE;
            PRBool isArray = type.IsArray();

            PRBool isSizedString = isArray ?
                    JS_FALSE :
                    type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
                    type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;

            nsXPTCVariant* dp = &dispatchParams[i];
            dp->type = type;

            if(isArray)
            {
                dp->SetValIsArray();

                if(NS_FAILED(ifaceInfo->GetTypeForParam(vtblIndex, &paramInfo, 1,
                                                    &datum_type)))
                {
                    Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
                    goto done;
                }
            }
            else
                datum_type = type;

            if(datum_type.IsInterfacePointer())
            {
                dp->SetValIsInterface();
            }

            // set 'src' to be the object from which we get the value and
            // prepare for out param

            if(paramInfo.IsOut())
            {
                dp->SetPtrIsData();
                dp->ptr = &dp->val;

                if(!paramInfo.IsRetval() &&
                   (JSVAL_IS_PRIMITIVE(argv[i]) ||
                    !OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[i]),
                        rt->GetStringID(XPCJSRuntime::IDX_VALUE), &src)))
                {
                    ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, ccx);
                    goto done;
                }

                if(datum_type.IsPointer() &&
                   !datum_type.IsInterfacePointer() &&
                   (isArray || !paramInfo.IsShared()))
                {
                    useAllocator = JS_TRUE;
                    dp->SetValIsAllocated();
                }

                if(!paramInfo.IsIn())
                    continue;
            }
            else
            {
                src = argv[i];

                if(datum_type.IsPointer() &&
                   datum_type.TagPart() == nsXPTType::T_IID)
                {
                    useAllocator = JS_TRUE;
                    dp->SetValIsAllocated();
                }
            }

            if(datum_type.IsInterfacePointer() &&
               !GetInterfaceTypeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
                                          vtblIndex, i, datum_type,
                                          dispatchParams, &param_iid))
                goto done;

            if(isArray || isSizedString)
            {
                if(!GetArraySizeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
                                          vtblIndex, i, GET_SIZE,
                                          dispatchParams, &array_capacity)||
                   !GetArraySizeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
                                          vtblIndex, i, GET_LENGTH,
                                          dispatchParams, &array_count))
                    goto done;

                if(isArray)
                {
                    if(array_count &&
                       !XPCConvert::JSArray2Native(ccx, (void**)&dp->val, src,
                                                   array_count, array_capacity,
                                                   datum_type,
                                                   useAllocator,
                                                   &param_iid, &err))
                    {
                        // XXX need exception scheme for arrays to indicate bad element
                        ThrowBadParam(err, i, ccx);
                        goto done;
                    }
                }
                else // if(isSizedString)
                {
                    if(!XPCConvert::JSStringWithSize2Native(ccx,
                                                   (void*)&dp->val,
                                                   src,
                                                   array_count, array_capacity,
                                                   datum_type, useAllocator,
                                                   &err))
                    {
                        ThrowBadParam(err, i, ccx);
                        goto done;
                    }
                }
            }
            else
            {
                if(!XPCConvert::JSData2Native(ccx, &dp->val, src, type,
                                              useAllocator, &param_iid,
                                              &err))
                {
                    ThrowBadParam(err, i, ccx);
                    goto done;
                }
            }
        }
    }


    {
        // avoid deadlock in case the native method blocks somehow
        AutoJSSuspendRequest req(ccx);  // scoped suspend of request

        // do the invoke
        invokeResult = XPTC_InvokeByIndex(callee, vtblIndex,
                                          paramCount, dispatchParams);
        // resume non-blocking JS operations now
    }


    xpcc->SetLastResult(invokeResult);

    if(NS_FAILED(invokeResult))
    {
        ThrowBadResult(invokeResult, ccx);
        goto done;
    }
    else if(ccx.GetExceptionWasThrown())
    {
        // the native callee claims to have already set a JSException
        goto done;
    }

    // now we iterate through the native params to gather and convert results
    for(i = 0; i < paramCount; i++)
    {
        const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
        if(!paramInfo.IsOut() && !paramInfo.IsDipper())
            continue;

        const nsXPTType& type = paramInfo.GetType();
        nsXPTCVariant* dp = &dispatchParams[i];
        jsval v = JSVAL_NULL;
        AUTO_MARK_JSVAL(ccx, &v);
        JSUint32 array_count;
        nsXPTType datum_type;
        PRBool isArray = type.IsArray();
        PRBool isSizedString = isArray ?
                JS_FALSE :
                type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
                type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;

        if(isArray)
        {
            if(NS_FAILED(ifaceInfo->GetTypeForParam(vtblIndex, &paramInfo, 1,
                                                    &datum_type)))
            {
                Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
                goto done;
            }
        }
        else
            datum_type = type;

        if(isArray || isSizedString)
        {
            if(!GetArraySizeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
                                      vtblIndex, i, GET_LENGTH, dispatchParams,
                                      &array_count))
                goto done;
        }

        if(datum_type.IsInterfacePointer() &&
           !GetInterfaceTypeFromParam(ccx, ifaceInfo, methodInfo, paramInfo,
                                      vtblIndex, i, datum_type, dispatchParams,
                                      &param_iid))
            goto done;

        if(isArray)
        {
            if(!XPCConvert::NativeArray2JS(ccx, &v, (const void**)&dp->val,
                                           datum_type, &param_iid,
                                           array_count, ccx.GetCurrentJSObject(),
                                           &err))
            {
                // XXX need exception scheme for arrays to indicate bad element
                ThrowBadParam(err, i, ccx);
                goto done;
            }
        }
        else if(isSizedString)
        {
            if(!XPCConvert::NativeStringWithSize2JS(ccx, &v,
                                           (const void*)&dp->val,
                                           datum_type,
                                           array_count, &err))
            {
                ThrowBadParam(err, i, ccx);
                goto done;
            }
        }
        else
        {
            if(!XPCConvert::NativeData2JS(ccx, &v, &dp->val, datum_type,
                                          &param_iid,
                                          ccx.GetCurrentJSObject(), &err))
            {
                ThrowBadParam(err, i, ccx);
                goto done;
            }
        }

        if(paramInfo.IsRetval())
        {
            if(!ccx.GetReturnValueWasSet())
                ccx.SetRetVal(v);
        }
        else
        {
            // we actually assured this before doing the invoke
            NS_ASSERTION(JSVAL_IS_OBJECT(argv[i]), "out var is not object");
            if(!OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[i]),
                        rt->GetStringID(XPCJSRuntime::IDX_VALUE), &v))
            {
                ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, i, ccx);
                goto done;
            }
        }
    }

    retval = JS_TRUE;
done:
    // iterate through the params (again!) and clean up
    // any alloc'd stuff and release wrappers of params
    if(dispatchParams)
    {
        for(i = 0; i < paramCount; i++)
        {
            nsXPTCVariant* dp = &dispatchParams[i];
            void* p = dp->val.p;
            if(!p)
                continue;

            if(dp->IsValArray())
            {
                // going to have to cleanup the array and perhaps its contents
                if(dp->IsValAllocated() || dp->IsValInterface())
                {
                    // we need to figure out how many elements are present.
                    JSUint32 array_count;

                    const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
                    if(!GetArraySizeFromParam(ccx, ifaceInfo, methodInfo,
                                              paramInfo, vtblIndex,
                                              i, GET_LENGTH, dispatchParams,
                                              &array_count))
                    {
                        NS_ASSERTION(0,"failed to get array length, we'll leak here");
                        continue;
                    }
                    if(dp->IsValAllocated())
                    {
                        void** a = (void**)p;
                        for(JSUint32 k = 0; k < array_count; k++)
                        {
                            void* o = a[k];
                            if(o) nsMemory::Free(o);
                        }
                    }
                    else // if(dp->IsValInterface())
                    {
                        nsISupports** a = (nsISupports**)p;
                        for(JSUint32 k = 0; k < array_count; k++)
                        {
                            nsISupports* o = a[k];
                            NS_IF_RELEASE(o);
                        }
                    }
                }
                // always free the array itself
                nsMemory::Free(p);
            }
            else if(dp->IsValAllocated())
                nsMemory::Free(p);
            else if(dp->IsValInterface())
                ((nsISupports*)p)->Release();
            else if(dp->IsValDOMString())
                delete (nsAString*)p;
            else if(dp->IsValUTF8String())
                delete (nsCString*) p;
            else if(dp->IsValCString())
                delete (nsCString*) p;
        }   
    }

    if(dispatchParams && dispatchParams != paramBuffer)
        delete [] dispatchParams;

#ifdef off_DEBUG_stats_jband
    endTime = PR_IntervalNow();

    printf("%s::%s %d ( js->c ) \n",
           ccx.GetInterface()->GetNameString(),
           ccx.GetInterface()->GetMemberName(ccx, ccx.GetMember()),
           PR_IntervalToMilliseconds(endTime-startTime));

    totalTime += (endTime-startTime);
#endif

    return retval;
}

Here is the caller graph for this function:

void nsIXPConnectWrappedNative::debugDump ( in short  depth) [inherited]
JSBool XPCWrappedNative::ExtendSet ( XPCCallContext ccx,
XPCNativeInterface aInterface 
) [private]

Definition at line 1284 of file xpcwrappednative.cpp.

{
    // This is only called while locked (during XPCWrappedNative::FindTearOff).

    if(!mSet->HasInterface(aInterface))
    {
        AutoMarkingNativeSetPtr newSet(ccx);
        newSet = XPCNativeSet::GetNewOrUsed(ccx, mSet, aInterface,
                                            mSet->GetInterfaceCount());
        if(!newSet)
            return JS_FALSE;

        mSet = newSet;

        DEBUG_ReportShadowedMembers(newSet, this, GetProto());
    }
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1332 of file xpcwrappednative.cpp.

{
    XPCAutoLock al(GetLock()); // hold the lock throughout

    nsresult rv = NS_OK;
    XPCWrappedNativeTearOff* to;
    XPCWrappedNativeTearOff* firstAvailable = nsnull;

    XPCWrappedNativeTearOffChunk* lastChunk;
    XPCWrappedNativeTearOffChunk* chunk;
    for(lastChunk = chunk = &mFirstChunk;
        chunk;
        lastChunk = chunk, chunk = chunk->mNextChunk)
    {
        to = chunk->mTearOffs;
        XPCWrappedNativeTearOff* const end = chunk->mTearOffs + 
            XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK;
        for(
            to = chunk->mTearOffs;
            to < end; 
            to++)
        {
            if(to->GetInterface() == aInterface)
            {
                if(needJSObject && !to->GetJSObject())
                {
                    AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to);
                    rv = InitTearOffJSObject(ccx, to);
                    // During shutdown, we don't sweep tearoffs.  So make sure
                    // to unmark manually in case the auto-marker marked us.
                    // We shouldn't ever be getting here _during_ our
                    // Mark/Sweep cycle, so this should be safe.
                    to->Unmark();
                    if(NS_FAILED(rv))
                        to = nsnull;
                }
                goto return_result;
            }
            if(!firstAvailable && to->IsAvailable())
                firstAvailable = to;
        }
    }

    to = firstAvailable;

    if(!to)
    {
        XPCWrappedNativeTearOffChunk* newChunk =
            new XPCWrappedNativeTearOffChunk();
        if(!newChunk)
        {
            rv = NS_ERROR_OUT_OF_MEMORY;
            goto return_result;
        }
        lastChunk->mNextChunk = newChunk;
        to = newChunk->mTearOffs;
    }

    {
        // Scope keeps |tearoff| from leaking across the return_result: label
        AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to);
        rv = InitTearOff(ccx, to, aInterface, needJSObject);
        // During shutdown, we don't sweep tearoffs.  So make sure to unmark
        // manually in case the auto-marker marked us.  We shouldn't ever be
        // getting here _during_ our Mark/Sweep cycle, so this should be safe.
        to->Unmark();
        if(NS_FAILED(rv))
            to = nsnull;
    }

return_result:

    if(pError)
        *pError = rv;
    return to;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 896 of file xpcwrappednative.cpp.

{
    if(!IsValid())
        return;

    // Iterate the tearoffs and null out each of their JSObject's privates.
    // This will keep them from trying to access their pointers to the
    // dying tearoff object. We can safely assume that those remaining
    // JSObjects are about to be finalized too.

    XPCWrappedNativeTearOffChunk* chunk;
    for(chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk)
    {
        XPCWrappedNativeTearOff* to = chunk->mTearOffs;
        for(int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK-1; i >= 0; i--, to++)
        {
            JSObject* jso = to->GetJSObject();
            if(jso)
            {
                NS_ASSERTION(JS_IsAboutToBeFinalized(cx, jso), "bad!");
                JS_SetPrivate(cx, jso, nsnull);
                to->JSObjectFinalized();
            }

            // We also need to release any native pointers held...
            nsISupports* obj = to->GetNative();
            if(obj)
            {
#ifdef XP_WIN
                // Try to detect free'd pointer
                NS_ASSERTION(*(int*)obj != 0xdddddddd, "bad pointer!");
                NS_ASSERTION(*(int*)obj != 0,          "bad pointer!");
#endif
                XPCJSRuntime* rt = GetRuntime();
                if(rt && rt->GetDeferReleases())
                {
                    if(!rt->DeferredRelease(obj))
                    {
                        NS_WARNING("Failed to append object for deferred release.");
                        // XXX do we really want to do this???
                        obj->Release();
                    }
                }
                else
                {
                    obj->Release();
                }
                to->SetNative(nsnull);
            }

            to->SetInterface(nsnull);
        }
    }

    //This makes IsValid return false from now on...
    mFlatJSObject = nsnull;

    NS_ASSERTION(mIdentity, "bad pointer!");
#ifdef XP_WIN
    // Try to detect free'd pointer
    NS_ASSERTION(*(int*)mIdentity != 0xdddddddd, "bad pointer!");
    NS_ASSERTION(*(int*)mIdentity != 0,          "bad pointer!");
#endif

    // Note that it's not safe to touch mNativeWrapper here since it's
    // likely that it has already been finalized.

    Release();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 615 of file xpcwrappednative.cpp.

{
    NS_ASSERTION(classInfo, "bad param");
    NS_ASSERTION(sciProto && !sciProto->GetCallback(), "bad param");

    nsCOMPtr<nsISupports> possibleHelper;
    nsresult rv = classInfo->GetHelperForLanguage(
                                    nsIProgrammingLanguage::JAVASCRIPT,
                                    getter_AddRefs(possibleHelper));
    if(NS_SUCCEEDED(rv) && possibleHelper)
    {
        nsCOMPtr<nsIXPCScriptable> helper(do_QueryInterface(possibleHelper));
        if(helper)
        {
            JSUint32 flags;
            rv = helper->GetScriptableFlags(&flags);
            if(NS_FAILED(rv))
                flags = 0;

            sciProto->SetCallback(helper);
            sciProto->SetFlags(flags);
        }
    }
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult XPCWrappedNative::GatherScriptableCreateInfo ( nsISupports *  obj,
nsIClassInfo classInfo,
XPCNativeScriptableCreateInfo sciProto,
XPCNativeScriptableCreateInfo sciWrapper 
) [static]

Definition at line 645 of file xpcwrappednative.cpp.

{
    NS_ASSERTION(sciProto   && !sciProto->GetCallback(), "bad param");
    NS_ASSERTION(sciWrapper && !sciWrapper->GetCallback(), "bad param");

    // Get the class scriptable helper (if present)
    if(classInfo)
    {
        GatherProtoScriptableCreateInfo(classInfo, sciProto);

        sciWrapper->SetCallback(sciProto->GetCallback());
        sciWrapper->SetFlags(sciProto->GetFlags());

        if(sciProto->GetFlags().DontAskInstanceForScriptable())
            return NS_OK;
    }

    // Do the same for the wrapper specific scriptable
    nsCOMPtr<nsIXPCScriptable> helper(do_QueryInterface(obj));
    if(helper)
    {
        JSUint32 flags;
        nsresult rv = helper->GetScriptableFlags(&flags);
        if(NS_FAILED(rv))
            flags = 0;

        sciWrapper->SetCallback(helper);
        sciWrapper->SetFlags(flags);

        // A whole series of assertions to catch bad uses of scriptable flags on
        // the siWrapper...

        NS_ASSERTION(!(sciWrapper->GetFlags().WantPreCreate() &&
                        !sciProto->GetFlags().WantPreCreate()),
                     "Can't set WANT_PRECREATE on an instance scriptable "
                     "without also setting it on the class scriptable");

        NS_ASSERTION(!(sciWrapper->GetFlags().DontEnumStaticProps() &&
                        !sciProto->GetFlags().DontEnumStaticProps() &&
                        sciProto->GetCallback() &&
                        !sciProto->GetFlags().DontSharePrototype()),
                     "Can't set DONT_ENUM_STATIC_PROPS on an instance scriptable "
                     "without also setting it on the class scriptable (if present and shared)");

        NS_ASSERTION(!(sciWrapper->GetFlags().DontEnumQueryInterface() &&
                        !sciProto->GetFlags().DontEnumQueryInterface() &&
                        sciProto->GetCallback() &&
                        !sciProto->GetFlags().DontSharePrototype()),
                     "Can't set DONT_ENUM_QUERY_INTERFACE on an instance scriptable "
                     "without also setting it on the class scriptable (if present and shared)");

        NS_ASSERTION(!(sciWrapper->GetFlags().DontAskInstanceForScriptable() &&
                        !sciProto->GetFlags().DontAskInstanceForScriptable()),
                     "Can't set DONT_ASK_INSTANCE_FOR_SCRIPTABLE on an instance scriptable "
                     "without also setting it on the class scriptable");

        NS_ASSERTION(!(sciWrapper->GetFlags().ClassInfoInterfacesOnly() &&
                        !sciProto->GetFlags().ClassInfoInterfacesOnly() &&
                        sciProto->GetCallback() &&
                        !sciProto->GetFlags().DontSharePrototype()),
                     "Can't set CLASSINFO_INTERFACES_ONLY on an instance scriptable "
                     "without also setting it on the class scriptable (if present and shared)");

        NS_ASSERTION(!(sciWrapper->GetFlags().AllowPropModsDuringResolve() &&
                        !sciProto->GetFlags().AllowPropModsDuringResolve() &&
                        sciProto->GetCallback() &&
                        !sciProto->GetFlags().DontSharePrototype()),
                     "Can't set ALLOW_PROP_MODS_DURING_RESOLVE on an instance scriptable "
                     "without also setting it on the class scriptable (if present and shared)");

        NS_ASSERTION(!(sciWrapper->GetFlags().AllowPropModsToPrototype() &&
                        !sciProto->GetFlags().AllowPropModsToPrototype() &&
                        sciProto->GetCallback() &&
                        !sciProto->GetFlags().DontSharePrototype()),
                     "Can't set ALLOW_PROP_MODS_TO_PROTOTYPE on an instance scriptable "
                     "without also setting it on the class scriptable (if present and shared)");

        NS_ASSERTION(!(sciWrapper->GetFlags().DontSharePrototype() &&
                        !sciProto->GetFlags().DontSharePrototype() &&
                        sciProto->GetCallback()),
                     "Can't set DONT_SHARE_PROTOTYPE on an instance scriptable "
                     "without also setting it on the class scriptable (if present and shared)");
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool XPCWrappedNative::GetAttribute ( XPCCallContext ccx) [inline, static]

Definition at line 1964 of file xpcprivate.h.

        {return CallMethod(ccx, CALL_GETTER);}

Here is the caller graph for this function:

Definition at line 1887 of file xpcprivate.h.

                         {return IsValid() && HasProto() ?
                            mMaybeProto->GetClassInfo() : nsnull;}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1862 of file xpcprivate.h.

{return mFlatJSObject;}

Here is the caller graph for this function:

nsISupports* XPCWrappedNative::GetIdentityObject ( ) const [inline]

Definition at line 1859 of file xpcprivate.h.

{return mIdentity;}

Here is the caller graph for this function:

XPCLock* XPCWrappedNative::GetLock ( ) const [inline]

Definition at line 1865 of file xpcprivate.h.

                    {return IsValid() && HasProto() ?
                                mMaybeProto->GetLock() : nsnull;}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2034 of file xpcprivate.h.

{ return mNativeWrapper; }

Here is the caller graph for this function:

nsresult XPCWrappedNative::GetNewOrUsed ( XPCCallContext ccx,
nsISupports *  Object,
XPCWrappedNativeScope Scope,
XPCNativeInterface Interface,
JSBool  isGlobal,
XPCWrappedNative **  wrapper 
) [static]

Definition at line 208 of file xpcwrappednative.cpp.

{
    nsresult rv;

    NS_ASSERTION(!Scope->GetRuntime()->GetThreadRunningGC(), 
                 "XPCWrappedNative::GetNewOrUsed called during GC");

    nsCOMPtr<nsISupports> identity;
#ifdef XPC_IDISPATCH_SUPPORT
    // XXX This is done for the benefit of some warped COM implementations
    // where QI(IID_IUnknown, a.b) == QI(IID_IUnknown, a). If someone passes
    // in a pointer that hasn't been QI'd to IDispatch properly this could
    // create multiple wrappers for the same object, creating a fair bit of
    // confusion.
    PRBool isIDispatch = Interface->GetIID()->Equals(NSID_IDISPATCH);
    if(isIDispatch)
        identity = Object;
    else
#endif
        identity = do_QueryInterface(Object);

    if(!identity)
    {
        NS_ERROR("This XPCOM object fails in QueryInterface to nsISupports!");
        return NS_ERROR_FAILURE;
    }

    XPCLock* mapLock = Scope->GetRuntime()->GetMapLock();
    
    // We use an AutoMarkingPtr here because it is possible for JS gc to happen
    // after we have Init'd the wrapper but *before* we add it to the hashtable.
    // This would cause the mSet to get collected and we'd later crash. I've
    // *seen* this happen.
    AutoMarkingWrappedNativePtr wrapper(ccx);

    Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap();
    {   // scoped lock
        XPCAutoLock lock(mapLock);
        wrapper = map->Find(identity);
        if(wrapper)
            wrapper->AddRef();
    }

    if(wrapper)
    {
        if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
        {
            NS_RELEASE(wrapper);
            NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
            return rv;
        }
        DEBUG_CheckWrapperThreadSafety(wrapper);
        *resultWrapper = wrapper;
        return NS_OK;
    }

    // There is a chance that the object wants to have the self-same JSObject
    // reflection regardless of the scope into which we are reflecting it.
    // Many DOM objects require this. The scriptable helper specifies this
    // in preCreate by indicating a 'parent' of a particular scope.
    //
    // To handle this we need to get the scriptable helper early and ask it.
    // It is possible that we will then end up forwarding this entire call
    // to this same function but with a different scope.

    // If we are making a wrapper for the nsIClassInfo interface then
    // We *don't* want to have it use the prototype meant for instances
    // of that class.
    JSBool isClassInfo = Interface->GetIID()->Equals(NS_GET_IID(nsIClassInfo));

    nsCOMPtr<nsIClassInfo> info;

    if(!isClassInfo)
        info = do_QueryInterface(identity);

#ifdef XPC_IDISPATCH_SUPPORT
    // If this is an IDispatch wrapper and it didn't give us a class info
    // we'll provide a default one
    if(isIDispatch && !info)
    {
        info = dont_AddRef(NS_STATIC_CAST(nsIClassInfo*,
                                          XPCIDispatchClassInfo::GetSingleton()));
    }
#endif

    XPCNativeScriptableCreateInfo sciProto;
    XPCNativeScriptableCreateInfo sciWrapper;

    // Gather scriptable create info if we are wrapping something
    // other than an nsIClassInfo object. We need to not do this for
    // nsIClassInfo objects because often nsIClassInfo implementations
    // are also nsIXPCScriptable helper implmentations, but the helper
    // code is obviously intended for the implementation of the class
    // described by the nsIClassInfo, not for the class info object
    // itself.
    if(!isClassInfo &&
       NS_FAILED(GatherScriptableCreateInfo(identity, info.get(),
                                            &sciProto, &sciWrapper)))
        return NS_ERROR_FAILURE;

    JSObject* parent = Scope->GetGlobalJSObject();

    jsval newParentVal = JSVAL_NULL;
    XPCMarkableJSVal newParentVal_markable(&newParentVal);
    AutoMarkingJSVal newParentVal_automarker(ccx, &newParentVal_markable);

    if(sciWrapper.GetFlags().WantPreCreate())
    {
        JSObject* plannedParent = parent;
        nsresult rv = sciWrapper.GetCallback()->PreCreate(identity, ccx,
                                                          parent, &parent);
        if(NS_FAILED(rv))
            return rv;

        NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(ccx, parent),
                     "Parent should never be an XPCNativeWrapper here");

        if(parent != plannedParent)
        {
            XPCWrappedNativeScope* betterScope =
                XPCWrappedNativeScope::FindInJSObjectScope(ccx, parent);
            if(betterScope != Scope)
                return GetNewOrUsed(ccx, identity, betterScope, Interface,
                                    isGlobal, resultWrapper);

            newParentVal = OBJECT_TO_JSVAL(parent);
        }

        // Take the performance hit of checking the hashtable again in case
        // the preCreate call caused the wrapper to get created through some
        // interesting path (the DOM code tends to make this happen sometimes).

        {   // scoped lock
            XPCAutoLock lock(mapLock);
            wrapper = map->Find(identity);
            if(wrapper)
                wrapper->AddRef();
        }

        if(wrapper)
        {
            if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
            {
                NS_RELEASE(wrapper);
                NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
                return rv;
            }
            DEBUG_CheckWrapperThreadSafety(wrapper);
            *resultWrapper = wrapper;
            return NS_OK;
        }
    }

    AutoMarkingWrappedNativeProtoPtr proto(ccx);

    // If there is ClassInfo (and we are not building a wrapper for the
    // nsIClassInfo interface) then we use a wrapper that needs a prototype.

    // Note that the security check happens inside FindTearOff - after the
    // wrapper is actually created, but before JS code can see it.

    if(info && !isClassInfo)
    {
        proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, Scope, info, &sciProto,
                                                    JS_FALSE, isGlobal);
        if(!proto)
            return NS_ERROR_FAILURE;

        wrapper = new XPCWrappedNative(identity, proto);
        if(!wrapper)
            return NS_ERROR_FAILURE;
    }
    else
    {
        AutoMarkingNativeSetPtr set(ccx);
        set = XPCNativeSet::GetNewOrUsed(ccx, nsnull, Interface, 0);

        if(!set)
            return NS_ERROR_FAILURE;

        wrapper = new XPCWrappedNative(identity, Scope, set);
        if(!wrapper)
            return NS_ERROR_FAILURE;

        DEBUG_ReportShadowedMembers(set, wrapper, nsnull);
    }

    NS_ADDREF(wrapper);

    NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(ccx, parent),
                 "XPCNativeWrapper being used to parent XPCWrappedNative?");
    
    if(!wrapper->Init(ccx, parent, isGlobal, &sciWrapper))
    {
        NS_RELEASE(wrapper);
        return NS_ERROR_FAILURE;
    }

    if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
    {
        // Second reference will be released by the FlatJSObject's finializer.
        wrapper->Release();
        NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
        return rv;
    }

#if DEBUG_XPCNativeWrapper
    {
        char* s = wrapper->ToString(ccx);
        NS_ASSERTION(wrapper->GetFlatJSObject(), "eh?");
        printf("Created wrapped native %s, flat JSObject is %p\n",
               s, (void*)wrapper->GetFlatJSObject());
        if (s)
            JS_smprintf_free(s);
    }
#endif

    // Redundant wrapper must be killed outside of the map lock.
    XPCWrappedNative* wrapperToKill = nsnull;

    {   // scoped lock
        XPCAutoLock lock(mapLock);

        // Deal with the case where the wrapper got created as a side effect
        // of one of our calls out of this code (or on another thread).
        XPCWrappedNative* wrapper2 = map->Add(wrapper);
        if(!wrapper2)
        {
            NS_ERROR("failed to add our wrapper!");
            wrapperToKill = wrapper;
            wrapper = nsnull;
        }
        else if(wrapper2 != wrapper)
        {
            NS_ADDREF(wrapper2);
            wrapperToKill = wrapper;
            wrapper = wrapper2;
        }
    }

    if(wrapperToKill)
    {
        // Second reference will be released by the FlatJSObject's finializer.
        wrapperToKill->Release();
    }
    else if(wrapper)
    {
        // Our newly created wrapper is the one that we just added to the table.
        // All is well. Call PostCreate as necessary.
        XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
        if(si && si->GetFlags().WantPostCreate())
        {
            rv = si->GetCallback()->
                     PostCreate(wrapper, ccx, wrapper->GetFlatJSObject());
            if(NS_FAILED(rv))
            {
                {   // scoped lock
                    XPCAutoLock lock(mapLock);
                    map->Remove(wrapper);
                }

                wrapper->Release();
                return rv;
            }
        }
    }

    if(!wrapper)
        return NS_ERROR_FAILURE;

    DEBUG_CheckClassInfoClaims(wrapper);
    *resultWrapper = wrapper;
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1852 of file xpcprivate.h.

{return HasProto() ? mMaybeProto : nsnull;}

Here is the caller graph for this function:

Definition at line 1900 of file xpcprivate.h.

                       {XPCWrappedNativeScope* scope = GetScope();
                        return scope ? scope->GetRuntime() : nsnull;}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1855 of file xpcprivate.h.

                     {return HasProto() ?
                           mMaybeProto->GetScope() : UnTagScope(mMaybeScope);}

Here is the caller graph for this function:

Definition at line 1880 of file xpcprivate.h.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1877 of file xpcprivate.h.

{return mScriptableInfo;}

Here is the caller graph for this function:

Definition at line 1883 of file xpcprivate.h.

                          {return HasProto() ?
                                   mMaybeProto->GetSecurityInfoAddr() : nsnull;}

Here is the caller graph for this function:

Definition at line 1869 of file xpcprivate.h.

{XPCAutoLock al(GetLock()); return mSet;}

Here is the caller graph for this function:

nsresult XPCWrappedNative::GetUsedOnly ( XPCCallContext ccx,
nsISupports *  Object,
XPCWrappedNativeScope Scope,
XPCNativeInterface Interface,
XPCWrappedNative **  wrapper 
) [static]

Definition at line 490 of file xpcwrappednative.cpp.

{
    NS_ASSERTION(Object, "XPCWrappedNative::GetUsedOnly was called with a null Object");
    nsCOMPtr<nsISupports> identity;
#ifdef XPC_IDISPATCH_SUPPORT
    // XXX See GetNewOrUsed for more info on this
    if(Interface->GetIID()->Equals(NSID_IDISPATCH))
        identity = Object;
    else
#endif
        identity = do_QueryInterface(Object);

    if(!identity)
    {
        NS_ERROR("This XPCOM object fails in QueryInterface to nsISupports!");
        return NS_ERROR_FAILURE;
    }

    XPCWrappedNative* wrapper;
    Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap();

    {   // scoped lock
        XPCAutoLock lock(Scope->GetRuntime()->GetMapLock());
        wrapper = map->Find(identity);
        if(!wrapper)
        {
            *resultWrapper = nsnull;
            return NS_OK;
        }
        NS_ADDREF(wrapper);
    }

    nsresult rv;
    if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))
    {
        NS_RELEASE(wrapper);
        NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
        return rv;
    }

    *resultWrapper = wrapper;
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1166 of file xpcwrappednative.cpp.

{
    NS_PRECONDITION(obj, "bad param");

    JSObject* cur;

    XPCWrappedNativeProto* proto = nsnull;
    nsIClassInfo* protoClassInfo = nsnull;

    // If we were passed a function object then we need to find the correct
    // wrapper out of those that might be in the callee obj's proto chain.

    if(funobj)
    {
        JSObject* funObjParent = JS_GetParent(cx, funobj);
        NS_ASSERTION(funObjParent, "funobj has no parent");

        JSClass* funObjParentClass = JS_GET_CLASS(cx, funObjParent);

        if(IS_PROTO_CLASS(funObjParentClass))
        {
            NS_ASSERTION(JS_GetParent(cx, funObjParent), "funobj's parent (proto) is global");
            proto = (XPCWrappedNativeProto*) JS_GetPrivate(cx, funObjParent);
            if(proto)
                protoClassInfo = proto->GetClassInfo();
        }
        else if(IS_WRAPPER_CLASS(funObjParentClass))
        {
            cur = funObjParent;
            goto return_wrapper;
        }
        else if(IS_TEAROFF_CLASS(funObjParentClass))
        {
            NS_ASSERTION(JS_GetParent(cx, funObjParent), "funobj's parent (tearoff) is global");
            cur = funObjParent;
            goto return_tearoff;
        }
        else
        {
            NS_ERROR("function object has parent of unknown class!");
            return nsnull;
        }
    }

    for(cur = obj; cur; cur = JS_GetPrototype(cx, cur))
    {
        // this is on two lines to make the compiler happy given the goto.
        JSClass* clazz;
        clazz = JS_GET_CLASS(cx, cur);

        if(IS_WRAPPER_CLASS(clazz))
        {
return_wrapper:
            XPCWrappedNative* wrapper =
                (XPCWrappedNative*) JS_GetPrivate(cx, cur);
            if(proto && proto != wrapper->GetProto() &&
               (proto->GetScope() != wrapper->GetScope() ||
                !protoClassInfo || !wrapper->GetProto() ||
                protoClassInfo != wrapper->GetProto()->GetClassInfo()))
                continue;
            if(pobj2)
                *pobj2 = cur;
            return wrapper;
        }

        if(IS_TEAROFF_CLASS(clazz))
        {
return_tearoff:
            XPCWrappedNative* wrapper =
                (XPCWrappedNative*) JS_GetPrivate(cx, JS_GetParent(cx,cur));
            if(proto && proto != wrapper->GetProto() &&
               (proto->GetScope() != wrapper->GetScope() ||
                !protoClassInfo || !wrapper->GetProto() ||
                protoClassInfo != wrapper->GetProto()->GetClassInfo()))
                continue;
            if(pobj2)
                *pobj2 = cur;
            XPCWrappedNativeTearOff* to =
                (XPCWrappedNativeTearOff*) JS_GetPrivate(cx, cur);
            if(!to)
                return nsnull;
            if(pTearOff)
                *pTearOff = to;
            return wrapper;
        }

        if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
        {
            if(pobj2)
                *pobj2 = cur;

            return XPCNativeWrapper::GetWrappedNative(cx, cur);
        }
    }

    // If we didn't find a wrapper using the given funobj and obj, try
    // again with obj's outer object, if it's got one.

    JSClass *clazz = JS_GET_CLASS(cx, obj);

    if((clazz->flags & JSCLASS_IS_EXTENDED) &&
       ((JSExtendedClass*)clazz)->outerObject)
    {
        JSObject *outer = ((JSExtendedClass*)clazz)->outerObject(cx, obj);

        if(outer && outer != obj)
            return GetWrappedNativeOfJSObject(cx, outer, funobj, pobj2,
                                              pTearOff);
    }

    return nsnull;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2032 of file xpcprivate.h.

{return mRefCnt > 1;}

Here is the caller graph for this function:

Definition at line 653 of file xpcinlines.h.

{
    return GetSet()->HasInterface(aInterface);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 659 of file xpcinlines.h.

{
    return nsnull != GetSet()->FindInterfaceWithIID(iid);
}

Here is the call graph for this function:

Definition at line 1895 of file xpcprivate.h.

                          {return IsValid() &&
                                  (!HasProto() ||
                                   GetSet() != mMaybeProto->GetSet());}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool XPCWrappedNative::HasProto ( ) const [inline]

Definition at line 1849 of file xpcprivate.h.

{return !IsTaggedScope(mMaybeScope);}

Here is the caller graph for this function:

Definition at line 1891 of file xpcprivate.h.

                           {return IsValid() && HasProto() &&
                            mMaybeProto->IsShared();}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool XPCWrappedNative::Init ( XPCCallContext ccx,
JSObject parent,
JSBool  isGlobal,
const XPCNativeScriptableCreateInfo sci 
) [private]

Definition at line 737 of file xpcwrappednative.cpp.

{
    // setup our scriptable info...

    if(sci->GetCallback())
    {
        if(HasProto())
        {
            XPCNativeScriptableInfo* siProto = GetProto()->GetScriptableInfo();
            if(siProto && siProto->GetCallback() == sci->GetCallback())
                mScriptableInfo = siProto;
        }
        if(!mScriptableInfo)
        {
            mScriptableInfo =
                XPCNativeScriptableInfo::Construct(ccx, isGlobal, sci);

            if(!mScriptableInfo)
                return JS_FALSE;

            // If we have a one-off proto, then it should share our scriptable.
            // This allows the proto's JSClass callbacks to do the right things
            // (like respecting the DONT_ENUM_STATIC_PROPS flag) w/o requiring
            // scriptable objects to have an nsIClassInfo.
            if(HasProto() && !HasSharedProto())
                GetProto()->SetScriptableInfo(mScriptableInfo);
        }
    }
    XPCNativeScriptableInfo* si = mScriptableInfo;

    // create our flatJSObject

    JSClass* jsclazz = si ? si->GetJSClass() : &XPC_WN_NoHelper_JSClass.base;

    NS_ASSERTION(jsclazz &&
                 jsclazz->name &&
                 jsclazz->flags &&
                 jsclazz->addProperty &&
                 jsclazz->delProperty &&
                 jsclazz->getProperty &&
                 jsclazz->setProperty &&
                 jsclazz->enumerate &&
                 jsclazz->resolve &&
                 jsclazz->convert &&
                 jsclazz->finalize, "bad class");

    JSObject* protoJSObject = HasProto() ?
                                GetProto()->GetJSProtoObject() :
                                GetScope()->GetPrototypeJSObject();

    mFlatJSObject = JS_NewObject(ccx, jsclazz, protoJSObject, parent);

    if(!mFlatJSObject)
        return JS_FALSE;

    // In the current JS engine JS_SetPrivate can't fail. But if it *did*
    // fail then we would not receive our finalizer call and would not be
    // able to properly cleanup. So, if it fails we null out mFlatJSObject
    // to indicate the invalid state of this object and return false. 
    if(!JS_SetPrivate(ccx, mFlatJSObject, this))
    {
        mFlatJSObject = nsnull;
        return JS_FALSE;
    }

    // Propagate the system flag from parent to child.
    if(JS_IsSystemObject(ccx, parent))
        JS_FlagSystemObject(ccx, mFlatJSObject);

    // This reference will be released when mFlatJSObject is finalized.
    // Since this reference will push the refcount to 2 it will also root
    // mFlatJSObject;
    NS_ASSERTION(1 == mRefCnt, "unexpected refcount value");
    NS_ADDREF(this);

    if(si && si->GetFlags().WantCreate() &&
       NS_FAILED(si->GetCallback()->Create(this, ccx, mFlatJSObject)))
    {
        return JS_FALSE;
    }

#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
    if(!gMainThread)
        gMainThread = nsXPConnect::GetMainThread();

    mThread = PR_GetCurrentThread();

    if(HasProto() && GetProto()->ClassIsMainThreadOnly() && gMainThread != mThread)
        DEBUG_ReportWrapperThreadSafetyError(ccx,
            "MainThread only wrapper created on the wrong thread", this);
#endif

    return JS_TRUE;
}

Here is the call graph for this function:

nsresult XPCWrappedNative::InitTearOff ( XPCCallContext ccx,
XPCWrappedNativeTearOff aTearOff,
XPCNativeInterface aInterface,
JSBool  needJSObject 
) [private]

Definition at line 1413 of file xpcwrappednative.cpp.

{
    // This is only called while locked (during XPCWrappedNative::FindTearOff).

    // Determine if the object really does this interface...

    const nsIID* iid = aInterface->GetIID();
    nsISupports* identity = GetIdentityObject();
    nsISupports* obj;

    // If the scriptable helper forbids us from reflecting additional
    // interfaces, then don't even try the QI, just fail.
    if(mScriptableInfo &&
       mScriptableInfo->GetFlags().ClassInfoInterfacesOnly() &&
       !mSet->HasInterface(aInterface) &&
       !mSet->HasInterfaceWithAncestor(aInterface))
    {
        return NS_ERROR_NO_INTERFACE;
    }

    // We are about to call out to unlock and other code.
    // So protect our intended tearoff.

    aTearOff->SetReserved();

    {   // scoped *un*lock
        XPCAutoUnlock unlock(GetLock());

        if(NS_FAILED(identity->QueryInterface(*iid, (void**)&obj)) || !obj)
        {
            aTearOff->SetInterface(nsnull);
            return NS_ERROR_NO_INTERFACE;
        }

        // Guard against trying to build a tearoff for a shared nsIClassInfo.
        if(iid->Equals(NS_GET_IID(nsIClassInfo)))
        {
            nsCOMPtr<nsISupports> alternate_identity(do_QueryInterface(obj));
            if(alternate_identity.get() != identity)
            {
                NS_RELEASE(obj);
                aTearOff->SetInterface(nsnull);
                return NS_ERROR_NO_INTERFACE;
            }
        }

        // Guard against trying to build a tearoff for an interface that is
        // aggregated and is implemented as a nsIXPConnectWrappedJS using this
        // self-same JSObject. The XBL system does this. If we mutate the set
        // of this wrapper then we will shadow the method that XBL has added to
        // the JSObject that it has inserted in the JS proto chain between our
        // JSObject and our XPCWrappedNativeProto's JSObject. If we let this
        // set mutation happen then the interface's methods will be added to 
        // our JSObject, but calls on those methods will get routed up to
        // native code and into the wrappedJS - which will do a method lookup
        // on *our* JSObject and find the same method and make another call
        // into an infinite loop.
        // see: http://bugzilla.mozilla.org/show_bug.cgi?id=96725

        // The code in this block also does a check for the double wrapped
        // nsIPropertyBag case.

        nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS(do_QueryInterface(obj));
        if(wrappedJS)
        {
            JSObject* jso = nsnull;
            if(NS_SUCCEEDED(wrappedJS->GetJSObject(&jso)) &&
               jso == GetFlatJSObject())
            {
                // The implementing JSObject is the same as ours! Just say OK
                // without actually extending the set.
                //
                // XXX It is a little cheesy to have FindTearOff return an
                // 'empty' tearoff. But this is the centralized place to do the
                // QI activities on the underlying object. *And* most caller to
                // FindTearOff only look for a non-null result and ignore the
                // actual tearoff returned. The only callers that do use the
                // returned tearoff make sure to check for either a non-null 
                // JSObject or a matching Interface before proceeding.
                // I think we can get away with this bit of ugliness.
                
#ifdef DEBUG_xpc_hacker
                {
                    // I want to make sure this only happens in xbl-like cases.
                    // So, some debug code to verify that there is at least
                    // *some* object between our JSObject and its inital proto.
                    // XXX This is a pretty funky test. Someone might hack it
                    // a bit if false positives start showing up. Note that 
                    // this is only going to run for the few people in the
                    // DEBUG_xpc_hacker list.
                    if(HasProto())
                    {
                        JSObject* proto  = nsnull;
                        JSObject* our_proto = GetProto()->GetJSProtoObject();

                        proto = JS_GetPrototype(ccx, jso);

                        NS_WARN_IF_FALSE(proto && proto != our_proto,
                            "!!! xpconnect/xbl check - wrapper has no special proto");

                        PRBool found_our_proto = PR_FALSE;
                        while (proto && !found_our_proto) {
                            proto = JS_GetPrototype(ccx, proto);

                            found_our_proto = proto == our_proto;
                        }

                        NS_WARN_IF_FALSE(found_our_proto,
                            "!!! xpconnect/xbl check - wrapper has extra proto");
                    }
                    else
                    {
                        NS_WARNING("!!! xpconnect/xbl check - wrapper has no proto");
                    }
                }
#endif
                NS_RELEASE(obj);
                aTearOff->SetInterface(nsnull);
                return NS_OK;
            }
            
            // Decide whether or not to expose nsIPropertyBag to calling
            // JS code in the double wrapped case.
            //
            // Our rule here is that when JSObjects are double wrapped and
            // exposed to other JSObjects then the nsIPropertyBag interface
            // is only exposed on an 'opt-in' basis; i.e. if the underlying
            // JSObject wants other JSObjects to be able to see this interface
            // then it must implement QueryInterface and not throw an exception
            // when asked for nsIPropertyBag. It need not actually *implement*
            // nsIPropertyBag - xpconnect will do that work.

            nsXPCWrappedJSClass* clazz;
            if(iid->Equals(NS_GET_IID(nsIPropertyBag)) && jso &&
               NS_SUCCEEDED(nsXPCWrappedJSClass::GetNewOrUsed(ccx,*iid,&clazz))&&
               clazz)
            {
                JSObject* answer =
                    clazz->CallQueryInterfaceOnJSObject(ccx, jso, *iid);
                NS_RELEASE(clazz);
                if(!answer)
                {
                    NS_RELEASE(obj);
                    aTearOff->SetInterface(nsnull);
                    return NS_ERROR_NO_INTERFACE;
                }
            }
        }

        nsIXPCSecurityManager* sm;
           sm = ccx.GetXPCContext()->GetAppropriateSecurityManager(
                                nsIXPCSecurityManager::HOOK_CREATE_WRAPPER);
        if(sm && NS_FAILED(sm->
                    CanCreateWrapper(ccx, *iid, identity,
                                     GetClassInfo(), GetSecurityInfoAddr())))
        {
            // the security manager vetoed. It should have set an exception.
            NS_RELEASE(obj);
            aTearOff->SetInterface(nsnull);
            return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
        }
    }
    // We are relocked from here on...

    // If this is not already in our set we need to extend our set.
    // Note: we do not cache the result of the previous call to HasInterface()
    // because we unlocked and called out in the interim and the result of the
    // previous call might not be correct anymore.

    if(!mSet->HasInterface(aInterface) && !ExtendSet(ccx, aInterface))
    {
        NS_RELEASE(obj);
        aTearOff->SetInterface(nsnull);
        return NS_ERROR_NO_INTERFACE;
    }

    aTearOff->SetInterface(aInterface);
    aTearOff->SetNative(obj);
#ifdef XPC_IDISPATCH_SUPPORT
    // Are we building a tearoff for IDispatch?
    if(iid->Equals(NSID_IDISPATCH))
    {
        aTearOff->SetIDispatch(ccx);
    }  
#endif
    if(needJSObject && !InitTearOffJSObject(ccx, aTearOff))
        return NS_ERROR_OUT_OF_MEMORY;

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1608 of file xpcwrappednative.cpp.

{
    // This is only called while locked (during XPCWrappedNative::FindTearOff).

    JSObject* obj = JS_NewObject(ccx, &XPC_WN_Tearoff_JSClass,
                                 GetScope()->GetPrototypeJSObject(),
                                 mFlatJSObject);

    if(!obj || !JS_SetPrivate(ccx, obj, to))
        return JS_FALSE;

    // Propagate the system flag from parent to child.
    if(JS_IsSystemObject(ccx, mFlatJSObject))
        JS_FlagSystemObject(ccx, obj);

    to->SetJSObject(obj);
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1836 of file xpcprivate.h.

        {return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;}
NS_DECL_ISUPPORTS NS_DECL_NSIXPCONNECTJSOBJECTHOLDER NS_DECL_NSIXPCONNECTWRAPPEDNATIVE JSBool XPCWrappedNative::IsValid ( ) const [inline]

Definition at line 1830 of file xpcprivate.h.

{return nsnull != mFlatJSObject;}

Here is the caller graph for this function:

Definition at line 1304 of file xpcwrappednative.cpp.

{
    XPCAutoLock al(GetLock()); // hold the lock throughout

    for(
        XPCWrappedNativeTearOffChunk* chunk = &mFirstChunk;
        chunk != nsnull;
        chunk = chunk->mNextChunk)
    {
        XPCWrappedNativeTearOff* tearOff = chunk->mTearOffs;
        XPCWrappedNativeTearOff* const end = tearOff + 
            XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK;
        for(
            tearOff = chunk->mTearOffs;
            tearOff < end; 
            tearOff++)
        {
            if(tearOff->GetInterface() == aInterface)
            {
                return tearOff;
            }
        }
    }
    return nsnull;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void XPCWrappedNative::Mark ( ) const [inline]

Definition at line 1979 of file xpcprivate.h.

    {
        mSet->Mark();
        if(mScriptableInfo) mScriptableInfo->Mark();
        if(HasProto()) mMaybeProto->Mark();
    }

Here is the call graph for this function:

Definition at line 1987 of file xpcprivate.h.

    {
        if(mScriptableInfo) mScriptableInfo->Mark();
        if(HasProto()) mMaybeProto->MarkBeforeJSFinalize(cx);
        if(mNativeWrapper)
        {
            JS_MarkGCThing(cx, mNativeWrapper, 
                           "XPCWrappedNative::mNativeWrapper", nsnull);
        }
    }

Here is the call graph for this function:

Here is the caller graph for this function:

nsISupports* nsIXPConnectWrappedNative::Native ( ) const [inline, inherited]

Faster access to the native object from C++.

Will never return null.

Definition at line 188 of file nsIXPConnect.idl.

{ return mIdentity; }
nsresult XPCWrappedNative::ReparentWrapperIfFound ( XPCCallContext ccx,
XPCWrappedNativeScope aOldScope,
XPCWrappedNativeScope aNewScope,
JSObject aNewParent,
nsISupports *  aCOMObj,
XPCWrappedNative **  aWrapper 
) [static]

Definition at line 1031 of file xpcwrappednative.cpp.

{
    XPCNativeInterface* iface =
        XPCNativeInterface::GetISupports(ccx);

    if(!iface)
        return NS_ERROR_FAILURE;

    nsresult rv;
    XPCWrappedNative* wrapper;

    rv = XPCWrappedNative::GetUsedOnly(ccx, aCOMObj, aOldScope, iface, &wrapper);
    if(NS_FAILED(rv))
        return rv;

    if(!wrapper || !wrapper->IsValid())
    {
        NS_IF_RELEASE(wrapper);
        *aWrapper = nsnull;
        return NS_OK;
    }

    if(aOldScope != aNewScope)
    {
        // Oh, so now we need to move the wrapper to a different scope.

        AutoMarkingWrappedNativeProtoPtr oldProto(ccx);
        AutoMarkingWrappedNativeProtoPtr newProto(ccx);

        if(wrapper->HasProto())
        {
            oldProto = wrapper->GetProto();
            XPCNativeScriptableInfo *info = oldProto->GetScriptableInfo();
            XPCNativeScriptableCreateInfo ci(*info);
            newProto =
                XPCWrappedNativeProto::GetNewOrUsed(ccx, aNewScope,
                                                    oldProto->GetClassInfo(),
                                                    &ci,
                                                    !oldProto->IsShared(),
                                                    (info->GetJSClass()->flags & JSCLASS_IS_GLOBAL));
            if(!newProto)
            {
                NS_RELEASE(wrapper);
                return NS_ERROR_FAILURE;
            }
        }

        Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
        Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap();

        {   // scoped lock
            XPCAutoLock lock(aOldScope->GetRuntime()->GetMapLock());

            // We only try to fixup the __proto__ JSObject if the wrapper
            // is directly using that of its XPCWrappedNativeProto.

            if(wrapper->HasProto() &&
               JS_GetPrototype(ccx, wrapper->GetFlatJSObject()) ==
               oldProto->GetJSProtoObject())
            {
                if(!JS_SetPrototype(ccx, wrapper->GetFlatJSObject(),
                                    newProto->GetJSProtoObject()))
                {
                    // this is bad, very bad
                    NS_ERROR("JS_SetPrototype failed");
                    NS_RELEASE(wrapper);
                    return NS_ERROR_FAILURE;
                }
            }
            else
            {
                NS_WARNING("Moving XPConnect wrappedNative to new scope, "
                           "but can't fixup __proto__");
            }

            oldMap->Remove(wrapper);

            if(wrapper->HasProto())
                wrapper->mMaybeProto = newProto;

            // If the wrapper has no scriptable or it has a non-shared
            // scriptable, then we don't need to mess with it.
            // Otherwise...

            if(wrapper->mScriptableInfo &&
               wrapper->mScriptableInfo == oldProto->GetScriptableInfo())
            {
                // The new proto had better have the same JSClass stuff as the
                // old one! We maintain a runtime wide unique map of this stuff.
                // So, if these don't match then the caller is doing something
                // bad here.

                NS_ASSERTION(
                     oldProto->GetScriptableInfo()->GetScriptableShared() ==
                     newProto->GetScriptableInfo()->GetScriptableShared(),
                    "Changing proto is also changing JSObject Classname or "
                    "helper's nsIXPScriptable flags. This is not allowed!");

                wrapper->mScriptableInfo = newProto->GetScriptableInfo();
            }

            NS_ASSERTION(!newMap->Find(wrapper->GetIdentityObject()),
                         "wrapper already in new scope!");

            (void) newMap->Add(wrapper);
        }
    }

    // Now we can just fix up the parent and return the wrapper

    if(!JS_SetParent(ccx, wrapper->GetFlatJSObject(), aNewParent))
    {
        NS_RELEASE(wrapper);
        return NS_ERROR_FAILURE;
    }

    *aWrapper = wrapper;
    return NS_OK;
}

Here is the call graph for this function:

static JSBool XPCWrappedNative::SetAttribute ( XPCCallContext ccx) [inline, static]

Definition at line 1967 of file xpcprivate.h.

        {return CallMethod(ccx, CALL_SETTER);}

Here is the caller graph for this function:

Definition at line 2035 of file xpcprivate.h.

Here is the caller graph for this function:

void XPCWrappedNative::SetSet ( XPCNativeSet set) [inline, private]

Definition at line 1873 of file xpcprivate.h.

{XPCAutoLock al(GetLock()); mSet = set;}

Definition at line 665 of file xpcinlines.h.

{
    XPCWrappedNativeTearOffChunk* chunk;
    for(chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk)
    {
        XPCWrappedNativeTearOff* to = chunk->mTearOffs;
        for(int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK; i > 0; i--, to++)
        {
            JSBool marked = to->IsMarked();
            to->Unmark();
            if(marked)
                continue;

            // If this tearoff does not have a live dedicated JSObject,
            // then let's recycle it.
            if(!to->GetJSObject())
            {
                nsISupports* obj = to->GetNative();
                if(obj)
                {
                    obj->Release();
                    to->SetNative(nsnull);
                }
                to->SetInterface(nsnull);
            }
        }
    }
}

Here is the call graph for this function:

Definition at line 967 of file xpcwrappednative.cpp.

{
    DEBUG_TrackShutdownWrapper(this);

    if(!IsValid())
        return;

    // The long standing strategy is to leak some objects still held at shutdown.
    // The general problem is that propagating release out of xpconnect at
    // shutdown time causes a world of problems.

    // We leak mIdentity (see above).

    // short circuit future finalization
    JS_SetPrivate(ccx, mFlatJSObject, nsnull);
    mFlatJSObject = nsnull; // This makes 'IsValid()' return false.

    XPCWrappedNativeProto* proto = GetProto();

    if(HasProto())
        proto->SystemIsBeingShutDown(ccx);

    if(mScriptableInfo &&
       (!HasProto() ||
        (proto && proto->GetScriptableInfo() != mScriptableInfo)))
    {
        delete mScriptableInfo;
    }

    // cleanup the tearoffs...

    XPCWrappedNativeTearOffChunk* chunk;
    for(chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk)
    {
        XPCWrappedNativeTearOff* to = chunk->mTearOffs;
        for(int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK-1; i >= 0; i--, to++)
        {
            if(to->GetJSObject())
            {
                JS_SetPrivate(ccx, to->GetJSObject(), nsnull);
#ifdef XPC_IDISPATCH_SUPPORT
                if(to->IsIDispatch())
                    delete to->GetIDispatchInfo();
#endif
                to->SetJSObject(nsnull);
            }
            // We leak the tearoff mNative
            // (for the same reason we leak mIdentity - see above).
            to->SetNative(nsnull);
            to->SetInterface(nsnull);
        }
    }

    if(mFirstChunk.mNextChunk)
    {
        delete mFirstChunk.mNextChunk;
        mFirstChunk.mNextChunk = nsnull;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1840 of file xpcprivate.h.

Definition at line 2539 of file xpcwrappednative.cpp.

{
#ifdef DEBUG
#  define FMT_ADDR " @ 0x%p"
#  define FMT_STR(str) str
#  define PARAM_ADDR(w) , w
#else
#  define FMT_ADDR ""
#  define FMT_STR(str)
#  define PARAM_ADDR(w)
#endif

    char* sz = nsnull;
    char* name = nsnull;

    XPCNativeScriptableInfo* si = GetScriptableInfo();
    if(si)
        name = JS_smprintf("%s", si->GetJSClass()->name);
    if(to)
    {
        const char* fmt = name ? " (%s)" : "%s";
        name = JS_sprintf_append(name, fmt,
                                 to->GetInterface()->GetNameString());
    }
    else if(!name)
    {
        XPCNativeSet* set = GetSet();
        XPCNativeInterface** array = set->GetInterfaceArray();
        PRUint16 count = set->GetInterfaceCount();

        if(count == 1)
            name = JS_sprintf_append(name, "%s", array[0]->GetNameString());
        else if(count == 2 &&
                array[0] == XPCNativeInterface::GetISupports(ccx))
        {
            name = JS_sprintf_append(name, "%s", array[1]->GetNameString());
        }
        else
        {
            for(PRUint16 i = 0; i < count; i++)
            {
                const char* fmt = (i == 0) ?
                                    "(%s" : (i == count-1) ?
                                        ", %s)" : ", %s";
                name = JS_sprintf_append(name, fmt,
                                         array[i]->GetNameString());
            }
        }
    }

    if(!name)
    {
        return nsnull;
    }
    const char* fmt = "[xpconnect wrapped %s" FMT_ADDR FMT_STR(" (native")
        FMT_ADDR FMT_STR(")") "]";
    if(si)
    {
        fmt = "[object %s" FMT_ADDR FMT_STR(" (native") FMT_ADDR FMT_STR(")") "]";
    }
    sz = JS_smprintf(fmt, name PARAM_ADDR(this) PARAM_ADDR(mIdentity));

    JS_smprintf_free(name);


    return sz;

#undef FMT_ADDR
#undef PARAM_ADDR
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1845 of file xpcprivate.h.


Member Data Documentation

union { ... } [private]

Definition at line 156 of file nsIXPConnect.idl.

Definition at line 164 of file nsIXPConnect.idl.

Definition at line 2082 of file xpcprivate.h.

Definition at line 2080 of file xpcprivate.h.

nsISupports* nsIXPConnectWrappedNative::mIdentity [protected, inherited]

Definition at line 191 of file nsIXPConnect.idl.

Definition at line 2083 of file xpcprivate.h.

Definition at line 2081 of file xpcprivate.h.

Definition at line 2079 of file xpcprivate.h.

readonly attribute nsISupports nsIXPConnectWrappedNative::Native [inherited]

Definition at line 163 of file nsIXPConnect.idl.

These are here as an aid to nsIXPCScriptable implementors.

Definition at line 170 of file nsIXPConnect.idl.


The documentation for this class was generated from the following files: