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