Back to index

lightning-sunbird  0.9+nobinonly
xpcinlines.h
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code, released
00017  * March 31, 1998.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1998
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   John Bandhauer <jband@netscape.com> (original author)
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 /* private inline methods (#include'd by xpcprivate.h). */
00042 
00043 #ifndef xpcinlines_h___
00044 #define xpcinlines_h___
00045 
00046 /***************************************************************************/
00047 
00048 inline JSBool
00049 XPCCallContext::IsValid() const
00050 {
00051     return mState != INIT_FAILED;
00052 }
00053 
00054 inline nsXPConnect*
00055 XPCCallContext::GetXPConnect() const
00056 {
00057     CHECK_STATE(HAVE_CONTEXT);
00058     return mXPC;
00059 }
00060 
00061 inline XPCJSRuntime*
00062 XPCCallContext::GetRuntime() const
00063 {
00064     CHECK_STATE(HAVE_CONTEXT);
00065     return mXPCContext->GetRuntime();
00066 }
00067 
00068 inline XPCPerThreadData*
00069 XPCCallContext::GetThreadData() const
00070 {
00071     CHECK_STATE(HAVE_CONTEXT);
00072     return mThreadData;
00073 }
00074 
00075 inline XPCContext*
00076 XPCCallContext::GetXPCContext() const
00077 {
00078     CHECK_STATE(HAVE_CONTEXT);
00079     return mXPCContext;
00080 }
00081 
00082 inline JSContext*
00083 XPCCallContext::GetJSContext() const
00084 {
00085     CHECK_STATE(HAVE_CONTEXT);
00086     return mJSContext;
00087 }
00088 
00089 inline JSContext*
00090 XPCCallContext::GetSafeJSContext() const
00091 {
00092     CHECK_STATE(HAVE_CONTEXT);
00093     JSContext* cx;
00094     if(NS_SUCCEEDED(mThreadData->GetJSContextStack()->GetSafeJSContext(&cx)))
00095         return cx;
00096     return nsnull;
00097 }
00098 
00099 inline JSBool
00100 XPCCallContext::GetContextPopRequired() const
00101 {
00102     CHECK_STATE(HAVE_CONTEXT);
00103     return mContextPopRequired;
00104 }
00105 
00106 inline XPCContext::LangType
00107 XPCCallContext::GetCallerLanguage() const
00108 {
00109     CHECK_STATE(HAVE_CONTEXT);
00110     return mCallerLanguage;
00111 }
00112 
00113 inline XPCContext::LangType
00114 XPCCallContext::GetPrevCallerLanguage() const
00115 {
00116     CHECK_STATE(HAVE_CONTEXT);
00117     return mPrevCallerLanguage;
00118 }
00119 
00120 inline XPCCallContext*
00121 XPCCallContext::GetPrevCallContext() const
00122 {
00123     CHECK_STATE(HAVE_CONTEXT);
00124     return mPrevCallContext;
00125 }
00126 
00127 inline JSObject*
00128 XPCCallContext::GetOperandJSObject() const
00129 {
00130     CHECK_STATE(HAVE_OBJECT);
00131     return mOperandJSObject;
00132 }
00133 
00134 inline JSObject*
00135 XPCCallContext::GetCurrentJSObject() const
00136 {
00137     CHECK_STATE(HAVE_OBJECT);
00138     return mCurrentJSObject;
00139 }
00140 
00141 inline JSObject*
00142 XPCCallContext::GetFlattenedJSObject() const
00143 {
00144     CHECK_STATE(HAVE_OBJECT);
00145     return mFlattenedJSObject;
00146 }
00147 
00148 inline nsISupports*
00149 XPCCallContext::GetIdentityObject() const
00150 {
00151     CHECK_STATE(HAVE_OBJECT);
00152     return mWrapper->GetIdentityObject();
00153 }
00154 
00155 inline XPCWrappedNative*
00156 XPCCallContext::GetWrapper() const
00157 {
00158     if(mState == INIT_FAILED)
00159         return nsnull;
00160 
00161     CHECK_STATE(HAVE_OBJECT);
00162     return mWrapper;
00163 }
00164 
00165 inline JSBool
00166 XPCCallContext::CanGetTearOff() const
00167 {
00168     return mState >= HAVE_OBJECT;
00169 }
00170 
00171 inline XPCWrappedNativeTearOff*
00172 XPCCallContext::GetTearOff() const
00173 {
00174     CHECK_STATE(HAVE_OBJECT);
00175     return mTearOff;
00176 }
00177 
00178 inline XPCNativeScriptableInfo*
00179 XPCCallContext::GetScriptableInfo() const
00180 {
00181     CHECK_STATE(HAVE_OBJECT);
00182     return mScriptableInfo;
00183 }
00184 
00185 inline JSBool
00186 XPCCallContext::CanGetSet() const
00187 {
00188     return mState >= HAVE_NAME;
00189 }
00190 
00191 inline XPCNativeSet*
00192 XPCCallContext::GetSet() const
00193 {
00194     CHECK_STATE(HAVE_NAME);
00195     return mSet;
00196 }
00197 
00198 inline JSBool
00199 XPCCallContext::CanGetInterface() const
00200 {
00201     return mState >= HAVE_NAME;
00202 }
00203 
00204 inline XPCNativeInterface*
00205 XPCCallContext::GetInterface() const
00206 {
00207     CHECK_STATE(HAVE_NAME);
00208     return mInterface;
00209 }
00210 
00211 inline XPCNativeMember*
00212 XPCCallContext::GetMember() const
00213 {
00214     CHECK_STATE(HAVE_NAME);
00215     return mMember;
00216 }
00217 
00218 inline JSBool
00219 XPCCallContext::HasInterfaceAndMember() const
00220 {
00221     return mState >= HAVE_NAME && mInterface && (mMember
00222 #ifdef XPC_IDISPATCH_SUPPORT
00223         || mIDispatchMember
00224 #endif
00225         );
00226 }
00227 
00228 inline jsval
00229 XPCCallContext::GetName() const
00230 {
00231     CHECK_STATE(HAVE_NAME);
00232     return mName;
00233 }
00234 
00235 inline JSBool
00236 XPCCallContext::GetStaticMemberIsLocal() const
00237 {
00238     CHECK_STATE(HAVE_NAME);
00239     return mStaticMemberIsLocal;
00240 }
00241 
00242 inline uintN
00243 XPCCallContext::GetArgc() const
00244 {
00245     CHECK_STATE(READY_TO_CALL);
00246     return mArgc;
00247 }
00248 
00249 inline jsval*
00250 XPCCallContext::GetArgv() const
00251 {
00252     CHECK_STATE(READY_TO_CALL);
00253     return mArgv;
00254 }
00255 
00256 inline jsval*
00257 XPCCallContext::GetRetVal() const
00258 {
00259     CHECK_STATE(READY_TO_CALL);
00260     return mRetVal;
00261 }
00262 
00263 inline JSBool
00264 XPCCallContext::GetExceptionWasThrown() const
00265 {
00266     CHECK_STATE(READY_TO_CALL);
00267     return mExceptionWasThrown;
00268 }
00269 
00270 inline JSBool
00271 XPCCallContext::GetReturnValueWasSet() const
00272 {
00273     CHECK_STATE(READY_TO_CALL);
00274     return mReturnValueWasSet;
00275 }
00276 
00277 inline void
00278 XPCCallContext::SetRetVal(jsval val)
00279 {
00280     CHECK_STATE(HAVE_ARGS);
00281     if(mRetVal)
00282         *mRetVal = val;
00283 }
00284 
00285 inline jsval
00286 XPCCallContext::GetResolveName() const
00287 {
00288     CHECK_STATE(HAVE_CONTEXT);
00289     return mThreadData->GetResolveName();
00290 }
00291 
00292 inline jsval
00293 XPCCallContext::SetResolveName(jsval name)
00294 {
00295     CHECK_STATE(HAVE_CONTEXT);
00296     return mThreadData->SetResolveName(name);
00297 }
00298 
00299 inline XPCWrappedNative*
00300 XPCCallContext::GetResolvingWrapper() const
00301 {
00302     CHECK_STATE(HAVE_OBJECT);
00303     return mThreadData->GetResolvingWrapper();
00304 }
00305 
00306 inline XPCWrappedNative*
00307 XPCCallContext::SetResolvingWrapper(XPCWrappedNative* w)
00308 {
00309     CHECK_STATE(HAVE_OBJECT);
00310     return mThreadData->SetResolvingWrapper(w);
00311 }
00312 
00313 inline JSObject*
00314 XPCCallContext::GetCallee() const
00315 {
00316     NS_ASSERTION(mCallerLanguage == NATIVE_CALLER,
00317                  "GetCallee() doesn't make sense");
00318     return mCallee;
00319 }
00320 
00321 inline void
00322 XPCCallContext::SetCallee(JSObject* callee)
00323 {
00324     NS_ASSERTION(mCallerLanguage == NATIVE_CALLER,
00325                  "SetCallee() doesn't make sense");
00326     mCallee = callee;
00327 }
00328 
00329 inline PRUint16
00330 XPCCallContext::GetMethodIndex() const
00331 {
00332     CHECK_STATE(HAVE_OBJECT);
00333     return mMethodIndex;
00334 }
00335 
00336 inline void
00337 XPCCallContext::SetMethodIndex(PRUint16 index)
00338 {
00339     CHECK_STATE(HAVE_OBJECT);
00340     mMethodIndex = index;
00341 }
00342 
00343 inline JSBool   
00344 XPCCallContext::GetDestroyJSContextInDestructor() const
00345 {
00346     CHECK_STATE(HAVE_CONTEXT);
00347     return mDestroyJSContextInDestructor;
00348 }
00349 
00350 inline void
00351 XPCCallContext::SetDestroyJSContextInDestructor(JSBool b)
00352 {
00353     CHECK_STATE(HAVE_CONTEXT);
00354     mDestroyJSContextInDestructor = b;
00355 }
00356 
00357 /***************************************************************************/
00358 
00359 inline const nsIID*
00360 XPCNativeInterface::GetIID() const
00361 {
00362     const nsIID* iid;
00363     return NS_SUCCEEDED(mInfo->GetIIDShared(&iid)) ? iid : nsnull;
00364 }
00365 
00366 inline const char*
00367 XPCNativeInterface::GetNameString() const
00368 {
00369     const char* name;
00370     return NS_SUCCEEDED(mInfo->GetNameShared(&name)) ? name : nsnull;
00371 }
00372 
00373 inline XPCNativeMember*
00374 XPCNativeInterface::FindMember(jsval name) const
00375 {
00376     const XPCNativeMember* member = mMembers;
00377     for(int i = (int) mMemberCount; i > 0; i--, member++)
00378         if(member->GetName() == name)
00379             return NS_CONST_CAST(XPCNativeMember*, member);
00380     return nsnull;
00381 }
00382 
00383 inline JSBool
00384 XPCNativeInterface::HasAncestor(const nsIID* iid) const
00385 {
00386     PRBool found = PR_FALSE;
00387     mInfo->HasAncestor(iid, &found);
00388     return found;
00389 }
00390 
00391 inline void
00392 XPCNativeInterface::DealWithDyingGCThings(JSContext* cx, XPCJSRuntime* rt)
00393 {
00394     XPCNativeMember* member = mMembers;
00395     for(int i = (int) mMemberCount; i > 0; i--, member++)
00396         member->DealWithDyingGCThings(cx, rt);
00397 }
00398 
00399 /***************************************************************************/
00400 
00401 inline JSBool
00402 XPCNativeSet::FindMember(jsval name, XPCNativeMember** pMember,
00403                          PRUint16* pInterfaceIndex) const
00404 {
00405     XPCNativeInterface* const * iface;
00406     int count = (int) mInterfaceCount;
00407     int i;
00408 
00409     // look for interface names first
00410 
00411     for(i = 0, iface = mInterfaces; i < count; i++, iface++)
00412     {
00413         if(name == (*iface)->GetName())
00414         {
00415             if(pMember)
00416                 *pMember = nsnull;
00417             if(pInterfaceIndex)
00418                 *pInterfaceIndex = (PRUint16) i;
00419             return JS_TRUE;
00420         }
00421     }
00422 
00423     // look for method names
00424     for(i = 0, iface = mInterfaces; i < count; i++, iface++)
00425     {
00426         XPCNativeMember* member = (*iface)->FindMember(name);
00427         if(member)
00428         {
00429             if(pMember)
00430                 *pMember = member;
00431             if(pInterfaceIndex)
00432                 *pInterfaceIndex = (PRUint16) i;
00433             return JS_TRUE;
00434         }
00435     }
00436     return JS_FALSE;
00437 }
00438 
00439 inline JSBool
00440 XPCNativeSet::FindMember(jsval name, XPCNativeMember** pMember,
00441                          XPCNativeInterface** pInterface) const
00442 {
00443     PRUint16 index;
00444     if(!FindMember(name, pMember, &index))
00445         return JS_FALSE;
00446     *pInterface = mInterfaces[index];
00447     return JS_TRUE;
00448 }
00449 
00450 inline JSBool
00451 XPCNativeSet::FindMember(jsval name,
00452                          XPCNativeMember** pMember,
00453                          XPCNativeInterface** pInterface,
00454                          XPCNativeSet* protoSet,
00455                          JSBool* pIsLocal) const
00456 {
00457     XPCNativeMember* Member;
00458     XPCNativeInterface* Interface;
00459     XPCNativeMember* protoMember;
00460 
00461     if(!FindMember(name, &Member, &Interface))
00462         return JS_FALSE;
00463 
00464     *pMember = Member;
00465     *pInterface = Interface;
00466 
00467     *pIsLocal =
00468         !Member ||
00469         !protoSet ||
00470         (protoSet != this &&
00471          !protoSet->MatchesSetUpToInterface(this, Interface) &&
00472           (!protoSet->FindMember(name, &protoMember, (PRUint16*)nsnull) ||
00473            protoMember != Member));
00474 
00475     return JS_TRUE;
00476 }
00477 
00478 inline XPCNativeInterface*
00479 XPCNativeSet::FindNamedInterface(jsval name) const
00480 {
00481     XPCNativeInterface* const * pp = mInterfaces;
00482 
00483     for(int i = (int) mInterfaceCount; i > 0; i--, pp++)
00484     {
00485         XPCNativeInterface* iface = *pp;
00486 
00487         if(name == iface->GetName())
00488             return iface;
00489     }
00490     return nsnull;
00491 }
00492 
00493 inline XPCNativeInterface*
00494 XPCNativeSet::FindInterfaceWithIID(const nsIID& iid) const
00495 {
00496     XPCNativeInterface* const * pp = mInterfaces;
00497 
00498     for(int i = (int) mInterfaceCount; i > 0; i--, pp++)
00499     {
00500         XPCNativeInterface* iface = *pp;
00501 
00502         if(iface->GetIID()->Equals(iid))
00503             return iface;
00504     }
00505     return nsnull;
00506 }
00507 
00508 inline JSBool
00509 XPCNativeSet::HasInterface(XPCNativeInterface* aInterface) const
00510 {
00511     XPCNativeInterface* const * pp = mInterfaces;
00512 
00513     for(int i = (int) mInterfaceCount; i > 0; i--, pp++)
00514     {
00515         if(aInterface == *pp)
00516             return JS_TRUE;
00517     }
00518     return JS_FALSE;
00519 }
00520 
00521 inline JSBool
00522 XPCNativeSet::HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const
00523 {
00524     const nsIID* iid = aInterface->GetIID();
00525 
00526     // We can safely skip the first interface which is *always* nsISupports.
00527     XPCNativeInterface* const * pp = mInterfaces+1;
00528     for(int i = (int) mInterfaceCount; i > 1; i--, pp++)
00529         if((*pp)->HasAncestor(iid))
00530             return JS_TRUE;
00531 
00532     // This is rare, so check last.
00533     if(iid == &NS_GET_IID(nsISupports))
00534         return PR_TRUE;
00535 
00536     return JS_FALSE;
00537 }
00538 
00539 inline JSBool
00540 XPCNativeSet::MatchesSetUpToInterface(const XPCNativeSet* other,
00541                                       XPCNativeInterface* iface) const
00542 {
00543     int count = JS_MIN((int)mInterfaceCount, (int)other->mInterfaceCount);
00544 
00545     XPCNativeInterface* const * pp1 = mInterfaces;
00546     XPCNativeInterface* const * pp2 = other->mInterfaces;
00547 
00548     for(int i = (int) count; i > 0; i--, pp1++, pp2++)
00549     {
00550         XPCNativeInterface* cur = (*pp1);
00551         if(cur != (*pp2))
00552             return JS_FALSE;
00553         if(cur == iface)
00554             return JS_TRUE;
00555     }
00556     return JS_FALSE;
00557 }
00558 
00559 inline void XPCNativeSet::Mark()
00560 {
00561     if(IsMarked())
00562         return;
00563 
00564     XPCNativeInterface* const * pp = mInterfaces;
00565 
00566     for(int i = (int) mInterfaceCount; i > 0; i--, pp++)
00567         (*pp)->Mark();
00568 
00569     MarkSelfOnly();
00570 }
00571 
00572 #ifdef DEBUG
00573 inline void XPCNativeSet::ASSERT_NotMarked()
00574 {
00575     NS_ASSERTION(!IsMarked(), "bad");
00576 
00577     XPCNativeInterface* const * pp = mInterfaces;
00578 
00579     for(int i = (int) mInterfaceCount; i > 0; i--, pp++)
00580         NS_ASSERTION(!(*pp)->IsMarked(), "bad");
00581 }
00582 #endif
00583 
00584 /***************************************************************************/
00585 
00586 inline
00587 JSObject* XPCWrappedNativeTearOff::GetJSObject() const
00588 {
00589 #ifdef XPC_IDISPATCH_SUPPORT
00590     if(IsIDispatch())
00591     {
00592         XPCDispInterface * iface = GetIDispatchInfo();
00593         return iface ? iface->GetJSObject() : nsnull;
00594     }
00595 #endif
00596     return mJSObject;
00597 }
00598 
00599 inline
00600 void XPCWrappedNativeTearOff::SetJSObject(JSObject*  JSObj)
00601 {
00602 #ifdef XPC_IDISPATCH_SUPPORT
00603     if(IsIDispatch())
00604     {
00605         XPCDispInterface* iface = GetIDispatchInfo();
00606         if(iface)
00607             iface->SetJSObject(JSObj);
00608     }
00609     else
00610 #endif
00611         mJSObject = JSObj;
00612 }
00613 
00614 #ifdef XPC_IDISPATCH_SUPPORT
00615 inline void
00616 XPCWrappedNativeTearOff::SetIDispatch(JSContext* cx)
00617 {
00618     mJSObject = (JSObject*)(((jsword)
00619         ::XPCDispInterface::NewInstance(cx,
00620                                           mNative)) | 2);
00621 }
00622 
00623 inline XPCDispInterface* 
00624 XPCWrappedNativeTearOff::GetIDispatchInfo() const
00625 {
00626     NS_ASSERTION((jsword)mJSObject & 2, "XPCWrappedNativeTearOff::GetIDispatchInfo "
00627                                 "called on a non IDispatch interface");
00628     return NS_REINTERPRET_CAST(XPCDispInterface*,
00629                                (((jsword)mJSObject) & ~JSOBJECT_MASK));
00630 }
00631 
00632 inline JSBool
00633 XPCWrappedNativeTearOff::IsIDispatch() const
00634 {
00635     return (JSBool)(((jsword)mJSObject) & IDISPATCH_BIT);
00636 }
00637 
00638 #endif
00639 
00640 inline
00641 XPCWrappedNativeTearOff::~XPCWrappedNativeTearOff()
00642 {
00643     NS_ASSERTION(!(GetInterface()||GetNative()||GetJSObject()), "tearoff not empty in dtor");
00644 #ifdef XPC_IDISPATCH_SUPPORT
00645     if(IsIDispatch())
00646         delete GetIDispatchInfo();
00647 #endif
00648 }
00649 
00650 /***************************************************************************/
00651 
00652 inline JSBool
00653 XPCWrappedNative::HasInterfaceNoQI(XPCNativeInterface* aInterface)
00654 {
00655     return GetSet()->HasInterface(aInterface);
00656 }
00657 
00658 inline JSBool
00659 XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid)
00660 {
00661     return nsnull != GetSet()->FindInterfaceWithIID(iid);
00662 }
00663 
00664 inline void
00665 XPCWrappedNative::SweepTearOffs()
00666 {
00667     XPCWrappedNativeTearOffChunk* chunk;
00668     for(chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk)
00669     {
00670         XPCWrappedNativeTearOff* to = chunk->mTearOffs;
00671         for(int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK; i > 0; i--, to++)
00672         {
00673             JSBool marked = to->IsMarked();
00674             to->Unmark();
00675             if(marked)
00676                 continue;
00677 
00678             // If this tearoff does not have a live dedicated JSObject,
00679             // then let's recycle it.
00680             if(!to->GetJSObject())
00681             {
00682                 nsISupports* obj = to->GetNative();
00683                 if(obj)
00684                 {
00685                     obj->Release();
00686                     to->SetNative(nsnull);
00687                 }
00688                 to->SetInterface(nsnull);
00689             }
00690         }
00691     }
00692 }
00693 
00694 /***************************************************************************/
00695 
00696 inline JSBool
00697 xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsval idval)
00698 {
00699     JSProperty* prop;
00700     JSObject* obj2;
00701     jsid id;    
00702 
00703     if(!JS_ValueToId(cx, idval, &id) ||
00704        !OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
00705         return JS_FALSE;
00706     if(prop)
00707         OBJ_DROP_PROPERTY(cx, obj2, prop);
00708     return JS_TRUE;
00709 }
00710 
00711 inline
00712 JSBool ThrowBadParam(nsresult rv, uintN paramNum, XPCCallContext& ccx)
00713 {
00714     XPCThrower::ThrowBadParam(rv, paramNum, ccx);
00715     return JS_FALSE;
00716 }
00717 
00718 inline 
00719 void ThrowBadResult(nsresult result, XPCCallContext& ccx)
00720 {
00721     XPCThrower::ThrowBadResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE,
00722                                result, ccx);
00723 }
00724 
00725 /***************************************************************************/
00726 
00727 #endif /* xpcinlines_h___ */