michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim: set ts=8 sts=4 et sw=4 tw=99: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* private inline methods (#include'd by xpcprivate.h). */ michael@0: michael@0: #ifndef xpcinlines_h___ michael@0: #define xpcinlines_h___ michael@0: michael@0: #include michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: inline void michael@0: XPCJSRuntime::AddVariantRoot(XPCTraceableVariant* variant) michael@0: { michael@0: variant->AddToRootSet(&mVariantRoots); michael@0: } michael@0: michael@0: inline void michael@0: XPCJSRuntime::AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS) michael@0: { michael@0: wrappedJS->AddToRootSet(&mWrappedJSRoots); michael@0: } michael@0: michael@0: inline void michael@0: XPCJSRuntime::AddObjectHolderRoot(XPCJSObjectHolder* holder) michael@0: { michael@0: holder->AddToRootSet(&mObjectHolderRoots); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: inline bool michael@0: XPCCallContext::IsValid() const michael@0: { michael@0: return mState != INIT_FAILED; michael@0: } michael@0: michael@0: inline XPCJSRuntime* michael@0: XPCCallContext::GetRuntime() const michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return mXPCContext->GetRuntime(); michael@0: } michael@0: michael@0: inline XPCContext* michael@0: XPCCallContext::GetXPCContext() const michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return mXPCContext; michael@0: } michael@0: michael@0: inline JSContext* michael@0: XPCCallContext::GetJSContext() const michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return mJSContext; michael@0: } michael@0: michael@0: inline XPCContext::LangType michael@0: XPCCallContext::GetCallerLanguage() const michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return mCallerLanguage; michael@0: } michael@0: michael@0: inline XPCContext::LangType michael@0: XPCCallContext::GetPrevCallerLanguage() const michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return mPrevCallerLanguage; michael@0: } michael@0: michael@0: inline XPCCallContext* michael@0: XPCCallContext::GetPrevCallContext() const michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return mPrevCallContext; michael@0: } michael@0: michael@0: inline JSObject* michael@0: XPCCallContext::GetFlattenedJSObject() const michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return mFlattenedJSObject; michael@0: } michael@0: michael@0: inline nsISupports* michael@0: XPCCallContext::GetIdentityObject() const michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: if (mWrapper) michael@0: return mWrapper->GetIdentityObject(); michael@0: return mFlattenedJSObject ? michael@0: static_cast(xpc_GetJSPrivate(mFlattenedJSObject)) : michael@0: nullptr; michael@0: } michael@0: michael@0: inline XPCWrappedNative* michael@0: XPCCallContext::GetWrapper() const michael@0: { michael@0: if (mState == INIT_FAILED) michael@0: return nullptr; michael@0: michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return mWrapper; michael@0: } michael@0: michael@0: inline XPCWrappedNativeProto* michael@0: XPCCallContext::GetProto() const michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return mWrapper ? mWrapper->GetProto() : nullptr; michael@0: } michael@0: michael@0: inline bool michael@0: XPCCallContext::CanGetTearOff() const michael@0: { michael@0: return mState >= HAVE_OBJECT; michael@0: } michael@0: michael@0: inline XPCWrappedNativeTearOff* michael@0: XPCCallContext::GetTearOff() const michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return mTearOff; michael@0: } michael@0: michael@0: inline XPCNativeScriptableInfo* michael@0: XPCCallContext::GetScriptableInfo() const michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return mScriptableInfo; michael@0: } michael@0: michael@0: inline bool michael@0: XPCCallContext::CanGetSet() const michael@0: { michael@0: return mState >= HAVE_NAME; michael@0: } michael@0: michael@0: inline XPCNativeSet* michael@0: XPCCallContext::GetSet() const michael@0: { michael@0: CHECK_STATE(HAVE_NAME); michael@0: return mSet; michael@0: } michael@0: michael@0: inline bool michael@0: XPCCallContext::CanGetInterface() const michael@0: { michael@0: return mState >= HAVE_NAME; michael@0: } michael@0: michael@0: inline XPCNativeInterface* michael@0: XPCCallContext::GetInterface() const michael@0: { michael@0: CHECK_STATE(HAVE_NAME); michael@0: return mInterface; michael@0: } michael@0: michael@0: inline XPCNativeMember* michael@0: XPCCallContext::GetMember() const michael@0: { michael@0: CHECK_STATE(HAVE_NAME); michael@0: return mMember; michael@0: } michael@0: michael@0: inline bool michael@0: XPCCallContext::HasInterfaceAndMember() const michael@0: { michael@0: return mState >= HAVE_NAME && mInterface && mMember; michael@0: } michael@0: michael@0: inline jsid michael@0: XPCCallContext::GetName() const michael@0: { michael@0: CHECK_STATE(HAVE_NAME); michael@0: return mName; michael@0: } michael@0: michael@0: inline bool michael@0: XPCCallContext::GetStaticMemberIsLocal() const michael@0: { michael@0: CHECK_STATE(HAVE_NAME); michael@0: return mStaticMemberIsLocal; michael@0: } michael@0: michael@0: inline unsigned michael@0: XPCCallContext::GetArgc() const michael@0: { michael@0: CHECK_STATE(READY_TO_CALL); michael@0: return mArgc; michael@0: } michael@0: michael@0: inline jsval* michael@0: XPCCallContext::GetArgv() const michael@0: { michael@0: CHECK_STATE(READY_TO_CALL); michael@0: return mArgv; michael@0: } michael@0: michael@0: inline jsval* michael@0: XPCCallContext::GetRetVal() const michael@0: { michael@0: CHECK_STATE(READY_TO_CALL); michael@0: return mRetVal; michael@0: } michael@0: michael@0: inline void michael@0: XPCCallContext::SetRetVal(jsval val) michael@0: { michael@0: CHECK_STATE(HAVE_ARGS); michael@0: if (mRetVal) michael@0: *mRetVal = val; michael@0: } michael@0: michael@0: inline jsid michael@0: XPCCallContext::GetResolveName() const michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return XPCJSRuntime::Get()->GetResolveName(); michael@0: } michael@0: michael@0: inline jsid michael@0: XPCCallContext::SetResolveName(JS::HandleId name) michael@0: { michael@0: CHECK_STATE(HAVE_CONTEXT); michael@0: return XPCJSRuntime::Get()->SetResolveName(name); michael@0: } michael@0: michael@0: inline XPCWrappedNative* michael@0: XPCCallContext::GetResolvingWrapper() const michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return XPCJSRuntime::Get()->GetResolvingWrapper(); michael@0: } michael@0: michael@0: inline XPCWrappedNative* michael@0: XPCCallContext::SetResolvingWrapper(XPCWrappedNative* w) michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return XPCJSRuntime::Get()->SetResolvingWrapper(w); michael@0: } michael@0: michael@0: inline uint16_t michael@0: XPCCallContext::GetMethodIndex() const michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: return mMethodIndex; michael@0: } michael@0: michael@0: inline void michael@0: XPCCallContext::SetMethodIndex(uint16_t index) michael@0: { michael@0: CHECK_STATE(HAVE_OBJECT); michael@0: mMethodIndex = index; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: inline const nsIID* michael@0: XPCNativeInterface::GetIID() const michael@0: { michael@0: const nsIID* iid; michael@0: return NS_SUCCEEDED(mInfo->GetIIDShared(&iid)) ? iid : nullptr; michael@0: } michael@0: michael@0: inline const char* michael@0: XPCNativeInterface::GetNameString() const michael@0: { michael@0: const char* name; michael@0: return NS_SUCCEEDED(mInfo->GetNameShared(&name)) ? name : nullptr; michael@0: } michael@0: michael@0: inline XPCNativeMember* michael@0: XPCNativeInterface::FindMember(jsid name) const michael@0: { michael@0: const XPCNativeMember* member = mMembers; michael@0: for (int i = (int) mMemberCount; i > 0; i--, member++) michael@0: if (member->GetName() == name) michael@0: return const_cast(member); michael@0: return nullptr; michael@0: } michael@0: michael@0: inline bool michael@0: XPCNativeInterface::HasAncestor(const nsIID* iid) const michael@0: { michael@0: bool found = false; michael@0: mInfo->HasAncestor(iid, &found); michael@0: return found; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: inline bool michael@0: XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, michael@0: uint16_t* pInterfaceIndex) const michael@0: { michael@0: XPCNativeInterface* const * iface; michael@0: int count = (int) mInterfaceCount; michael@0: int i; michael@0: michael@0: // look for interface names first michael@0: michael@0: for (i = 0, iface = mInterfaces; i < count; i++, iface++) { michael@0: if (name == (*iface)->GetName()) { michael@0: if (pMember) michael@0: *pMember = nullptr; michael@0: if (pInterfaceIndex) michael@0: *pInterfaceIndex = (uint16_t) i; michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: // look for method names michael@0: for (i = 0, iface = mInterfaces; i < count; i++, iface++) { michael@0: XPCNativeMember* member = (*iface)->FindMember(name); michael@0: if (member) { michael@0: if (pMember) michael@0: *pMember = member; michael@0: if (pInterfaceIndex) michael@0: *pInterfaceIndex = (uint16_t) i; michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: inline bool michael@0: XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, michael@0: XPCNativeInterface** pInterface) const michael@0: { michael@0: uint16_t index; michael@0: if (!FindMember(name, pMember, &index)) michael@0: return false; michael@0: *pInterface = mInterfaces[index]; michael@0: return true; michael@0: } michael@0: michael@0: inline bool michael@0: XPCNativeSet::FindMember(jsid name, michael@0: XPCNativeMember** pMember, michael@0: XPCNativeInterface** pInterface, michael@0: XPCNativeSet* protoSet, michael@0: bool* pIsLocal) const michael@0: { michael@0: XPCNativeMember* Member; michael@0: XPCNativeInterface* Interface; michael@0: XPCNativeMember* protoMember; michael@0: michael@0: if (!FindMember(name, &Member, &Interface)) michael@0: return false; michael@0: michael@0: *pMember = Member; michael@0: *pInterface = Interface; michael@0: michael@0: *pIsLocal = michael@0: !Member || michael@0: !protoSet || michael@0: (protoSet != this && michael@0: !protoSet->MatchesSetUpToInterface(this, Interface) && michael@0: (!protoSet->FindMember(name, &protoMember, (uint16_t*)nullptr) || michael@0: protoMember != Member)); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: inline XPCNativeInterface* michael@0: XPCNativeSet::FindNamedInterface(jsid name) const michael@0: { michael@0: XPCNativeInterface* const * pp = mInterfaces; michael@0: michael@0: for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { michael@0: XPCNativeInterface* iface = *pp; michael@0: michael@0: if (name == iface->GetName()) michael@0: return iface; michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: inline XPCNativeInterface* michael@0: XPCNativeSet::FindInterfaceWithIID(const nsIID& iid) const michael@0: { michael@0: XPCNativeInterface* const * pp = mInterfaces; michael@0: michael@0: for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { michael@0: XPCNativeInterface* iface = *pp; michael@0: michael@0: if (iface->GetIID()->Equals(iid)) michael@0: return iface; michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: inline bool michael@0: XPCNativeSet::HasInterface(XPCNativeInterface* aInterface) const michael@0: { michael@0: XPCNativeInterface* const * pp = mInterfaces; michael@0: michael@0: for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { michael@0: if (aInterface == *pp) michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: inline bool michael@0: XPCNativeSet::HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const michael@0: { michael@0: return HasInterfaceWithAncestor(aInterface->GetIID()); michael@0: } michael@0: michael@0: inline bool michael@0: XPCNativeSet::HasInterfaceWithAncestor(const nsIID* iid) const michael@0: { michael@0: // We can safely skip the first interface which is *always* nsISupports. michael@0: XPCNativeInterface* const * pp = mInterfaces+1; michael@0: for (int i = (int) mInterfaceCount; i > 1; i--, pp++) michael@0: if ((*pp)->HasAncestor(iid)) michael@0: return true; michael@0: michael@0: // This is rare, so check last. michael@0: if (iid == &NS_GET_IID(nsISupports)) michael@0: return true; michael@0: michael@0: return false; michael@0: } michael@0: michael@0: inline bool michael@0: XPCNativeSet::MatchesSetUpToInterface(const XPCNativeSet* other, michael@0: XPCNativeInterface* iface) const michael@0: { michael@0: int count = std::min(int(mInterfaceCount), int(other->mInterfaceCount)); michael@0: michael@0: XPCNativeInterface* const * pp1 = mInterfaces; michael@0: XPCNativeInterface* const * pp2 = other->mInterfaces; michael@0: michael@0: for (int i = (int) count; i > 0; i--, pp1++, pp2++) { michael@0: XPCNativeInterface* cur = (*pp1); michael@0: if (cur != (*pp2)) michael@0: return false; michael@0: if (cur == iface) michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: inline void XPCNativeSet::Mark() michael@0: { michael@0: if (IsMarked()) michael@0: return; michael@0: michael@0: XPCNativeInterface* const * pp = mInterfaces; michael@0: michael@0: for (int i = (int) mInterfaceCount; i > 0; i--, pp++) michael@0: (*pp)->Mark(); michael@0: michael@0: MarkSelfOnly(); michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: inline void XPCNativeSet::ASSERT_NotMarked() michael@0: { michael@0: MOZ_ASSERT(!IsMarked(), "bad"); michael@0: michael@0: XPCNativeInterface* const * pp = mInterfaces; michael@0: michael@0: for (int i = (int) mInterfaceCount; i > 0; i--, pp++) michael@0: MOZ_ASSERT(!(*pp)->IsMarked(), "bad"); michael@0: } michael@0: #endif michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: inline michael@0: JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const michael@0: { michael@0: return reinterpret_cast(reinterpret_cast(mJSObject) & ~1); michael@0: } michael@0: michael@0: inline michael@0: JSObject* XPCWrappedNativeTearOff::GetJSObject() michael@0: { michael@0: JSObject *obj = GetJSObjectPreserveColor(); michael@0: if (obj) { michael@0: JS::ExposeObjectToActiveJS(obj); michael@0: } michael@0: return obj; michael@0: } michael@0: michael@0: inline michael@0: void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj) michael@0: { michael@0: MOZ_ASSERT(!IsMarked()); michael@0: mJSObject = JSObj; michael@0: } michael@0: michael@0: inline michael@0: XPCWrappedNativeTearOff::~XPCWrappedNativeTearOff() michael@0: { michael@0: MOZ_ASSERT(!(GetInterface() || GetNative() || GetJSObjectPreserveColor()), michael@0: "tearoff not empty in dtor"); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: inline bool michael@0: XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid) michael@0: { michael@0: return nullptr != GetSet()->FindInterfaceWithIID(iid); michael@0: } michael@0: michael@0: inline void michael@0: XPCWrappedNative::SweepTearOffs() michael@0: { michael@0: XPCWrappedNativeTearOffChunk* chunk; michael@0: for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk) { michael@0: XPCWrappedNativeTearOff* to = chunk->mTearOffs; michael@0: for (int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK; i > 0; i--, to++) { michael@0: bool marked = to->IsMarked(); michael@0: to->Unmark(); michael@0: if (marked) michael@0: continue; michael@0: michael@0: // If this tearoff does not have a live dedicated JSObject, michael@0: // then let's recycle it. michael@0: if (!to->GetJSObjectPreserveColor()) { michael@0: nsISupports* obj = to->GetNative(); michael@0: if (obj) { michael@0: obj->Release(); michael@0: to->SetNative(nullptr); michael@0: } michael@0: to->SetInterface(nullptr); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: inline bool michael@0: xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid idArg) michael@0: { michael@0: JS::RootedValue prop(cx); michael@0: JS::RootedId id(cx, idArg); michael@0: michael@0: if (!JS_LookupPropertyById(cx, obj, id, &prop)) michael@0: return false; michael@0: return true; michael@0: } michael@0: michael@0: inline jsid michael@0: GetRTIdByIndex(JSContext *cx, unsigned index) michael@0: { michael@0: XPCJSRuntime *rt = nsXPConnect::XPConnect()->GetRuntime(); michael@0: return rt->GetStringID(index); michael@0: } michael@0: michael@0: inline michael@0: bool ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx) michael@0: { michael@0: XPCThrower::ThrowBadParam(rv, paramNum, ccx); michael@0: return false; michael@0: } michael@0: michael@0: inline michael@0: void ThrowBadResult(nsresult result, XPCCallContext& ccx) michael@0: { michael@0: XPCThrower::ThrowBadResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, michael@0: result, ccx); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: #endif /* xpcinlines_h___ */