|
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 |
|
24 #include "nsIServiceManager.h" |
|
25 #include "nsIFile.h" |
|
26 #include "nsIDirectoryService.h" |
|
27 #include "nsDirectoryServiceDefs.h" |
|
28 #include "nsAppDirectoryServiceDefs.h" |
|
29 #include "nsIWeakReference.h" |
|
30 |
|
31 #include "mozilla/ReentrantMonitor.h" |
|
32 #include "mozilla/Mutex.h" |
|
33 #include "mozilla/Attributes.h" |
|
34 |
|
35 #include "nsCRT.h" |
|
36 #include "nsMemory.h" |
|
37 |
|
38 #include "nsCOMArray.h" |
|
39 #include "nsQuickSort.h" |
|
40 |
|
41 #include "nsXPIDLString.h" |
|
42 |
|
43 #include "nsIInputStream.h" |
|
44 |
|
45 #include "nsHashKeys.h" |
|
46 #include "nsDataHashtable.h" |
|
47 #include "plstr.h" |
|
48 #include "prprf.h" |
|
49 #include "prio.h" |
|
50 #include "prtime.h" |
|
51 #include "prenv.h" |
|
52 |
|
53 #include <stdio.h> |
|
54 #include <stdarg.h> |
|
55 |
|
56 /***************************************************************************/ |
|
57 |
|
58 #if 0 && defined(DEBUG_jband) |
|
59 #define LOG_RESOLVE(x) printf x |
|
60 #define LOG_LOAD(x) printf x |
|
61 #define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0) |
|
62 #else |
|
63 #define LOG_RESOLVE(x) ((void)0) |
|
64 #define LOG_LOAD(x) ((void)0) |
|
65 #define LOG_AUTOREG(x) ((void)0) |
|
66 #endif |
|
67 |
|
68 #if 1 && defined(DEBUG_jband) |
|
69 #define SHOW_INFO_COUNT_STATS |
|
70 #endif |
|
71 |
|
72 /***************************************************************************/ |
|
73 |
|
74 class xptiInterfaceInfo; |
|
75 class xptiInterfaceEntry; |
|
76 class xptiTypelibGuts; |
|
77 |
|
78 extern XPTArena* gXPTIStructArena; |
|
79 |
|
80 /***************************************************************************/ |
|
81 |
|
82 /***************************************************************************/ |
|
83 |
|
84 // No virtuals. |
|
85 // These are always constructed in the struct arena using placement new. |
|
86 // dtor need not be called. |
|
87 |
|
88 class xptiTypelibGuts |
|
89 { |
|
90 public: |
|
91 static xptiTypelibGuts* Create(XPTHeader* aHeader); |
|
92 |
|
93 XPTHeader* GetHeader() {return mHeader;} |
|
94 uint16_t GetEntryCount() const {return mHeader->num_interfaces;} |
|
95 |
|
96 void SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr) |
|
97 { |
|
98 NS_ASSERTION(mHeader,"bad state!"); |
|
99 NS_ASSERTION(i < GetEntryCount(),"bad param!"); |
|
100 mEntryArray[i] = ptr; |
|
101 } |
|
102 |
|
103 xptiInterfaceEntry* GetEntryAt(uint16_t i); |
|
104 |
|
105 private: |
|
106 xptiTypelibGuts(XPTHeader* aHeader) |
|
107 : mHeader(aHeader) |
|
108 { } |
|
109 ~xptiTypelibGuts(); |
|
110 |
|
111 private: |
|
112 XPTHeader* mHeader; // hold pointer into arena |
|
113 xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit. |
|
114 }; |
|
115 |
|
116 /***************************************************************************/ |
|
117 |
|
118 /***************************************************************************/ |
|
119 |
|
120 // This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value |
|
121 // and a set of bitflags in one 8bit value. See below. |
|
122 |
|
123 class xptiInfoFlags |
|
124 { |
|
125 enum {STATE_MASK = 3}; |
|
126 public: |
|
127 xptiInfoFlags(uint8_t n) : mData(n) {} |
|
128 xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {} |
|
129 |
|
130 static uint8_t GetStateMask() |
|
131 {return uint8_t(STATE_MASK);} |
|
132 |
|
133 void Clear() |
|
134 {mData = 0;} |
|
135 |
|
136 uint8_t GetData() const |
|
137 {return mData;} |
|
138 |
|
139 uint8_t GetState() const |
|
140 {return mData & GetStateMask();} |
|
141 |
|
142 void SetState(uint8_t state) |
|
143 {mData &= ~GetStateMask(); mData |= state;} |
|
144 |
|
145 void SetFlagBit(uint8_t flag, bool on) |
|
146 {if(on) |
|
147 mData |= ~GetStateMask() & flag; |
|
148 else |
|
149 mData &= GetStateMask() | ~flag;} |
|
150 |
|
151 bool GetFlagBit(uint8_t flag) const |
|
152 {return (mData & flag) ? true : false;} |
|
153 |
|
154 private: |
|
155 uint8_t mData; |
|
156 }; |
|
157 |
|
158 /****************************************************/ |
|
159 |
|
160 // No virtual methods. |
|
161 // We always create in the struct arena and construct using "placement new". |
|
162 // No members need dtor calls. |
|
163 |
|
164 class xptiInterfaceEntry |
|
165 { |
|
166 public: |
|
167 static xptiInterfaceEntry* Create(const char* name, |
|
168 const nsID& iid, |
|
169 XPTInterfaceDescriptor* aDescriptor, |
|
170 xptiTypelibGuts* aTypelib); |
|
171 |
|
172 enum { |
|
173 PARTIALLY_RESOLVED = 1, |
|
174 FULLY_RESOLVED = 2, |
|
175 RESOLVE_FAILED = 3 |
|
176 }; |
|
177 |
|
178 // Additional bit flags... |
|
179 enum {SCRIPTABLE = 4, BUILTINCLASS = 8}; |
|
180 |
|
181 uint8_t GetResolveState() const {return mFlags.GetState();} |
|
182 |
|
183 bool IsFullyResolved() const |
|
184 {return GetResolveState() == (uint8_t) FULLY_RESOLVED;} |
|
185 |
|
186 void SetScriptableFlag(bool on) |
|
187 {mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);} |
|
188 bool GetScriptableFlag() const |
|
189 {return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));} |
|
190 void SetBuiltinClassFlag(bool on) |
|
191 {mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);} |
|
192 bool GetBuiltinClassFlag() const |
|
193 {return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));} |
|
194 |
|
195 const nsID* GetTheIID() const {return &mIID;} |
|
196 const char* GetTheName() const {return mName;} |
|
197 |
|
198 bool EnsureResolved() |
|
199 {return IsFullyResolved() ? true : Resolve();} |
|
200 |
|
201 already_AddRefed<xptiInterfaceInfo> InterfaceInfo(); |
|
202 bool InterfaceInfoEquals(const xptiInterfaceInfo* info) const |
|
203 {return info == mInfo;} |
|
204 |
|
205 void LockedInvalidateInterfaceInfo(); |
|
206 void LockedInterfaceInfoDeathNotification() {mInfo = nullptr;} |
|
207 |
|
208 xptiInterfaceEntry* Parent() const { |
|
209 NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?"); |
|
210 return mParent; |
|
211 } |
|
212 |
|
213 const nsID& IID() const { return mIID; } |
|
214 |
|
215 ////////////////////// |
|
216 // These non-virtual methods handle the delegated nsIInterfaceInfo methods. |
|
217 |
|
218 nsresult GetName(char * *aName); |
|
219 nsresult GetIID(nsIID * *aIID); |
|
220 nsresult IsScriptable(bool *_retval); |
|
221 nsresult IsBuiltinClass(bool *_retval) { |
|
222 *_retval = GetBuiltinClassFlag(); |
|
223 return NS_OK; |
|
224 } |
|
225 // Except this one. |
|
226 //nsresult GetParent(nsIInterfaceInfo * *aParent); |
|
227 nsresult GetMethodCount(uint16_t *aMethodCount); |
|
228 nsresult GetConstantCount(uint16_t *aConstantCount); |
|
229 nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info); |
|
230 nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info); |
|
231 nsresult GetConstant(uint16_t index, const nsXPTConstant * *constant); |
|
232 nsresult GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval); |
|
233 nsresult GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval); |
|
234 nsresult GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval); |
|
235 nsresult GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval); |
|
236 nsresult GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval); |
|
237 nsresult IsIID(const nsIID * IID, bool *_retval); |
|
238 nsresult GetNameShared(const char **name); |
|
239 nsresult GetIIDShared(const nsIID * *iid); |
|
240 nsresult IsFunction(bool *_retval); |
|
241 nsresult HasAncestor(const nsIID * iid, bool *_retval); |
|
242 nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid); |
|
243 |
|
244 private: |
|
245 xptiInterfaceEntry(const char* name, |
|
246 size_t nameLength, |
|
247 const nsID& iid, |
|
248 XPTInterfaceDescriptor* aDescriptor, |
|
249 xptiTypelibGuts* aTypelib); |
|
250 ~xptiInterfaceEntry(); |
|
251 |
|
252 void SetResolvedState(int state) |
|
253 {mFlags.SetState(uint8_t(state));} |
|
254 |
|
255 bool Resolve(); |
|
256 |
|
257 // We only call these "*Locked" variants after locking. This is done to |
|
258 // allow reentrace as files are loaded and various interfaces resolved |
|
259 // without having to worry about the locked state. |
|
260 |
|
261 bool EnsureResolvedLocked() |
|
262 {return IsFullyResolved() ? true : ResolveLocked();} |
|
263 bool ResolveLocked(); |
|
264 |
|
265 // private helpers |
|
266 |
|
267 nsresult GetEntryForParam(uint16_t methodIndex, |
|
268 const nsXPTParamInfo * param, |
|
269 xptiInterfaceEntry** entry); |
|
270 |
|
271 nsresult GetTypeInArray(const nsXPTParamInfo* param, |
|
272 uint16_t dimension, |
|
273 const XPTTypeDescriptor** type); |
|
274 |
|
275 private: |
|
276 nsID mIID; |
|
277 XPTInterfaceDescriptor* mDescriptor; |
|
278 |
|
279 uint16_t mMethodBaseIndex; |
|
280 uint16_t mConstantBaseIndex; |
|
281 xptiTypelibGuts* mTypelib; |
|
282 |
|
283 xptiInterfaceEntry* mParent; // Valid only when fully resolved |
|
284 |
|
285 xptiInterfaceInfo* mInfo; // May come and go. |
|
286 xptiInfoFlags mFlags; |
|
287 char mName[1]; // Always last. Sized to fit. |
|
288 }; |
|
289 |
|
290 class xptiInterfaceInfo MOZ_FINAL : public nsIInterfaceInfo |
|
291 { |
|
292 public: |
|
293 NS_DECL_THREADSAFE_ISUPPORTS |
|
294 |
|
295 // Use delegation to implement (most!) of nsIInterfaceInfo. |
|
296 NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); } |
|
297 NS_IMETHOD GetInterfaceIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); } |
|
298 NS_IMETHOD IsScriptable(bool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); } |
|
299 NS_IMETHOD IsBuiltinClass(bool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); } |
|
300 // Except this one. |
|
301 NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) |
|
302 { |
|
303 if(!EnsureResolved() || !EnsureParent()) |
|
304 return NS_ERROR_UNEXPECTED; |
|
305 NS_IF_ADDREF(*aParent = mParent); |
|
306 return NS_OK; |
|
307 } |
|
308 NS_IMETHOD GetMethodCount(uint16_t *aMethodCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); } |
|
309 NS_IMETHOD GetConstantCount(uint16_t *aConstantCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); } |
|
310 NS_IMETHOD GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); } |
|
311 NS_IMETHOD GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); } |
|
312 NS_IMETHOD GetConstant(uint16_t index, const nsXPTConstant * *constant) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant); } |
|
313 NS_IMETHOD GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); } |
|
314 NS_IMETHOD GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); } |
|
315 NS_IMETHOD GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); } |
|
316 NS_IMETHOD GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); } |
|
317 NS_IMETHOD GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); } |
|
318 NS_IMETHOD IsIID(const nsIID * IID, bool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); } |
|
319 NS_IMETHOD GetNameShared(const char **name) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); } |
|
320 NS_IMETHOD GetIIDShared(const nsIID * *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); } |
|
321 NS_IMETHOD IsFunction(bool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); } |
|
322 NS_IMETHOD HasAncestor(const nsIID * iid, bool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); } |
|
323 NS_IMETHOD GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); } |
|
324 |
|
325 public: |
|
326 xptiInterfaceInfo(xptiInterfaceEntry* entry); |
|
327 |
|
328 void Invalidate() |
|
329 {NS_IF_RELEASE(mParent); mEntry = nullptr;} |
|
330 |
|
331 private: |
|
332 |
|
333 ~xptiInterfaceInfo(); |
|
334 |
|
335 // Note that mParent might still end up as nullptr if we don't have one. |
|
336 bool EnsureParent() |
|
337 { |
|
338 NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call"); |
|
339 return mParent || !mEntry->Parent() || BuildParent(); |
|
340 } |
|
341 |
|
342 bool EnsureResolved() |
|
343 { |
|
344 return mEntry && mEntry->EnsureResolved(); |
|
345 } |
|
346 |
|
347 bool BuildParent(); |
|
348 |
|
349 xptiInterfaceInfo(); // not implemented |
|
350 |
|
351 private: |
|
352 xptiInterfaceEntry* mEntry; |
|
353 xptiInterfaceInfo* mParent; |
|
354 }; |
|
355 |
|
356 /***************************************************************************/ |
|
357 |
|
358 #endif /* xptiprivate_h___ */ |