Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
6 /* Library-private header for Interface Info system. */
8 #ifndef xptiprivate_h___
9 #define xptiprivate_h___
11 #include "nscore.h"
12 #include <new>
13 #include "nsISupports.h"
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"
20 #include "nsIInterfaceInfo.h"
21 #include "nsIInterfaceInfoManager.h"
22 #include "xptinfo.h"
24 #include "nsIServiceManager.h"
25 #include "nsIFile.h"
26 #include "nsIDirectoryService.h"
27 #include "nsDirectoryServiceDefs.h"
28 #include "nsAppDirectoryServiceDefs.h"
29 #include "nsIWeakReference.h"
31 #include "mozilla/ReentrantMonitor.h"
32 #include "mozilla/Mutex.h"
33 #include "mozilla/Attributes.h"
35 #include "nsCRT.h"
36 #include "nsMemory.h"
38 #include "nsCOMArray.h"
39 #include "nsQuickSort.h"
41 #include "nsXPIDLString.h"
43 #include "nsIInputStream.h"
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"
53 #include <stdio.h>
54 #include <stdarg.h>
56 /***************************************************************************/
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
68 #if 1 && defined(DEBUG_jband)
69 #define SHOW_INFO_COUNT_STATS
70 #endif
72 /***************************************************************************/
74 class xptiInterfaceInfo;
75 class xptiInterfaceEntry;
76 class xptiTypelibGuts;
78 extern XPTArena* gXPTIStructArena;
80 /***************************************************************************/
82 /***************************************************************************/
84 // No virtuals.
85 // These are always constructed in the struct arena using placement new.
86 // dtor need not be called.
88 class xptiTypelibGuts
89 {
90 public:
91 static xptiTypelibGuts* Create(XPTHeader* aHeader);
93 XPTHeader* GetHeader() {return mHeader;}
94 uint16_t GetEntryCount() const {return mHeader->num_interfaces;}
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 }
103 xptiInterfaceEntry* GetEntryAt(uint16_t i);
105 private:
106 xptiTypelibGuts(XPTHeader* aHeader)
107 : mHeader(aHeader)
108 { }
109 ~xptiTypelibGuts();
111 private:
112 XPTHeader* mHeader; // hold pointer into arena
113 xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
114 };
116 /***************************************************************************/
118 /***************************************************************************/
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.
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) {}
130 static uint8_t GetStateMask()
131 {return uint8_t(STATE_MASK);}
133 void Clear()
134 {mData = 0;}
136 uint8_t GetData() const
137 {return mData;}
139 uint8_t GetState() const
140 {return mData & GetStateMask();}
142 void SetState(uint8_t state)
143 {mData &= ~GetStateMask(); mData |= state;}
145 void SetFlagBit(uint8_t flag, bool on)
146 {if(on)
147 mData |= ~GetStateMask() & flag;
148 else
149 mData &= GetStateMask() | ~flag;}
151 bool GetFlagBit(uint8_t flag) const
152 {return (mData & flag) ? true : false;}
154 private:
155 uint8_t mData;
156 };
158 /****************************************************/
160 // No virtual methods.
161 // We always create in the struct arena and construct using "placement new".
162 // No members need dtor calls.
164 class xptiInterfaceEntry
165 {
166 public:
167 static xptiInterfaceEntry* Create(const char* name,
168 const nsID& iid,
169 XPTInterfaceDescriptor* aDescriptor,
170 xptiTypelibGuts* aTypelib);
172 enum {
173 PARTIALLY_RESOLVED = 1,
174 FULLY_RESOLVED = 2,
175 RESOLVE_FAILED = 3
176 };
178 // Additional bit flags...
179 enum {SCRIPTABLE = 4, BUILTINCLASS = 8};
181 uint8_t GetResolveState() const {return mFlags.GetState();}
183 bool IsFullyResolved() const
184 {return GetResolveState() == (uint8_t) FULLY_RESOLVED;}
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));}
195 const nsID* GetTheIID() const {return &mIID;}
196 const char* GetTheName() const {return mName;}
198 bool EnsureResolved()
199 {return IsFullyResolved() ? true : Resolve();}
201 already_AddRefed<xptiInterfaceInfo> InterfaceInfo();
202 bool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
203 {return info == mInfo;}
205 void LockedInvalidateInterfaceInfo();
206 void LockedInterfaceInfoDeathNotification() {mInfo = nullptr;}
208 xptiInterfaceEntry* Parent() const {
209 NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?");
210 return mParent;
211 }
213 const nsID& IID() const { return mIID; }
215 //////////////////////
216 // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
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);
244 private:
245 xptiInterfaceEntry(const char* name,
246 size_t nameLength,
247 const nsID& iid,
248 XPTInterfaceDescriptor* aDescriptor,
249 xptiTypelibGuts* aTypelib);
250 ~xptiInterfaceEntry();
252 void SetResolvedState(int state)
253 {mFlags.SetState(uint8_t(state));}
255 bool Resolve();
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.
261 bool EnsureResolvedLocked()
262 {return IsFullyResolved() ? true : ResolveLocked();}
263 bool ResolveLocked();
265 // private helpers
267 nsresult GetEntryForParam(uint16_t methodIndex,
268 const nsXPTParamInfo * param,
269 xptiInterfaceEntry** entry);
271 nsresult GetTypeInArray(const nsXPTParamInfo* param,
272 uint16_t dimension,
273 const XPTTypeDescriptor** type);
275 private:
276 nsID mIID;
277 XPTInterfaceDescriptor* mDescriptor;
279 uint16_t mMethodBaseIndex;
280 uint16_t mConstantBaseIndex;
281 xptiTypelibGuts* mTypelib;
283 xptiInterfaceEntry* mParent; // Valid only when fully resolved
285 xptiInterfaceInfo* mInfo; // May come and go.
286 xptiInfoFlags mFlags;
287 char mName[1]; // Always last. Sized to fit.
288 };
290 class xptiInterfaceInfo MOZ_FINAL : public nsIInterfaceInfo
291 {
292 public:
293 NS_DECL_THREADSAFE_ISUPPORTS
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); }
325 public:
326 xptiInterfaceInfo(xptiInterfaceEntry* entry);
328 void Invalidate()
329 {NS_IF_RELEASE(mParent); mEntry = nullptr;}
331 private:
333 ~xptiInterfaceInfo();
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 }
342 bool EnsureResolved()
343 {
344 return mEntry && mEntry->EnsureResolved();
345 }
347 bool BuildParent();
349 xptiInterfaceInfo(); // not implemented
351 private:
352 xptiInterfaceEntry* mEntry;
353 xptiInterfaceInfo* mParent;
354 };
356 /***************************************************************************/
358 #endif /* xptiprivate_h___ */