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 #ifndef nsComponentManager_h__
7 #define nsComponentManager_h__
9 #include "nsXPCOM.h"
11 #include "xpcom-private.h"
12 #include "nsIComponentManager.h"
13 #include "nsIComponentRegistrar.h"
14 #include "nsIMemoryReporter.h"
15 #include "nsIServiceManager.h"
16 #include "nsIFile.h"
17 #include "mozilla/MemoryReporting.h"
18 #include "mozilla/Module.h"
19 #include "mozilla/ModuleLoader.h"
20 #include "mozilla/Mutex.h"
21 #include "nsXULAppAPI.h"
22 #include "nsNativeComponentLoader.h"
23 #include "nsIFactory.h"
24 #include "nsIInterfaceRequestor.h"
25 #include "nsIInterfaceRequestorUtils.h"
26 #include "pldhash.h"
27 #include "prtime.h"
28 #include "nsCOMPtr.h"
29 #include "nsAutoPtr.h"
30 #include "nsWeakReference.h"
31 #include "plarena.h"
32 #include "nsCOMArray.h"
33 #include "nsDataHashtable.h"
34 #include "nsInterfaceHashtable.h"
35 #include "nsClassHashtable.h"
36 #include "nsTArray.h"
38 #include "mozilla/Omnijar.h"
39 #include "mozilla/Attributes.h"
41 struct nsFactoryEntry;
42 class nsIServiceManager;
43 struct PRThread;
45 #define NS_COMPONENTMANAGER_CID \
46 { /* 91775d60-d5dc-11d2-92fb-00e09805570f */ \
47 0x91775d60, \
48 0xd5dc, \
49 0x11d2, \
50 {0x92, 0xfb, 0x00, 0xe0, 0x98, 0x05, 0x57, 0x0f} \
51 }
53 /* keys for registry use */
54 extern const char xpcomKeyName[];
55 extern const char xpcomComponentsKeyName[];
56 extern const char lastModValueName[];
57 extern const char fileSizeValueName[];
58 extern const char nativeComponentType[];
59 extern const char staticComponentType[];
61 #ifdef DEBUG
62 #define XPCOM_CHECK_PENDING_CIDS
63 #endif
64 ////////////////////////////////////////////////////////////////////////////////
66 extern const mozilla::Module kXPCOMModule;
68 /**
69 * This is a wrapper around mozilla::Mutex which provides runtime
70 * checking for a deadlock where the same thread tries to lock a mutex while
71 * it is already locked. This checking is present in both debug and release
72 * builds.
73 */
74 class SafeMutex
75 {
76 public:
77 SafeMutex(const char* name)
78 : mMutex(name)
79 , mOwnerThread(nullptr)
80 { }
81 ~SafeMutex()
82 { }
84 void Lock()
85 {
86 AssertNotCurrentThreadOwns();
87 mMutex.Lock();
88 MOZ_ASSERT(mOwnerThread == nullptr);
89 mOwnerThread = PR_GetCurrentThread();
90 }
92 void Unlock()
93 {
94 MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread());
95 mOwnerThread = nullptr;
96 mMutex.Unlock();
97 }
99 void AssertCurrentThreadOwns() const
100 {
101 // This method is a debug-only check
102 MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread());
103 }
105 MOZ_NEVER_INLINE void AssertNotCurrentThreadOwns() const
106 {
107 // This method is a release-mode check
108 if (PR_GetCurrentThread() == mOwnerThread) {
109 MOZ_CRASH();
110 }
111 }
113 private:
114 mozilla::Mutex mMutex;
115 volatile PRThread* mOwnerThread;
116 };
118 typedef mozilla::BaseAutoLock<SafeMutex> SafeMutexAutoLock;
119 typedef mozilla::BaseAutoUnlock<SafeMutex> SafeMutexAutoUnlock;
121 class nsComponentManagerImpl MOZ_FINAL
122 : public nsIComponentManager
123 , public nsIServiceManager
124 , public nsSupportsWeakReference
125 , public nsIComponentRegistrar
126 , public nsIInterfaceRequestor
127 , public nsIMemoryReporter
128 {
129 public:
130 NS_DECL_THREADSAFE_ISUPPORTS
131 NS_DECL_NSIINTERFACEREQUESTOR
132 NS_DECL_NSICOMPONENTMANAGER
133 NS_DECL_NSICOMPONENTREGISTRAR
134 NS_DECL_NSIMEMORYREPORTER
136 static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
138 nsresult RegistryLocationForFile(nsIFile* aFile,
139 nsCString& aResult);
140 nsresult FileForRegistryLocation(const nsCString &aLocation,
141 nsIFile **aSpec);
143 NS_DECL_NSISERVICEMANAGER
145 // nsComponentManagerImpl methods:
146 nsComponentManagerImpl();
148 static nsComponentManagerImpl* gComponentManager;
149 nsresult Init();
151 nsresult Shutdown(void);
153 nsresult FreeServices();
155 already_AddRefed<mozilla::ModuleLoader> LoaderForExtension(const nsACString& aExt);
156 nsInterfaceHashtable<nsCStringHashKey, mozilla::ModuleLoader> mLoaderMap;
158 already_AddRefed<nsIFactory> FindFactory(const nsCID& aClass);
159 already_AddRefed<nsIFactory> FindFactory(const char *contractID,
160 uint32_t aContractIDLen);
162 already_AddRefed<nsIFactory> LoadFactory(nsFactoryEntry *aEntry);
164 nsFactoryEntry *GetFactoryEntry(const char *aContractID,
165 uint32_t aContractIDLen);
166 nsFactoryEntry *GetFactoryEntry(const nsCID &aClass);
168 nsDataHashtable<nsIDHashKey, nsFactoryEntry*> mFactories;
169 nsDataHashtable<nsCStringHashKey, nsFactoryEntry*> mContractIDs;
171 SafeMutex mLock;
173 static void InitializeStaticModules();
174 static void InitializeModuleLocations();
176 struct ComponentLocation
177 {
178 NSLocationType type;
179 mozilla::FileLocation location;
180 };
182 class ComponentLocationComparator
183 {
184 public:
185 bool Equals(const ComponentLocation& a, const ComponentLocation& b) const
186 {
187 return (a.type == b.type && a.location.Equals(b.location));
188 }
189 };
191 static nsTArray<const mozilla::Module*>* sStaticModules;
192 static nsTArray<ComponentLocation>* sModuleLocations;
194 nsNativeModuleLoader mNativeModuleLoader;
196 class KnownModule
197 {
198 public:
199 /**
200 * Static or binary module.
201 */
202 KnownModule(const mozilla::Module* aModule, mozilla::FileLocation &aFile)
203 : mModule(aModule)
204 , mFile(aFile)
205 , mLoaded(false)
206 , mFailed(false)
207 { }
209 KnownModule(const mozilla::Module* aModule)
210 : mModule(aModule)
211 , mLoaded(false)
212 , mFailed(false)
213 { }
215 KnownModule(mozilla::FileLocation &aFile)
216 : mModule(nullptr)
217 , mFile(aFile)
218 , mLoader(nullptr)
219 , mLoaded(false)
220 , mFailed(false)
221 { }
223 ~KnownModule()
224 {
225 if (mLoaded && mModule->unloadProc)
226 mModule->unloadProc();
227 }
229 bool EnsureLoader();
230 bool Load();
232 const mozilla::Module* Module() const
233 {
234 return mModule;
235 }
237 /**
238 * For error logging, get a description of this module, either the
239 * file path, or <static module>.
240 */
241 nsCString Description() const;
243 private:
244 const mozilla::Module* mModule;
245 mozilla::FileLocation mFile;
246 nsCOMPtr<mozilla::ModuleLoader> mLoader;
247 bool mLoaded;
248 bool mFailed;
249 };
251 // The KnownModule is kept alive by these members, it is
252 // referenced by pointer from the factory entries.
253 nsTArray< nsAutoPtr<KnownModule> > mKnownStaticModules;
254 // The key is the URI string of the module
255 nsClassHashtable<nsCStringHashKey, KnownModule> mKnownModules;
257 // Mutex not held
258 void RegisterModule(const mozilla::Module* aModule,
259 mozilla::FileLocation* aFile);
262 // Mutex held
263 void RegisterCIDEntryLocked(const mozilla::Module::CIDEntry* aEntry,
264 KnownModule* aModule);
265 void RegisterContractIDLocked(const mozilla::Module::ContractIDEntry* aEntry);
267 // Mutex not held
268 void RegisterManifest(NSLocationType aType, mozilla::FileLocation &aFile,
269 bool aChromeOnly);
271 struct ManifestProcessingContext
272 {
273 ManifestProcessingContext(NSLocationType aType, mozilla::FileLocation &aFile, bool aChromeOnly)
274 : mType(aType)
275 , mFile(aFile)
276 , mChromeOnly(aChromeOnly)
277 { }
279 ~ManifestProcessingContext() { }
281 NSLocationType mType;
282 mozilla::FileLocation mFile;
283 bool mChromeOnly;
284 };
286 void ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv);
287 void ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv);
288 void ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv);
289 void ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv);
290 void ManifestContract(ManifestProcessingContext& cx, int lineno, char* const * argv);
291 void ManifestCategory(ManifestProcessingContext& cx, int lineno, char* const * argv);
293 void RereadChromeManifests(bool aChromeOnly = true);
295 // Shutdown
296 enum {
297 NOT_INITIALIZED,
298 NORMAL,
299 SHUTDOWN_IN_PROGRESS,
300 SHUTDOWN_COMPLETE
301 } mStatus;
303 PLArenaPool mArena;
305 struct PendingServiceInfo {
306 const nsCID* cid;
307 PRThread* thread;
308 };
310 inline PendingServiceInfo* AddPendingService(const nsCID& aServiceCID,
311 PRThread* aThread);
312 inline void RemovePendingService(const nsCID& aServiceCID);
313 inline PRThread* GetPendingServiceThread(const nsCID& aServiceCID) const;
315 nsTArray<PendingServiceInfo> mPendingServices;
317 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
319 private:
320 ~nsComponentManagerImpl();
321 };
324 #define NS_MAX_FILENAME_LEN 1024
326 #define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24)
328 struct nsFactoryEntry
329 {
330 nsFactoryEntry(const mozilla::Module::CIDEntry* entry,
331 nsComponentManagerImpl::KnownModule* module);
333 // nsIComponentRegistrar.registerFactory support
334 nsFactoryEntry(const nsCID& aClass, nsIFactory* factory);
336 ~nsFactoryEntry();
338 already_AddRefed<nsIFactory> GetFactory();
340 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
342 const mozilla::Module::CIDEntry* mCIDEntry;
343 nsComponentManagerImpl::KnownModule* mModule;
345 nsCOMPtr<nsIFactory> mFactory;
346 nsCOMPtr<nsISupports> mServiceObject;
347 };
349 #endif // nsComponentManager_h__