XPCInlines.h (10553B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* private inline methods (#include'd by xpcprivate.h). */ 8 9 #ifndef xpcinlines_h___ 10 #define xpcinlines_h___ 11 12 #include <algorithm> 13 14 #include "js/PropertyAndElement.h" // JS_HasProperty, JS_HasPropertyById 15 16 /***************************************************************************/ 17 18 inline void XPCJSRuntime::AddSubjectToFinalizationWJS( 19 nsXPCWrappedJS* wrappedJS) { 20 mSubjectToFinalizationWJS.insertBack(wrappedJS); 21 } 22 23 /***************************************************************************/ 24 25 inline bool XPCCallContext::IsValid() const { return mState != INIT_FAILED; } 26 27 inline XPCJSContext* XPCCallContext::GetContext() const { 28 CHECK_STATE(HAVE_CONTEXT); 29 return mXPCJSContext; 30 } 31 32 inline JSContext* XPCCallContext::GetJSContext() const { 33 CHECK_STATE(HAVE_CONTEXT); 34 return mJSContext; 35 } 36 37 inline XPCCallContext* XPCCallContext::GetPrevCallContext() const { 38 CHECK_STATE(HAVE_CONTEXT); 39 return mPrevCallContext; 40 } 41 42 inline XPCWrappedNative* XPCCallContext::GetWrapper() const { 43 if (mState == INIT_FAILED) { 44 return nullptr; 45 } 46 47 CHECK_STATE(HAVE_OBJECT); 48 return mWrapper; 49 } 50 51 inline bool XPCCallContext::CanGetTearOff() const { 52 return mState >= HAVE_OBJECT; 53 } 54 55 inline XPCWrappedNativeTearOff* XPCCallContext::GetTearOff() const { 56 CHECK_STATE(HAVE_OBJECT); 57 return mTearOff; 58 } 59 60 inline nsIXPCScriptable* XPCCallContext::GetScriptable() const { 61 CHECK_STATE(HAVE_OBJECT); 62 return mScriptable; 63 } 64 65 inline XPCNativeSet* XPCCallContext::GetSet() const { 66 CHECK_STATE(HAVE_NAME); 67 return mSet; 68 } 69 70 inline XPCNativeInterface* XPCCallContext::GetInterface() const { 71 CHECK_STATE(HAVE_NAME); 72 return mInterface; 73 } 74 75 inline XPCNativeMember* XPCCallContext::GetMember() const { 76 CHECK_STATE(HAVE_NAME); 77 return mMember; 78 } 79 80 inline bool XPCCallContext::HasInterfaceAndMember() const { 81 return mState >= HAVE_NAME && mInterface && mMember; 82 } 83 84 inline bool XPCCallContext::GetStaticMemberIsLocal() const { 85 CHECK_STATE(HAVE_NAME); 86 return mStaticMemberIsLocal; 87 } 88 89 inline unsigned XPCCallContext::GetArgc() const { 90 CHECK_STATE(READY_TO_CALL); 91 return mArgc; 92 } 93 94 inline JS::Value* XPCCallContext::GetArgv() const { 95 CHECK_STATE(READY_TO_CALL); 96 return mArgv; 97 } 98 99 inline void XPCCallContext::SetRetVal(const JS::Value& val) { 100 CHECK_STATE(HAVE_ARGS); 101 if (mRetVal) { 102 *mRetVal = val; 103 } 104 } 105 106 inline jsid XPCCallContext::GetResolveName() const { 107 CHECK_STATE(HAVE_CONTEXT); 108 return GetContext()->GetResolveName(); 109 } 110 111 inline jsid XPCCallContext::SetResolveName(JS::HandleId name) { 112 CHECK_STATE(HAVE_CONTEXT); 113 return GetContext()->SetResolveName(name); 114 } 115 116 inline XPCWrappedNative* XPCCallContext::GetResolvingWrapper() const { 117 CHECK_STATE(HAVE_OBJECT); 118 return GetContext()->GetResolvingWrapper(); 119 } 120 121 inline XPCWrappedNative* XPCCallContext::SetResolvingWrapper( 122 XPCWrappedNative* w) { 123 CHECK_STATE(HAVE_OBJECT); 124 return GetContext()->SetResolvingWrapper(w); 125 } 126 127 inline uint16_t XPCCallContext::GetMethodIndex() const { 128 CHECK_STATE(HAVE_OBJECT); 129 return mMethodIndex; 130 } 131 132 /***************************************************************************/ 133 inline XPCNativeInterface* XPCNativeMember::GetInterface() const { 134 XPCNativeMember* arrayStart = 135 const_cast<XPCNativeMember*>(this - mIndexInInterface); 136 size_t arrayStartOffset = XPCNativeInterface::OffsetOfMembers(); 137 char* xpcNativeInterfaceStart = 138 reinterpret_cast<char*>(arrayStart) - arrayStartOffset; 139 return reinterpret_cast<XPCNativeInterface*>(xpcNativeInterfaceStart); 140 } 141 142 /***************************************************************************/ 143 144 inline const nsIID* XPCNativeInterface::GetIID() const { return &mInfo->IID(); } 145 146 inline const char* XPCNativeInterface::GetNameString() const { 147 return mInfo->Name(); 148 } 149 150 inline XPCNativeMember* XPCNativeInterface::FindMember(jsid name) const { 151 const XPCNativeMember* member = mMembers; 152 for (int i = (int)mMemberCount; i > 0; i--, member++) { 153 if (member->GetName() == name) { 154 return const_cast<XPCNativeMember*>(member); 155 } 156 } 157 return nullptr; 158 } 159 160 /* static */ 161 inline size_t XPCNativeInterface::OffsetOfMembers() { 162 return offsetof(XPCNativeInterface, mMembers); 163 } 164 165 /***************************************************************************/ 166 167 inline XPCNativeSetKey::XPCNativeSetKey(XPCNativeSet* baseSet, 168 XPCNativeInterface* addition) 169 : mCx(nullptr), mBaseSet(baseSet), mAddition(addition) { 170 MOZ_ASSERT(mBaseSet); 171 MOZ_ASSERT(mAddition); 172 MOZ_ASSERT(!mBaseSet->HasInterface(mAddition)); 173 } 174 175 /***************************************************************************/ 176 177 inline bool XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, 178 uint16_t* pInterfaceIndex) const { 179 XPCNativeInterface* const* iface; 180 int count = (int)mInterfaceCount; 181 int i; 182 183 // look for interface names first 184 185 for (i = 0, iface = mInterfaces; i < count; i++, iface++) { 186 if (name == (*iface)->GetName()) { 187 if (pMember) { 188 *pMember = nullptr; 189 } 190 if (pInterfaceIndex) { 191 *pInterfaceIndex = (uint16_t)i; 192 } 193 return true; 194 } 195 } 196 197 // look for method names 198 for (i = 0, iface = mInterfaces; i < count; i++, iface++) { 199 XPCNativeMember* member = (*iface)->FindMember(name); 200 if (member) { 201 if (pMember) { 202 *pMember = member; 203 } 204 if (pInterfaceIndex) { 205 *pInterfaceIndex = (uint16_t)i; 206 } 207 return true; 208 } 209 } 210 return false; 211 } 212 213 inline bool XPCNativeSet::FindMember( 214 jsid name, XPCNativeMember** pMember, 215 RefPtr<XPCNativeInterface>* pInterface) const { 216 uint16_t index; 217 if (!FindMember(name, pMember, &index)) { 218 return false; 219 } 220 *pInterface = mInterfaces[index]; 221 return true; 222 } 223 224 inline bool XPCNativeSet::FindMember(JS::HandleId name, 225 XPCNativeMember** pMember, 226 RefPtr<XPCNativeInterface>* pInterface, 227 XPCNativeSet* protoSet, 228 bool* pIsLocal) const { 229 XPCNativeMember* Member; 230 RefPtr<XPCNativeInterface> Interface; 231 XPCNativeMember* protoMember; 232 233 if (!FindMember(name, &Member, &Interface)) { 234 return false; 235 } 236 237 *pMember = Member; 238 239 *pIsLocal = !Member || !protoSet || 240 (protoSet != this && 241 !protoSet->MatchesSetUpToInterface(this, Interface) && 242 (!protoSet->FindMember(name, &protoMember, (uint16_t*)nullptr) || 243 protoMember != Member)); 244 245 *pInterface = std::move(Interface); 246 247 return true; 248 } 249 250 inline bool XPCNativeSet::HasInterface(XPCNativeInterface* aInterface) const { 251 XPCNativeInterface* const* pp = mInterfaces; 252 253 for (int i = (int)mInterfaceCount; i > 0; i--, pp++) { 254 if (aInterface == *pp) { 255 return true; 256 } 257 } 258 return false; 259 } 260 261 inline bool XPCNativeSet::MatchesSetUpToInterface( 262 const XPCNativeSet* other, XPCNativeInterface* iface) const { 263 int count = std::min(int(mInterfaceCount), int(other->mInterfaceCount)); 264 265 XPCNativeInterface* const* pp1 = mInterfaces; 266 XPCNativeInterface* const* pp2 = other->mInterfaces; 267 268 for (int i = (int)count; i > 0; i--, pp1++, pp2++) { 269 XPCNativeInterface* cur = (*pp1); 270 if (cur != (*pp2)) { 271 return false; 272 } 273 if (cur == iface) { 274 return true; 275 } 276 } 277 return false; 278 } 279 280 /***************************************************************************/ 281 282 inline JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const { 283 return mJSObject.unbarrieredGetPtr(); 284 } 285 286 inline JSObject* XPCWrappedNativeTearOff::GetJSObject() { return mJSObject; } 287 288 inline void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj) { 289 MOZ_ASSERT(!IsMarked()); 290 mJSObject = JSObj; 291 } 292 293 inline void XPCWrappedNativeTearOff::JSObjectMoved(JSObject* obj, 294 const JSObject* old) { 295 MOZ_ASSERT(!IsMarked()); 296 MOZ_ASSERT(mJSObject == old); 297 mJSObject = obj; 298 } 299 300 inline XPCWrappedNativeTearOff::~XPCWrappedNativeTearOff() { 301 MOZ_COUNT_DTOR(XPCWrappedNativeTearOff); 302 MOZ_ASSERT(!(GetInterface() || GetNative() || GetJSObjectPreserveColor()), 303 "tearoff not empty in dtor"); 304 } 305 306 /***************************************************************************/ 307 308 inline void XPCWrappedNative::SweepTearOffs() { 309 for (XPCWrappedNativeTearOff* to = &mFirstTearOff; to; 310 to = to->GetNextTearOff()) { 311 bool marked = to->IsMarked(); 312 to->Unmark(); 313 if (marked) { 314 continue; 315 } 316 317 // If this tearoff does not have a live dedicated JSObject, 318 // then let's recycle it. 319 if (!to->GetJSObjectPreserveColor()) { 320 to->SetNative(nullptr); 321 to->SetInterface(nullptr); 322 } 323 } 324 } 325 326 /***************************************************************************/ 327 328 inline bool xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, 329 jsid idArg) { 330 JS::RootedId id(cx, idArg); 331 bool dummy; 332 return JS_HasPropertyById(cx, obj, id, &dummy); 333 } 334 335 inline jsid GetJSIDByIndex(JSContext* cx, unsigned index) { 336 XPCJSRuntime* xpcrt = nsXPConnect::GetRuntimeInstance(); 337 return xpcrt->GetStringID(index); 338 } 339 340 inline bool ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx) { 341 XPCThrower::ThrowBadParam(rv, paramNum, ccx); 342 return false; 343 } 344 345 inline void ThrowBadResult(nsresult result, XPCCallContext& ccx) { 346 XPCThrower::ThrowBadResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, result, ccx); 347 } 348 349 /***************************************************************************/ 350 351 inline void xpc::CleanupValue(const nsXPTType& aType, void* aValue, 352 uint32_t aArrayLen) { 353 // Check if we can do a cheap early return, and only perform the inner call 354 // if we can't. We never have to clean up null pointer types or arithmetic 355 // types. 356 // 357 // NOTE: We can skip zeroing arithmetic types in CleanupValue, as they are 358 // already in a valid state. 359 if (aType.IsArithmetic() || (aType.IsPointer() && !*(void**)aValue)) { 360 return; 361 } 362 xpc::InnerCleanupValue(aType, aValue, aArrayLen); 363 } 364 365 /***************************************************************************/ 366 367 #endif /* xpcinlines_h___ */