author Jean-Yves Avenard <jyavenard@mozilla.com>
Mon, 12 Nov 2018 01:09:03 +0000
changeset 505066 6f08cc82afe3280863c897dda1e141d8c4c165d7
parent 501700 ded047a09c690d95cbe1a2c8babdfa8d917cf29b
child 508163 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1505910 - P2. Remove use of AsTaskQueue(). r=cpearce Make IsCurrentThreadIn() const. Depends on D11491 Differential Revision: https://phabricator.services.mozilla.com/D11492

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsComponentManager_h__
#define nsComponentManager_h__

#include "nsXPCOM.h"

#include "xpcom-private.h"
#include "nsIComponentManager.h"
#include "nsIComponentRegistrar.h"
#include "nsIMemoryReporter.h"
#include "nsIServiceManager.h"
#include "nsIFile.h"
#include "mozilla/ArenaAllocator.h"
#include "mozilla/Atomics.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Module.h"
#include "mozilla/Mutex.h"
#include "nsXULAppAPI.h"
#include "nsIFactory.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "PLDHashTable.h"
#include "prtime.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsWeakReference.h"
#include "nsCOMArray.h"
#include "nsDataHashtable.h"
#include "nsInterfaceHashtable.h"
#include "nsClassHashtable.h"
#include "nsTArray.h"

#include "mozilla/Omnijar.h"
#include "mozilla/Attributes.h"

struct nsFactoryEntry;
struct PRThread;

