|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */ |
|
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 /***************************************************************************/ |
|
15 |
|
16 inline void |
|
17 XPCJSRuntime::AddVariantRoot(XPCTraceableVariant* variant) |
|
18 { |
|
19 variant->AddToRootSet(&mVariantRoots); |
|
20 } |
|
21 |
|
22 inline void |
|
23 XPCJSRuntime::AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS) |
|
24 { |
|
25 wrappedJS->AddToRootSet(&mWrappedJSRoots); |
|
26 } |
|
27 |
|
28 inline void |
|
29 XPCJSRuntime::AddObjectHolderRoot(XPCJSObjectHolder* holder) |
|
30 { |
|
31 holder->AddToRootSet(&mObjectHolderRoots); |
|
32 } |
|
33 |
|
34 /***************************************************************************/ |
|
35 |
|
36 inline bool |
|
37 XPCCallContext::IsValid() const |
|
38 { |
|
39 return mState != INIT_FAILED; |
|
40 } |
|
41 |
|
42 inline XPCJSRuntime* |
|
43 XPCCallContext::GetRuntime() const |
|
44 { |
|
45 CHECK_STATE(HAVE_CONTEXT); |
|
46 return mXPCContext->GetRuntime(); |
|
47 } |
|
48 |
|
49 inline XPCContext* |
|
50 XPCCallContext::GetXPCContext() const |
|
51 { |
|
52 CHECK_STATE(HAVE_CONTEXT); |
|
53 return mXPCContext; |
|
54 } |
|
55 |
|
56 inline JSContext* |
|
57 XPCCallContext::GetJSContext() const |
|
58 { |
|
59 CHECK_STATE(HAVE_CONTEXT); |
|
60 return mJSContext; |
|
61 } |
|
62 |
|
63 inline XPCContext::LangType |
|
64 XPCCallContext::GetCallerLanguage() const |
|
65 { |
|
66 CHECK_STATE(HAVE_CONTEXT); |
|
67 return mCallerLanguage; |
|
68 } |
|
69 |
|
70 inline XPCContext::LangType |
|
71 XPCCallContext::GetPrevCallerLanguage() const |
|
72 { |
|
73 CHECK_STATE(HAVE_CONTEXT); |
|
74 return mPrevCallerLanguage; |
|
75 } |
|
76 |
|
77 inline XPCCallContext* |
|
78 XPCCallContext::GetPrevCallContext() const |
|
79 { |
|
80 CHECK_STATE(HAVE_CONTEXT); |
|
81 return mPrevCallContext; |
|
82 } |
|
83 |
|
84 inline JSObject* |
|
85 XPCCallContext::GetFlattenedJSObject() const |
|
86 { |
|
87 CHECK_STATE(HAVE_OBJECT); |
|
88 return mFlattenedJSObject; |
|
89 } |
|
90 |
|
91 inline nsISupports* |
|
92 XPCCallContext::GetIdentityObject() const |
|
93 { |
|
94 CHECK_STATE(HAVE_OBJECT); |
|
95 if (mWrapper) |
|
96 return mWrapper->GetIdentityObject(); |
|
97 return mFlattenedJSObject ? |
|
98 static_cast<nsISupports*>(xpc_GetJSPrivate(mFlattenedJSObject)) : |
|
99 nullptr; |
|
100 } |
|
101 |
|
102 inline XPCWrappedNative* |
|
103 XPCCallContext::GetWrapper() const |
|
104 { |
|
105 if (mState == INIT_FAILED) |
|
106 return nullptr; |
|
107 |
|
108 CHECK_STATE(HAVE_OBJECT); |
|
109 return mWrapper; |
|
110 } |
|
111 |
|
112 inline XPCWrappedNativeProto* |
|
113 XPCCallContext::GetProto() const |
|
114 { |
|
115 CHECK_STATE(HAVE_OBJECT); |
|
116 return mWrapper ? mWrapper->GetProto() : nullptr; |
|
117 } |
|
118 |
|
119 inline bool |
|
120 XPCCallContext::CanGetTearOff() const |
|
121 { |
|
122 return mState >= HAVE_OBJECT; |
|
123 } |
|
124 |
|
125 inline XPCWrappedNativeTearOff* |
|
126 XPCCallContext::GetTearOff() const |
|
127 { |
|
128 CHECK_STATE(HAVE_OBJECT); |
|
129 return mTearOff; |
|
130 } |
|
131 |
|
132 inline XPCNativeScriptableInfo* |
|
133 XPCCallContext::GetScriptableInfo() const |
|
134 { |
|
135 CHECK_STATE(HAVE_OBJECT); |
|
136 return mScriptableInfo; |
|
137 } |
|
138 |
|
139 inline bool |
|
140 XPCCallContext::CanGetSet() const |
|
141 { |
|
142 return mState >= HAVE_NAME; |
|
143 } |
|
144 |
|
145 inline XPCNativeSet* |
|
146 XPCCallContext::GetSet() const |
|
147 { |
|
148 CHECK_STATE(HAVE_NAME); |
|
149 return mSet; |
|
150 } |
|
151 |
|
152 inline bool |
|
153 XPCCallContext::CanGetInterface() const |
|
154 { |
|
155 return mState >= HAVE_NAME; |
|
156 } |
|
157 |
|
158 inline XPCNativeInterface* |
|
159 XPCCallContext::GetInterface() const |
|
160 { |
|
161 CHECK_STATE(HAVE_NAME); |
|
162 return mInterface; |
|
163 } |
|
164 |
|
165 inline XPCNativeMember* |
|
166 XPCCallContext::GetMember() const |
|
167 { |
|
168 CHECK_STATE(HAVE_NAME); |
|
169 return mMember; |
|
170 } |
|
171 |
|
172 inline bool |
|
173 XPCCallContext::HasInterfaceAndMember() const |
|
174 { |
|
175 return mState >= HAVE_NAME && mInterface && mMember; |
|
176 } |
|
177 |
|
178 inline jsid |
|
179 XPCCallContext::GetName() const |
|
180 { |
|
181 CHECK_STATE(HAVE_NAME); |
|
182 return mName; |
|
183 } |
|
184 |
|
185 inline bool |
|
186 XPCCallContext::GetStaticMemberIsLocal() const |
|
187 { |
|
188 CHECK_STATE(HAVE_NAME); |
|
189 return mStaticMemberIsLocal; |
|
190 } |
|
191 |
|
192 inline unsigned |
|
193 XPCCallContext::GetArgc() const |
|
194 { |
|
195 CHECK_STATE(READY_TO_CALL); |
|
196 return mArgc; |
|
197 } |
|
198 |
|
199 inline jsval* |
|
200 XPCCallContext::GetArgv() const |
|
201 { |
|
202 CHECK_STATE(READY_TO_CALL); |
|
203 return mArgv; |
|
204 } |
|
205 |
|
206 inline jsval* |
|
207 XPCCallContext::GetRetVal() const |
|
208 { |
|
209 CHECK_STATE(READY_TO_CALL); |
|
210 return mRetVal; |
|
211 } |
|
212 |
|
213 inline void |
|
214 XPCCallContext::SetRetVal(jsval val) |
|
215 { |
|
216 CHECK_STATE(HAVE_ARGS); |
|
217 if (mRetVal) |
|
218 *mRetVal = val; |
|
219 } |
|
220 |
|
221 inline jsid |
|
222 XPCCallContext::GetResolveName() const |
|
223 { |
|
224 CHECK_STATE(HAVE_CONTEXT); |
|
225 return XPCJSRuntime::Get()->GetResolveName(); |
|
226 } |
|
227 |
|
228 inline jsid |
|
229 XPCCallContext::SetResolveName(JS::HandleId name) |
|
230 { |
|
231 CHECK_STATE(HAVE_CONTEXT); |
|
232 return XPCJSRuntime::Get()->SetResolveName(name); |
|
233 } |
|
234 |
|
235 inline XPCWrappedNative* |
|
236 XPCCallContext::GetResolvingWrapper() const |
|
237 { |
|
238 CHECK_STATE(HAVE_OBJECT); |
|
239 return XPCJSRuntime::Get()->GetResolvingWrapper(); |
|
240 } |
|
241 |
|
242 inline XPCWrappedNative* |
|
243 XPCCallContext::SetResolvingWrapper(XPCWrappedNative* w) |
|
244 { |
|
245 CHECK_STATE(HAVE_OBJECT); |
|
246 return XPCJSRuntime::Get()->SetResolvingWrapper(w); |
|
247 } |
|
248 |
|
249 inline uint16_t |
|
250 XPCCallContext::GetMethodIndex() const |
|
251 { |
|
252 CHECK_STATE(HAVE_OBJECT); |
|
253 return mMethodIndex; |
|
254 } |
|
255 |
|
256 inline void |
|
257 XPCCallContext::SetMethodIndex(uint16_t index) |
|
258 { |
|
259 CHECK_STATE(HAVE_OBJECT); |
|
260 mMethodIndex = index; |
|
261 } |
|
262 |
|
263 /***************************************************************************/ |
|
264 |
|
265 inline const nsIID* |
|
266 XPCNativeInterface::GetIID() const |
|
267 { |
|
268 const nsIID* iid; |
|
269 return NS_SUCCEEDED(mInfo->GetIIDShared(&iid)) ? iid : nullptr; |
|
270 } |
|
271 |
|
272 inline const char* |
|
273 XPCNativeInterface::GetNameString() const |
|
274 { |
|
275 const char* name; |
|
276 return NS_SUCCEEDED(mInfo->GetNameShared(&name)) ? name : nullptr; |
|
277 } |
|
278 |
|
279 inline XPCNativeMember* |
|
280 XPCNativeInterface::FindMember(jsid name) const |
|
281 { |
|
282 const XPCNativeMember* member = mMembers; |
|
283 for (int i = (int) mMemberCount; i > 0; i--, member++) |
|
284 if (member->GetName() == name) |
|
285 return const_cast<XPCNativeMember*>(member); |
|
286 return nullptr; |
|
287 } |
|
288 |
|
289 inline bool |
|
290 XPCNativeInterface::HasAncestor(const nsIID* iid) const |
|
291 { |
|
292 bool found = false; |
|
293 mInfo->HasAncestor(iid, &found); |
|
294 return found; |
|
295 } |
|
296 |
|
297 /***************************************************************************/ |
|
298 |
|
299 inline bool |
|
300 XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, |
|
301 uint16_t* pInterfaceIndex) const |
|
302 { |
|
303 XPCNativeInterface* const * iface; |
|
304 int count = (int) mInterfaceCount; |
|
305 int i; |
|
306 |
|
307 // look for interface names first |
|
308 |
|
309 for (i = 0, iface = mInterfaces; i < count; i++, iface++) { |
|
310 if (name == (*iface)->GetName()) { |
|
311 if (pMember) |
|
312 *pMember = nullptr; |
|
313 if (pInterfaceIndex) |
|
314 *pInterfaceIndex = (uint16_t) i; |
|
315 return true; |
|
316 } |
|
317 } |
|
318 |
|
319 // look for method names |
|
320 for (i = 0, iface = mInterfaces; i < count; i++, iface++) { |
|
321 XPCNativeMember* member = (*iface)->FindMember(name); |
|
322 if (member) { |
|
323 if (pMember) |
|
324 *pMember = member; |
|
325 if (pInterfaceIndex) |
|
326 *pInterfaceIndex = (uint16_t) i; |
|
327 return true; |
|
328 } |
|
329 } |
|
330 return false; |
|
331 } |
|
332 |
|
333 inline bool |
|
334 XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, |
|
335 XPCNativeInterface** pInterface) const |
|
336 { |
|
337 uint16_t index; |
|
338 if (!FindMember(name, pMember, &index)) |
|
339 return false; |
|
340 *pInterface = mInterfaces[index]; |
|
341 return true; |
|
342 } |
|
343 |
|
344 inline bool |
|
345 XPCNativeSet::FindMember(jsid name, |
|
346 XPCNativeMember** pMember, |
|
347 XPCNativeInterface** pInterface, |
|
348 XPCNativeSet* protoSet, |
|
349 bool* pIsLocal) const |
|
350 { |
|
351 XPCNativeMember* Member; |
|
352 XPCNativeInterface* Interface; |
|
353 XPCNativeMember* protoMember; |
|
354 |
|
355 if (!FindMember(name, &Member, &Interface)) |
|
356 return false; |
|
357 |
|
358 *pMember = Member; |
|
359 *pInterface = Interface; |
|
360 |
|
361 *pIsLocal = |
|
362 !Member || |
|
363 !protoSet || |
|
364 (protoSet != this && |
|
365 !protoSet->MatchesSetUpToInterface(this, Interface) && |
|
366 (!protoSet->FindMember(name, &protoMember, (uint16_t*)nullptr) || |
|
367 protoMember != Member)); |
|
368 |
|
369 return true; |
|
370 } |
|
371 |
|
372 inline XPCNativeInterface* |
|
373 XPCNativeSet::FindNamedInterface(jsid name) const |
|
374 { |
|
375 XPCNativeInterface* const * pp = mInterfaces; |
|
376 |
|
377 for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { |
|
378 XPCNativeInterface* iface = *pp; |
|
379 |
|
380 if (name == iface->GetName()) |
|
381 return iface; |
|
382 } |
|
383 return nullptr; |
|
384 } |
|
385 |
|
386 inline XPCNativeInterface* |
|
387 XPCNativeSet::FindInterfaceWithIID(const nsIID& iid) const |
|
388 { |
|
389 XPCNativeInterface* const * pp = mInterfaces; |
|
390 |
|
391 for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { |
|
392 XPCNativeInterface* iface = *pp; |
|
393 |
|
394 if (iface->GetIID()->Equals(iid)) |
|
395 return iface; |
|
396 } |
|
397 return nullptr; |
|
398 } |
|
399 |
|
400 inline bool |
|
401 XPCNativeSet::HasInterface(XPCNativeInterface* aInterface) const |
|
402 { |
|
403 XPCNativeInterface* const * pp = mInterfaces; |
|
404 |
|
405 for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { |
|
406 if (aInterface == *pp) |
|
407 return true; |
|
408 } |
|
409 return false; |
|
410 } |
|
411 |
|
412 inline bool |
|
413 XPCNativeSet::HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const |
|
414 { |
|
415 return HasInterfaceWithAncestor(aInterface->GetIID()); |
|
416 } |
|
417 |
|
418 inline bool |
|
419 XPCNativeSet::HasInterfaceWithAncestor(const nsIID* iid) const |
|
420 { |
|
421 // We can safely skip the first interface which is *always* nsISupports. |
|
422 XPCNativeInterface* const * pp = mInterfaces+1; |
|
423 for (int i = (int) mInterfaceCount; i > 1; i--, pp++) |
|
424 if ((*pp)->HasAncestor(iid)) |
|
425 return true; |
|
426 |
|
427 // This is rare, so check last. |
|
428 if (iid == &NS_GET_IID(nsISupports)) |
|
429 return true; |
|
430 |
|
431 return false; |
|
432 } |
|
433 |
|
434 inline bool |
|
435 XPCNativeSet::MatchesSetUpToInterface(const XPCNativeSet* other, |
|
436 XPCNativeInterface* iface) const |
|
437 { |
|
438 int count = std::min(int(mInterfaceCount), int(other->mInterfaceCount)); |
|
439 |
|
440 XPCNativeInterface* const * pp1 = mInterfaces; |
|
441 XPCNativeInterface* const * pp2 = other->mInterfaces; |
|
442 |
|
443 for (int i = (int) count; i > 0; i--, pp1++, pp2++) { |
|
444 XPCNativeInterface* cur = (*pp1); |
|
445 if (cur != (*pp2)) |
|
446 return false; |
|
447 if (cur == iface) |
|
448 return true; |
|
449 } |
|
450 return false; |
|
451 } |
|
452 |
|
453 inline void XPCNativeSet::Mark() |
|
454 { |
|
455 if (IsMarked()) |
|
456 return; |
|
457 |
|
458 XPCNativeInterface* const * pp = mInterfaces; |
|
459 |
|
460 for (int i = (int) mInterfaceCount; i > 0; i--, pp++) |
|
461 (*pp)->Mark(); |
|
462 |
|
463 MarkSelfOnly(); |
|
464 } |
|
465 |
|
466 #ifdef DEBUG |
|
467 inline void XPCNativeSet::ASSERT_NotMarked() |
|
468 { |
|
469 MOZ_ASSERT(!IsMarked(), "bad"); |
|
470 |
|
471 XPCNativeInterface* const * pp = mInterfaces; |
|
472 |
|
473 for (int i = (int) mInterfaceCount; i > 0; i--, pp++) |
|
474 MOZ_ASSERT(!(*pp)->IsMarked(), "bad"); |
|
475 } |
|
476 #endif |
|
477 |
|
478 /***************************************************************************/ |
|
479 |
|
480 inline |
|
481 JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const |
|
482 { |
|
483 return reinterpret_cast<JSObject *>(reinterpret_cast<uintptr_t>(mJSObject) & ~1); |
|
484 } |
|
485 |
|
486 inline |
|
487 JSObject* XPCWrappedNativeTearOff::GetJSObject() |
|
488 { |
|
489 JSObject *obj = GetJSObjectPreserveColor(); |
|
490 if (obj) { |
|
491 JS::ExposeObjectToActiveJS(obj); |
|
492 } |
|
493 return obj; |
|
494 } |
|
495 |
|
496 inline |
|
497 void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj) |
|
498 { |
|
499 MOZ_ASSERT(!IsMarked()); |
|
500 mJSObject = JSObj; |
|
501 } |
|
502 |
|
503 inline |
|
504 XPCWrappedNativeTearOff::~XPCWrappedNativeTearOff() |
|
505 { |
|
506 MOZ_ASSERT(!(GetInterface() || GetNative() || GetJSObjectPreserveColor()), |
|
507 "tearoff not empty in dtor"); |
|
508 } |
|
509 |
|
510 /***************************************************************************/ |
|
511 |
|
512 inline bool |
|
513 XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid) |
|
514 { |
|
515 return nullptr != GetSet()->FindInterfaceWithIID(iid); |
|
516 } |
|
517 |
|
518 inline void |
|
519 XPCWrappedNative::SweepTearOffs() |
|
520 { |
|
521 XPCWrappedNativeTearOffChunk* chunk; |
|
522 for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk) { |
|
523 XPCWrappedNativeTearOff* to = chunk->mTearOffs; |
|
524 for (int i = XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK; i > 0; i--, to++) { |
|
525 bool marked = to->IsMarked(); |
|
526 to->Unmark(); |
|
527 if (marked) |
|
528 continue; |
|
529 |
|
530 // If this tearoff does not have a live dedicated JSObject, |
|
531 // then let's recycle it. |
|
532 if (!to->GetJSObjectPreserveColor()) { |
|
533 nsISupports* obj = to->GetNative(); |
|
534 if (obj) { |
|
535 obj->Release(); |
|
536 to->SetNative(nullptr); |
|
537 } |
|
538 to->SetInterface(nullptr); |
|
539 } |
|
540 } |
|
541 } |
|
542 } |
|
543 |
|
544 /***************************************************************************/ |
|
545 |
|
546 inline bool |
|
547 xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid idArg) |
|
548 { |
|
549 JS::RootedValue prop(cx); |
|
550 JS::RootedId id(cx, idArg); |
|
551 |
|
552 if (!JS_LookupPropertyById(cx, obj, id, &prop)) |
|
553 return false; |
|
554 return true; |
|
555 } |
|
556 |
|
557 inline jsid |
|
558 GetRTIdByIndex(JSContext *cx, unsigned index) |
|
559 { |
|
560 XPCJSRuntime *rt = nsXPConnect::XPConnect()->GetRuntime(); |
|
561 return rt->GetStringID(index); |
|
562 } |
|
563 |
|
564 inline |
|
565 bool ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx) |
|
566 { |
|
567 XPCThrower::ThrowBadParam(rv, paramNum, ccx); |
|
568 return false; |
|
569 } |
|
570 |
|
571 inline |
|
572 void ThrowBadResult(nsresult result, XPCCallContext& ccx) |
|
573 { |
|
574 XPCThrower::ThrowBadResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, |
|
575 result, ccx); |
|
576 } |
|
577 |
|
578 /***************************************************************************/ |
|
579 |
|
580 #endif /* xpcinlines_h___ */ |