Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/components/nsComponentManager.h
Line
Count
Source (jump to first uncovered line)
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
  explicit SafeMutex(const char* aName)
79
    : mMutex(aName)
80
    , mOwnerThread(nullptr)
81
3
  {
82
3
  }
83
84
0
  ~SafeMutex() {}
85
86
  void Lock()
87
4.44M
  {
88
4.44M
    AssertNotCurrentThreadOwns();
89
4.44M
    mMutex.Lock();
90
4.44M
    MOZ_ASSERT(mOwnerThread == nullptr);
91
4.44M
    mOwnerThread = PR_GetCurrentThread();
92
4.44M
  }
93
94
  void Unlock()
95
4.44M
  {
96
4.44M
    MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread());
97
4.44M
    mOwnerThread = nullptr;
98
4.44M
    mMutex.Unlock();
99
4.44M
  }
100
101
  void AssertCurrentThreadOwns() const
102
2.64k
  {
103
2.64k
    // This method is a debug-only check
104
2.64k
    MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread());
105
2.64k
  }
106
107
  MOZ_NEVER_INLINE void AssertNotCurrentThreadOwns() const
108
6.36M
  {
109
6.36M
    // This method is a release-mode check
110
6.36M
    if (PR_GetCurrentThread() == mOwnerThread) {
111
0
      MOZ_CRASH();
112
0
    }
113
6.36M
  }
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<nsIDPointerHashKey, nsFactoryEntry*> mFactories;
171
  nsDataHashtable<nsCStringHashKey, nsFactoryEntry*> mContractIDs;
172
173
  SafeMutex mLock;
174
175
  static void InitializeStaticModules();
176
  static void InitializeModuleLocations();
177
178
  struct ComponentLocation
179
  {
180
    NSLocationType type;
181
    mozilla::FileLocation location;
182
  };
183
184
  class ComponentLocationComparator
185
  {
186
  public:
187
    bool Equals(const ComponentLocation& aA, const ComponentLocation& aB) const
188
0
    {
189
0
      return (aA.type == aB.type && aA.location.Equals(aB.location));
190
0
    }
191
  };
192
193
  static nsTArray<ComponentLocation>* sModuleLocations;
194
195
  class KnownModule
196
  {
197
  public:
198
    /**
199
     * Static or binary module.
200
     */
201
    KnownModule(const mozilla::Module* aModule, mozilla::FileLocation& aFile)
202
      : mModule(aModule)
203
      , mFile(aFile)
204
      , mLoaded(false)
205
      , mFailed(false)
206
0
    {
207
0
    }
208
209
    explicit KnownModule(const mozilla::Module* aModule)
210
      : mModule(aModule)
211
      , mLoaded(false)
212
      , mFailed(false)
213
180
    {
214
180
    }
215
216
    explicit KnownModule(mozilla::FileLocation& aFile)
217
      : mModule(nullptr)
218
      , mFile(aFile)
219
      , mLoader(nullptr)
220
      , mLoaded(false)
221
      , mFailed(false)
222
240
    {
223
240
    }
224
225
    ~KnownModule()
226
0
    {
227
0
      if (mLoaded && mModule->unloadProc) {
228
0
        mModule->unloadProc();
229
0
      }
230
0
    }
231
232
    bool EnsureLoader();
233
    bool Load();
234
235
120
    const mozilla::Module* Module() const { return mModule; }
236
237
    /**
238
     * For error logging, get a description of this module, either the
239
     * file path, or <static module>.
240
     */
241
    nsCString Description() const;
242
243
  private:
244
    const mozilla::Module* mModule;
245
    mozilla::FileLocation mFile;
246
    nsCOMPtr<mozilla::ModuleLoader> mLoader;
247
    bool mLoaded;
248
    bool mFailed;
249
  };
250
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;
256
257
  // Mutex not held
258
  void RegisterModule(const mozilla::Module* aModule,
259
                      mozilla::FileLocation* aFile);
260
261
262
  // Mutex held
263
  void RegisterCIDEntryLocked(const mozilla::Module::CIDEntry* aEntry,
264
                              KnownModule* aModule);
265
  void RegisterContractIDLocked(const mozilla::Module::ContractIDEntry* aEntry);
266
267
  // Mutex not held
268
  void RegisterManifest(NSLocationType aType, mozilla::FileLocation& aFile,
269
                        bool aChromeOnly);
270
271
  struct ManifestProcessingContext
272
  {
273
    ManifestProcessingContext(NSLocationType aType,
274
                              mozilla::FileLocation& aFile, bool aChromeOnly)
275
      : mType(aType)
276
      , mFile(aFile)
277
      , mChromeOnly(aChromeOnly)
278
12
    {
279
12
    }
280
281
12
    ~ManifestProcessingContext() {}
282
283
    NSLocationType mType;
284
    mozilla::FileLocation mFile;
285
    bool mChromeOnly;
286
  };
287
288
  void ManifestManifest(ManifestProcessingContext& aCx, int aLineNo,
289
                        char* const* aArgv);
290
  void ManifestComponent(ManifestProcessingContext& aCx, int aLineNo,
291
                         char* const* aArgv);
292
  void ManifestContract(ManifestProcessingContext& aCx, int aLineNo,
293
                        char* const* aArgv);
294
  void ManifestCategory(ManifestProcessingContext& aCx, int aLineNo,
295
                        char* const* aArgv);
296
297
  void RereadChromeManifests(bool aChromeOnly = true);
298
299
  // Shutdown
300
  enum
301
  {
302
    NOT_INITIALIZED,
303
    NORMAL,
304
    SHUTDOWN_IN_PROGRESS,
305
    SHUTDOWN_COMPLETE
306
  } mStatus;
307
308
  mozilla::ArenaAllocator<1024*8, 8> mArena;
309
310
  struct PendingServiceInfo
311
  {
312
    const nsCID* cid;
313
    PRThread* thread;
314
  };
315
316
  inline PendingServiceInfo* AddPendingService(const nsCID& aServiceCID,
317
                                               PRThread* aThread);
318
  inline void RemovePendingService(const nsCID& aServiceCID);
319
  inline PRThread* GetPendingServiceThread(const nsCID& aServiceCID) const;
320
321
  nsTArray<PendingServiceInfo> mPendingServices;
322
323
  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
324
325
private:
326
  ~nsComponentManagerImpl();
327
};
328
329
330
#define NS_MAX_FILENAME_LEN     1024
331
332
#define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24)
333
334
struct nsFactoryEntry
335
{
336
  nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry,
337
                 nsComponentManagerImpl::KnownModule* aModule);
338
339
  // nsIComponentRegistrar.registerFactory support
340
  nsFactoryEntry(const nsCID& aClass, nsIFactory* aFactory);
341
342
  ~nsFactoryEntry();
343
344
  already_AddRefed<nsIFactory> GetFactory();
345
346
  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
347
348
  const mozilla::Module::CIDEntry* mCIDEntry;
349
  nsComponentManagerImpl::KnownModule* mModule;
350
351
  nsCOMPtr<nsIFactory>   mFactory;
352
  nsCOMPtr<nsISupports>  mServiceObject;
353
};
354
355
#endif // nsComponentManager_h__