/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* vim: set ts=8 sts=4 et sw=4 tw=99: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* private inline methods (#include'd by xpcprivate.h). */ #ifndef xpcinlines_h___ #define xpcinlines_h___ #include /***************************************************************************/ inline void XPCJSContext::AddVariantRoot(XPCTraceableVariant* variant) { variant->AddToRootSet(&mVariantRoots); } inline void XPCJSContext::AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS) { wrappedJS->AddToRootSet(&mWrappedJSRoots); } inline void XPCJSContext::AddObjectHolderRoot(XPCJSObjectHolder* holder) { holder->AddToRootSet(&mObjectHolderRoots); } /***************************************************************************/ inline bool XPCCallContext::IsValid() const { return mState != INIT_FAILED; } inline XPCJSContext* XPCCallContext::GetContext() const { CHECK_STATE(HAVE_CONTEXT); return mXPCJSContext; } inline JSContext* XPCCallContext::GetJSContext() const { CHECK_STATE(HAVE_CONTEXT); return mJSContext; } inline XPCCallContext* XPCCallContext::GetPrevCallContext() const { CHECK_STATE(HAVE_CONTEXT); return mPrevCallContext; } inline nsISupports* XPCCallContext::GetIdentityObject() const { CHECK_STATE(HAVE_OBJECT); if (mWrapper) return mWrapper->GetIdentityObject(); return nullptr; } inline XPCWrappedNative* XPCCallContext::GetWrapper() const { if (mState == INIT_FAILED) return nullptr; CHECK_STATE(HAVE_OBJECT); return mWrapper; } inline XPCWrappedNativeProto* XPCCallContext::GetProto() const { CHECK_STATE(HAVE_OBJECT); return mWrapper ? mWrapper->GetProto() : nullptr; } inline bool XPCCallContext::CanGetTearOff() const { return mState >= HAVE_OBJECT; } inline XPCWrappedNativeTearOff* XPCCallContext::GetTearOff() const { CHECK_STATE(HAVE_OBJECT); return mTearOff; } inline XPCNativeScriptableInfo* XPCCallContext::GetScriptableInfo() const { CHECK_STATE(HAVE_OBJECT); return mScriptableInfo; } inline bool XPCCallContext::CanGetSet() const { return mState >= HAVE_NAME; } inline XPCNativeSet* XPCCallContext::GetSet() const { CHECK_STATE(HAVE_NAME); return mSet; } inline XPCNativeInterface* XPCCallContext::GetInterface() const { CHECK_STATE(HAVE_NAME); return mInterface; } inline XPCNativeMember* XPCCallContext::GetMember() const { CHECK_STATE(HAVE_NAME); return mMember; } inline bool XPCCallContext::HasInterfaceAndMember() const { return mState >= HAVE_NAME && mInterface && mMember; } inline jsid XPCCallContext::GetName() const { CHECK_STATE(HAVE_NAME); return mName; } inline bool XPCCallContext::GetStaticMemberIsLocal() const { CHECK_STATE(HAVE_NAME); return mStaticMemberIsLocal; } inline unsigned XPCCallContext::GetArgc() const { CHECK_STATE(READY_TO_CALL); return mArgc; } inline JS::Value* XPCCallContext::GetArgv() const { CHECK_STATE(READY_TO_CALL); return mArgv; } inline JS::Value* XPCCallContext::GetRetVal() const { CHECK_STATE(READY_TO_CALL); return mRetVal; } inline void XPCCallContext::SetRetVal(const JS::Value& val) { CHECK_STATE(HAVE_ARGS); if (mRetVal) *mRetVal = val; } inline jsid XPCCallContext::GetResolveName() const { CHECK_STATE(HAVE_CONTEXT); return XPCJSContext::Get()->GetResolveName(); } inline jsid XPCCallContext::SetResolveName(JS::HandleId name) { CHECK_STATE(HAVE_CONTEXT); return XPCJSContext::Get()->SetResolveName(name); } inline XPCWrappedNative* XPCCallContext::GetResolvingWrapper() const { CHECK_STATE(HAVE_OBJECT); return XPCJSContext::Get()->GetResolvingWrapper(); } inline XPCWrappedNative* XPCCallContext::SetResolvingWrapper(XPCWrappedNative* w) { CHECK_STATE(HAVE_OBJECT); return XPCJSContext::Get()->SetResolvingWrapper(w); } inline uint16_t XPCCallContext::GetMethodIndex() const { CHECK_STATE(HAVE_OBJECT); return mMethodIndex; } inline void XPCCallContext::SetMethodIndex(uint16_t index) { CHECK_STATE(HAVE_OBJECT); mMethodIndex = index; } /***************************************************************************/ inline XPCNativeInterface* XPCNativeMember::GetInterface() const { XPCNativeMember* arrayStart = const_cast(this - mIndexInInterface); size_t arrayStartOffset = XPCNativeInterface::OffsetOfMembers(); char* xpcNativeInterfaceStart = reinterpret_cast(arrayStart) - arrayStartOffset; return reinterpret_cast(xpcNativeInterfaceStart); } /***************************************************************************/ inline const nsIID* XPCNativeInterface::GetIID() const { const nsIID* iid; return NS_SUCCEEDED(mInfo->GetIIDShared(&iid)) ? iid : nullptr; } inline const char* XPCNativeInterface::GetNameString() const { const char* name; return NS_SUCCEEDED(mInfo->GetNameShared(&name)) ? name : nullptr; } inline XPCNativeMember* XPCNativeInterface::FindMember(jsid name) const { const XPCNativeMember* member = mMembers; for (int i = (int) mMemberCount; i > 0; i--, member++) if (member->GetName() == name) return const_cast(member); return nullptr; } inline bool XPCNativeInterface::HasAncestor(const nsIID* iid) const { bool found = false; mInfo->HasAncestor(iid, &found); return found; } /* static */ inline size_t XPCNativeInterface::OffsetOfMembers() { return offsetof(XPCNativeInterface, mMembers); } /***************************************************************************/ inline XPCNativeSetKey::XPCNativeSetKey(XPCNativeSet* baseSet, XPCNativeInterface* addition) : mBaseSet(baseSet) , mAddition(addition) { MOZ_ASSERT(mBaseSet); MOZ_ASSERT(mAddition); MOZ_ASSERT(!mBaseSet->HasInterface(mAddition)); } /***************************************************************************/ inline bool XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, uint16_t* pInterfaceIndex) const { XPCNativeInterface* const * iface; int count = (int) mInterfaceCount; int i; // look for interface names first for (i = 0, iface = mInterfaces; i < count; i++, iface++) { if (name == (*iface)->GetName()) { if (pMember) *pMember = nullptr; if (pInterfaceIndex) *pInterfaceIndex = (uint16_t) i; return true; } } // look for method names for (i = 0, iface = mInterfaces; i < count; i++, iface++) { XPCNativeMember* member = (*iface)->FindMember(name); if (member) { if (pMember) *pMember = member; if (pInterfaceIndex) *pInterfaceIndex = (uint16_t) i; return true; } } return false; } inline bool XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, RefPtr* pInterface) const { uint16_t index; if (!FindMember(name, pMember, &index)) return false; *pInterface = mInterfaces[index]; return true; } inline bool XPCNativeSet::FindMember(JS::HandleId name, XPCNativeMember** pMember, RefPtr* pInterface, XPCNativeSet* protoSet, bool* pIsLocal) const { XPCNativeMember* Member; RefPtr Interface; XPCNativeMember* protoMember; if (!FindMember(name, &Member, &Interface)) return false; *pMember = Member; *pIsLocal = !Member || !protoSet || (protoSet != this && !protoSet->MatchesSetUpToInterface(this, Interface) && (!protoSet->FindMember(name, &protoMember, (uint16_t*)nullptr) || protoMember != Member)); *pInterface = Interface.forget(); return true; } inline XPCNativeInterface* XPCNativeSet::FindNamedInterface(jsid name) const { XPCNativeInterface* const * pp = mInterfaces; for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { XPCNativeInterface* iface = *pp; if (name == iface->GetName()) return iface; } return nullptr; } inline XPCNativeInterface* XPCNativeSet::FindInterfaceWithIID(const nsIID& iid) const { XPCNativeInterface* const * pp = mInterfaces; for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { XPCNativeInterface* iface = *pp; if (iface->GetIID()->Equals(iid)) return iface; } return nullptr; } inline bool XPCNativeSet::HasInterface(XPCNativeInterface* aInterface) const { XPCNativeInterface* const * pp = mInterfaces; for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { if (aInterface == *pp) return true; } return false; } inline bool XPCNativeSet::HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const { return HasInterfaceWithAncestor(aInterface->GetIID()); } inline bool XPCNativeSet::HasInterfaceWithAncestor(const nsIID* iid) const { // We can safely skip the first interface which is *always* nsISupports. XPCNativeInterface* const * pp = mInterfaces+1; for (int i = (int) mInterfaceCount; i > 1; i--, pp++) if ((*pp)->HasAncestor(iid)) return true; // This is rare, so check last. if (iid == &NS_GET_IID(nsISupports)) return true; return false; } inline bool XPCNativeSet::MatchesSetUpToInterface(const XPCNativeSet* other, XPCNativeInterface* iface) const { int count = std::min(int(mInterfaceCount), int(other->mInterfaceCount)); XPCNativeInterface* const * pp1 = mInterfaces; XPCNativeInterface* const * pp2 = other->mInterfaces; for (int i = (int) count; i > 0; i--, pp1++, pp2++) { XPCNativeInterface* cur = (*pp1); if (cur != (*pp2)) return false; if (cur == iface) return true; } return false; } /***************************************************************************/ inline JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const { return mJSObject.unbarrieredGetPtr(); } inline JSObject* XPCWrappedNativeTearOff::GetJSObject() { return mJSObject; } inline void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj) { MOZ_ASSERT(!IsMarked()); mJSObject = JSObj; } inline void XPCWrappedNativeTearOff::JSObjectMoved(JSObject* obj, const JSObject* old) { MOZ_ASSERT(!IsMarked()); MOZ_ASSERT(mJSObject.unbarrieredGetPtr() == old); mJSObject = obj; } inline XPCWrappedNativeTearOff::~XPCWrappedNativeTearOff() { MOZ_COUNT_DTOR(XPCWrappedNativeTearOff); MOZ_ASSERT(!(GetInterface() || GetNative() || GetJSObjectPreserveColor()), "tearoff not empty in dtor"); } /***************************************************************************/ inline bool XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid) { return nullptr != GetSet()->FindInterfaceWithIID(iid); } inline void XPCWrappedNative::SweepTearOffs() { for (XPCWrappedNativeTearOff* to = &mFirstTearOff; to; to = to->GetNextTearOff()) { bool 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->GetJSObjectPreserveColor()) { to->SetNative(nullptr); to->SetInterface(nullptr); } } } /***************************************************************************/ inline bool xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid idArg) { JS::RootedId id(cx, idArg); bool dummy; return JS_HasPropertyById(cx, obj, id, &dummy); } inline jsid GetJSIDByIndex(JSContext* cx, unsigned index) { XPCJSContext* xpcx = nsXPConnect::XPConnect()->GetContext(); return xpcx->GetStringID(index); } inline bool ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx) { XPCThrower::ThrowBadParam(rv, paramNum, ccx); return false; } inline void ThrowBadResult(nsresult result, XPCCallContext& ccx) { XPCThrower::ThrowBadResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, result, ccx); } /***************************************************************************/ #endif /* xpcinlines_h___ */