#define NS_COMPONENTMANAGER_CID                      \
{ /* 91775d60-d5dc-11d2-92fb-00e09805570f */         \
    0x91775d60,                                      \
    0xd5dc,                                          \
    0x11d2,                                          \
    {0x92, 0xfb, 0x00, 0xe0, 0x98, 0x05, 0x57, 0x0f} \


extern const mozilla::Module kXPCOMModule;

 * This is a wrapper around mozilla::Mutex which provides runtime
 * checking for a deadlock where the same thread tries to lock a mutex while
 * it is already locked. This checking is present in both debug and release
 * builds.
class SafeMutex
  explicit SafeMutex(const char* aName)
    : mMutex(aName)
    , mOwnerThread(nullptr)

  ~SafeMutex() {}

  void Lock()
    MOZ_ASSERT(mOwnerThread == nullptr);
    mOwnerThread = PR_GetCurrentThread();

  void Unlock()
    MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread());
    mOwnerThread = nullptr;

  void AssertCurrentThreadOwns() const
    // This method is a debug-only check
    MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread());

  MOZ_NEVER_INLINE void AssertNotCurrentThreadOwns() const
    // This method is a release-mode check
    if (PR_GetCurrentThread() == mOwnerThread) {

  mozilla::Mutex mMutex;
  mozilla::Atomic<PRThread*, mozilla::Relaxed> mOwnerThread;

typedef mozilla::BaseAutoLock<SafeMutex&> SafeMutexAutoLock;
typedef mozilla::BaseAutoUnlock<SafeMutex&> SafeMutexAutoUnlock;

class nsComponentManagerImpl final
  : public nsIComponentManager
  , public nsIServiceManager
  , public nsSupportsWeakReference
  , public nsIComponentRegistrar
  , public nsIInterfaceRequestor
  , public nsIMemoryReporter

  static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);

  nsresult RegistryLocationForFile(nsIFile* aFile,
                                   nsCString& aResult);
  nsresult FileForRegistryLocation(const nsCString& aLocation,
                                   nsIFile** aSpec);


  // nsComponentManagerImpl methods:

  static nsComponentManagerImpl* gComponentManager;
  nsresult Init();

  nsresult Shutdown(void);

  nsresult FreeServices();

  already_AddRefed<nsIFactory> FindFactory(const nsCID& aClass);
  already_AddRefed<nsIFactory> FindFactory(const char* aContractID,
                                           uint32_t aContractIDLen);

  already_AddRefed<nsIFactory> LoadFactory(nsFactoryEntry* aEntry);

  nsFactoryEntry* GetFactoryEntry(const char* aContractID,
                                  uint32_t aContractIDLen);
  nsFactoryEntry* GetFactoryEntry(const nsCID& aClass);

  nsDataHashtable<nsIDPointerHashKey, nsFactoryEntry*> mFactories;
  nsDataHashtable<nsCStringHashKey, nsFactoryEntry*> mContractIDs;

  SafeMutex mLock;

  static void InitializeStaticModules();
  static void InitializeModuleLocations();

  struct ComponentLocation
    NSLocationType type;
    mozilla::FileLocation location;

  class ComponentLocationComparator
    bool Equals(const ComponentLocation& aA, const ComponentLocation& aB) const
      return (aA.type == aB.type && aA.location.Equals(aB.location));

  static nsTArray<ComponentLocation>* sModuleLocations;

  class KnownModule
     * Static or binary module.
    explicit KnownModule(const mozilla::Module* aModule)
      : mModule(aModule)
      , mLoaded(false)
      , mFailed(false)

    explicit KnownModule(mozilla::FileLocation& aFile)
      : mModule(nullptr)
      , mFile(aFile)
      , mLoaded(false)
      , mFailed(false)

      if (mLoaded && mModule->unloadProc) {

    bool Load();

    const mozilla::Module* Module() const { return mModule; }

     * For error logging, get a description of this module, either the
     * file path, or <static module>.
    nsCString Description() const;

    const mozilla::Module* mModule;
    mozilla::FileLocation mFile;
    bool mLoaded;
    bool mFailed;

  // The KnownModule is kept alive by these members, it is
  // referenced by pointer from the factory entries.
  nsTArray<nsAutoPtr<KnownModule>> mKnownStaticModules;
  // The key is the URI string of the module
  nsClassHashtable<nsCStringHashKey, KnownModule> mKnownModules;

  // Mutex not held
  void RegisterModule(const mozilla::Module* aModule);

  // Mutex held
  void RegisterCIDEntryLocked(const mozilla::Module::CIDEntry* aEntry,
                              KnownModule* aModule);
  void RegisterContractIDLocked(const mozilla::Module::ContractIDEntry* aEntry);

  // Mutex not held
  void RegisterManifest(NSLocationType aType, mozilla::FileLocation& aFile,
                        bool aChromeOnly);

  struct ManifestProcessingContext
    ManifestProcessingContext(NSLocationType aType,
                              mozilla::FileLocation& aFile, bool aChromeOnly)
      : mType(aType)
      , mFile(aFile)
      , mChromeOnly(aChromeOnly)

    ~ManifestProcessingContext() {}

    NSLocationType mType;
    mozilla::FileLocation mFile;
    bool mChromeOnly;

  void ManifestManifest(ManifestProcessingContext& aCx, int aLineNo,
                        char* const* aArgv);
  void ManifestComponent(ManifestProcessingContext& aCx, int aLineNo,
                         char* const* aArgv);
  void ManifestContract(ManifestProcessingContext& aCx, int aLineNo,
                        char* const* aArgv);
  void ManifestCategory(ManifestProcessingContext& aCx, int aLineNo,
                        char* const* aArgv);

  void RereadChromeManifests(bool aChromeOnly = true);

  // Shutdown
  } mStatus;

  mozilla::ArenaAllocator<1024*8, 8> mArena;

  struct PendingServiceInfo
    const nsCID* cid;
    PRThread* thread;

  inline PendingServiceInfo* AddPendingService(const nsCID& aServiceCID,
                                               PRThread* aThread);
  inline void RemovePendingService(const nsCID& aServiceCID);
  inline PRThread* GetPendingServiceThread(const nsCID& aServiceCID) const;

  nsTArray<PendingServiceInfo> mPendingServices;

  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;


#define NS_MAX_FILENAME_LEN     1024


struct nsFactoryEntry
  nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry,
                 nsComponentManagerImpl::KnownModule* aModule);

  // nsIComponentRegistrar.registerFactory support
  nsFactoryEntry(const nsCID& aClass, nsIFactory* aFactory);


  already_AddRefed<nsIFactory> GetFactory();

  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);

  const mozilla::Module::CIDEntry* mCIDEntry;
  nsComponentManagerImpl::KnownModule* mModule;

  nsCOMPtr<nsIFactory>   mFactory;
  nsCOMPtr<nsISupports>  mServiceObject;

#endif // nsComponentManager_h__