Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /* Library-private header for Interface Info system. */
7 :
8 : #ifndef xptiprivate_h___
9 : #define xptiprivate_h___
10 :
11 : #include "nscore.h"
12 : #include <new>
13 : #include "nsISupports.h"
14 :
15 : // this after nsISupports, to pick up IID
16 : // so that xpt stuff doesn't try to define it itself...
17 : #include "xpt_struct.h"
18 : #include "xpt_xdr.h"
19 :
20 : #include "nsIInterfaceInfo.h"
21 : #include "nsIInterfaceInfoManager.h"
22 : #include "xptinfo.h"
23 : #include "ShimInterfaceInfo.h"
24 :
25 : #include "nsIServiceManager.h"
26 : #include "nsIFile.h"
27 : #include "nsIDirectoryService.h"
28 : #include "nsDirectoryServiceDefs.h"
29 : #include "nsAppDirectoryServiceDefs.h"
30 : #include "nsIWeakReference.h"
31 :
32 : #include "mozilla/ReentrantMonitor.h"
33 : #include "mozilla/Mutex.h"
34 : #include "mozilla/Attributes.h"
35 :
36 : #include "js/TypeDecls.h"
37 :
38 : #include "nsCRT.h"
39 : #include "nsMemory.h"
40 :
41 : #include "nsCOMArray.h"
42 : #include "nsQuickSort.h"
43 :
44 : #include "nsXPIDLString.h"
45 :
46 : #include "nsIInputStream.h"
47 :
48 : #include "nsHashKeys.h"
49 : #include "nsDataHashtable.h"
50 : #include "plstr.h"
51 : #include "prprf.h"
52 : #include "prio.h"
53 : #include "prtime.h"
54 : #include "prenv.h"
55 :
56 : #include <stdio.h>
57 : #include <stdarg.h>
58 :
59 : /***************************************************************************/
60 :
61 : #if 0 && defined(DEBUG_jband)
62 : #define LOG_RESOLVE(x) printf x
63 : #define LOG_LOAD(x) printf x
64 : #define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
65 : #else
66 : #define LOG_RESOLVE(x) ((void)0)
67 : #define LOG_LOAD(x) ((void)0)
68 : #define LOG_AUTOREG(x) ((void)0)
69 : #endif
70 :
71 : #if 1 && defined(DEBUG_jband)
72 : #define SHOW_INFO_COUNT_STATS
73 : #endif
74 :
75 : /***************************************************************************/
76 :
77 : class xptiInterfaceInfo;
78 : class xptiInterfaceEntry;
79 : class xptiTypelibGuts;
80 :
81 : extern XPTArena* gXPTIStructArena;
82 :
83 : /***************************************************************************/
84 :
85 : /***************************************************************************/
86 :
87 : // No virtuals.
88 : // These are always constructed in the struct arena using placement new.
89 : // dtor need not be called.
90 :
91 : class xptiTypelibGuts
92 : {
93 : public:
94 : static xptiTypelibGuts* Create(XPTHeader* aHeader);
95 :
96 : XPTHeader* GetHeader() {return mHeader;}
97 10157 : uint16_t GetEntryCount() const {return mHeader->num_interfaces;}
98 :
99 4054 : void SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr)
100 : {
101 4054 : NS_ASSERTION(mHeader,"bad state!");
102 4054 : NS_ASSERTION(i < GetEntryCount(),"bad param!");
103 4054 : mEntryArray[i] = ptr;
104 4054 : }
105 :
106 : xptiInterfaceEntry* GetEntryAt(uint16_t i);
107 : const char* GetEntryNameAt(uint16_t i);
108 :
109 : private:
110 522 : explicit xptiTypelibGuts(XPTHeader* aHeader)
111 522 : : mHeader(aHeader)
112 522 : { }
113 : ~xptiTypelibGuts();
114 :
115 : private:
116 : XPTHeader* mHeader; // hold pointer into arena
117 : xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
118 : };
119 :
120 : /***************************************************************************/
121 :
122 : /***************************************************************************/
123 :
124 : // This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
125 : // and a set of bitflags in one 8bit value. See below.
126 :
127 : class xptiInfoFlags
128 : {
129 : enum {STATE_MASK = 3};
130 : public:
131 3849 : explicit xptiInfoFlags(uint8_t n) : mData(n) {}
132 : xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
133 :
134 79780 : static uint8_t GetStateMask()
135 79780 : {return uint8_t(STATE_MASK);}
136 :
137 : void Clear()
138 : {mData = 0;}
139 :
140 : uint8_t GetData() const
141 : {return mData;}
142 :
143 63905 : uint8_t GetState() const
144 63905 : {return mData & GetStateMask();}
145 :
146 4279 : void SetState(uint8_t state)
147 4279 : {mData &= ~GetStateMask(); mData |= state;}
148 :
149 11596 : void SetFlagBit(uint8_t flag, bool on)
150 11596 : {if(on)
151 4378 : mData |= ~GetStateMask() & flag;
152 : else
153 7218 : mData &= GetStateMask() | ~flag;}
154 :
155 7309 : bool GetFlagBit(uint8_t flag) const
156 7309 : {return (mData & flag) ? true : false;}
157 :
158 : private:
159 : uint8_t mData;
160 : };
161 :
162 : /****************************************************/
163 :
164 : // No virtual methods.
165 : // We always create in the struct arena and construct using "placement new".
166 : // No members need dtor calls.
167 :
168 : class xptiInterfaceEntry
169 : {
170 : public:
171 : static xptiInterfaceEntry* Create(const char* name,
172 : const nsID& iid,
173 : XPTInterfaceDescriptor* aDescriptor,
174 : xptiTypelibGuts* aTypelib);
175 :
176 : enum {
177 : PARTIALLY_RESOLVED = 1,
178 : FULLY_RESOLVED = 2,
179 : RESOLVE_FAILED = 3
180 : };
181 :
182 : // Additional bit flags...
183 : enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16,
184 : MAIN_PROCESS_SCRIPTABLE_ONLY = 32};
185 :
186 63905 : uint8_t GetResolveState() const {return mFlags.GetState();}
187 :
188 63045 : bool IsFullyResolved() const
189 63045 : {return GetResolveState() == (uint8_t) FULLY_RESOLVED;}
190 :
191 3849 : void SetScriptableFlag(bool on)
192 3849 : {mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);}
193 2869 : bool GetScriptableFlag() const
194 2869 : {return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));}
195 3849 : void SetBuiltinClassFlag(bool on)
196 3849 : {mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);}
197 1250 : bool GetBuiltinClassFlag() const
198 1250 : {return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));}
199 3849 : void SetMainProcessScriptableOnlyFlag(bool on)
200 3849 : {mFlags.SetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY),on);}
201 1823 : bool GetMainProcessScriptableOnlyFlag() const
202 1823 : {return mFlags.GetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY));}
203 :
204 :
205 : // AddRef/Release are special and are not considered for the NOTXPCOM flag.
206 49 : void SetHasNotXPCOMFlag()
207 : {
208 49 : mFlags.SetFlagBit(HASNOTXPCOM, true);
209 49 : }
210 1367 : bool GetHasNotXPCOMFlag() const
211 : {
212 1367 : return mFlags.GetFlagBit(HASNOTXPCOM);
213 : }
214 :
215 : const nsID* GetTheIID() const {return &mIID;}
216 3849 : const char* GetTheName() const {return mName;}
217 :
218 62423 : bool EnsureResolved()
219 62423 : {return IsFullyResolved() ? true : Resolve();}
220 :
221 : already_AddRefed<xptiInterfaceInfo> InterfaceInfo();
222 65 : bool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
223 65 : {return info == mInfo;}
224 :
225 : void LockedInvalidateInterfaceInfo();
226 65 : void LockedInterfaceInfoDeathNotification() {mInfo = nullptr;}
227 :
228 63 : xptiInterfaceEntry* Parent() const {
229 63 : NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?");
230 63 : return mParent;
231 : }
232 :
233 6004 : const nsID& IID() const { return mIID; }
234 :
235 : //////////////////////
236 : // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
237 :
238 : nsresult GetName(char * *aName);
239 : nsresult GetIID(nsIID * *aIID);
240 : nsresult IsScriptable(bool *_retval);
241 310 : nsresult IsBuiltinClass(bool *_retval) {
242 310 : *_retval = GetBuiltinClassFlag();
243 310 : return NS_OK;
244 : }
245 1823 : nsresult IsMainProcessScriptableOnly(bool *_retval) {
246 1823 : *_retval = GetMainProcessScriptableOnlyFlag();
247 1823 : return NS_OK;
248 : }
249 : // Except this one.
250 : //nsresult GetParent(nsIInterfaceInfo * *aParent);
251 : nsresult GetMethodCount(uint16_t *aMethodCount);
252 : nsresult GetConstantCount(uint16_t *aConstantCount);
253 : nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info);
254 : nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info);
255 : nsresult GetConstant(uint16_t index, JS::MutableHandleValue, char** constant);
256 : nsresult GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
257 : nsresult GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
258 : nsresult GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval);
259 : nsresult GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval);
260 : nsresult GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval);
261 : nsresult IsIID(const nsIID * IID, bool *_retval);
262 : nsresult GetNameShared(const char **name);
263 : nsresult GetIIDShared(const nsIID * *iid);
264 : nsresult IsFunction(bool *_retval);
265 : nsresult HasAncestor(const nsIID * iid, bool *_retval);
266 : nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
267 :
268 : private:
269 : xptiInterfaceEntry(const char* name,
270 : size_t nameLength,
271 : const nsID& iid,
272 : XPTInterfaceDescriptor* aDescriptor,
273 : xptiTypelibGuts* aTypelib);
274 : ~xptiInterfaceEntry();
275 :
276 4279 : void SetResolvedState(int state)
277 4279 : {mFlags.SetState(uint8_t(state));}
278 :
279 : bool Resolve();
280 :
281 : // We only call these "*Locked" variants after locking. This is done to
282 : // allow reentrace as files are loaded and various interfaces resolved
283 : // without having to worry about the locked state.
284 :
285 427 : bool EnsureResolvedLocked()
286 427 : {return IsFullyResolved() ? true : ResolveLocked();}
287 : bool ResolveLocked();
288 :
289 : // private helpers
290 :
291 : nsresult GetEntryForParam(uint16_t methodIndex,
292 : const nsXPTParamInfo * param,
293 : xptiInterfaceEntry** entry);
294 :
295 : nsresult GetTypeInArray(const nsXPTParamInfo* param,
296 : uint16_t dimension,
297 : const XPTTypeDescriptor** type);
298 :
299 : nsresult GetInterfaceIndexForParam(uint16_t methodIndex,
300 : const nsXPTParamInfo* param,
301 : uint16_t* interfaceIndex);
302 :
303 : already_AddRefed<ShimInterfaceInfo>
304 : GetShimForParam(uint16_t methodIndex, const nsXPTParamInfo* param);
305 :
306 : private:
307 : nsID mIID;
308 : XPTInterfaceDescriptor* mDescriptor;
309 :
310 : xptiTypelibGuts* mTypelib;
311 :
312 : xptiInterfaceEntry* mParent; // Valid only when fully resolved
313 :
314 : xptiInterfaceInfo* MOZ_UNSAFE_REF("The safety of this pointer is ensured "
315 : "by the semantics of xptiWorkingSet.")
316 : mInfo; // May come and go.
317 :
318 : uint16_t mMethodBaseIndex;
319 : uint16_t mConstantBaseIndex;
320 :
321 : xptiInfoFlags mFlags;
322 :
323 : char mName[1]; // Always last. Sized to fit.
324 : };
325 :
326 : class xptiInterfaceInfo final : public nsIInterfaceInfo
327 : {
328 : public:
329 : NS_DECL_THREADSAFE_ISUPPORTS
330 :
331 : // Use delegation to implement (most!) of nsIInterfaceInfo.
332 1171 : NS_IMETHOD GetName(char * *aName) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
333 0 : NS_IMETHOD GetInterfaceIID(nsIID * *aIID) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
334 2869 : NS_IMETHOD IsScriptable(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
335 310 : NS_IMETHOD IsBuiltinClass(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); }
336 1823 : NS_IMETHOD IsMainProcessScriptableOnly(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsMainProcessScriptableOnly(_retval); }
337 : // Except this one.
338 21 : NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) override
339 : {
340 21 : if(!EnsureResolved() || !EnsureParent())
341 0 : return NS_ERROR_UNEXPECTED;
342 21 : NS_IF_ADDREF(*aParent = mParent);
343 21 : return NS_OK;
344 : }
345 1915 : NS_IMETHOD GetMethodCount(uint16_t *aMethodCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
346 1823 : NS_IMETHOD GetConstantCount(uint16_t *aConstantCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
347 28270 : NS_IMETHOD GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
348 0 : NS_IMETHOD GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
349 4014 : NS_IMETHOD GetConstant(uint16_t index, JS::MutableHandleValue constant, char** name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant, name); }
350 0 : NS_IMETHOD GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
351 0 : NS_IMETHOD GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
352 90 : NS_IMETHOD GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
353 65 : NS_IMETHOD GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
354 105 : NS_IMETHOD GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
355 482 : NS_IMETHOD IsIID(const nsIID * IID, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
356 3838 : NS_IMETHOD GetNameShared(const char **name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
357 22957 : NS_IMETHOD GetIIDShared(const nsIID * *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
358 758 : NS_IMETHOD IsFunction(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
359 2433 : NS_IMETHOD HasAncestor(const nsIID * iid, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
360 5610 : NS_IMETHOD GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
361 :
362 : public:
363 : explicit xptiInterfaceInfo(xptiInterfaceEntry* entry);
364 :
365 : void Invalidate();
366 :
367 : private:
368 :
369 : ~xptiInterfaceInfo();
370 :
371 : // Note that mParent might still end up as nullptr if we don't have one.
372 21 : bool EnsureParent()
373 : {
374 21 : NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
375 21 : return mParent || !mEntry->Parent() || BuildParent();
376 : }
377 :
378 21 : bool EnsureResolved()
379 : {
380 21 : return mEntry && mEntry->EnsureResolved();
381 : }
382 :
383 : bool BuildParent();
384 :
385 : xptiInterfaceInfo(); // not implemented
386 :
387 : private:
388 : xptiInterfaceEntry* mEntry;
389 : RefPtr<xptiInterfaceInfo> mParent;
390 : };
391 :
392 : /***************************************************************************/
393 :
394 : #endif /* xptiprivate_h___ */
|