author Ehsan Akhgari <ehsan@mozilla.com>
Fri, 24 Apr 2015 15:12:50 -0400
changeset 267826 9ef3b7efaaa734430bcb9e5b612dcc14a56bd60c
parent 259646 a20c7910a82fa2df2f3398c1108d102bac9128b0
child 268720 0f5799df920bfbf966217fa7a8d511a646a53725
permissions -rw-r--r--
Bug 892973 - Add support for the YouCompleteMe vim plugin. r=gps, a=NPOTB

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/MemoryReporting.h"
#include "mozilla/Module.h"
#include "mozilla/ModuleLoader.h"
#include "mozilla/Mutex.h"
#include "nsXULAppAPI.h"
#include "nsNativeModuleLoader.h"
#include "nsIFactory.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "pldhash.h"
#include "prtime.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsWeakReference.h"
#include "plarena.h"
#include "nsCOMArray.h"
#include "nsDataHashtable.h"
#include "nsInterfaceHashtable.h"
#include "nsClassHashtable.h"
#include "nsTArray.h"

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

#include "mozilla/FileLocation.h"

struct nsFactoryEntry;
class nsIServiceManager;
struct PRThread;

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

/* keys for registry use */
extern const char xpcomKeyName[];
extern const char xpcomComponentsKeyName[];
extern const char lastModValueName[];
extern const char fileSizeValueName[];
extern const char nativeComponentType[];
extern const char staticComponentType[];

#ifdef DEBUG

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;
  volatile PRThread* 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<mozilla::ModuleLoader> LoaderForExtension(const nsACString& aExt);
  nsInterfaceHashtable<nsCStringHashKey, mozilla::ModuleLoader> mLoaderMap;

  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<nsIDHashKey, 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<const mozilla::Module*>* sStaticModules;
  static nsTArray<ComponentLocation>* sModuleLocations;

  nsNativeModuleLoader mNativeModuleLoader;

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

    explicit KnownModule(const mozilla::Module* aModule)
      : mModule(aModule)
      , mLoaded(false)
      , mFailed(false)

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

      if (mLoaded && mModule->unloadProc) {

    bool EnsureLoader();
    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;
    nsCOMPtr<mozilla::ModuleLoader> mLoader;
    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,
                      mozilla::FileLocation* aFile);

  // 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 ManifestBinaryComponent(ManifestProcessingContext& aCx, int aLineNo,
                               char* const* aArgv);
  void ManifestXPT(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;

  PLArenaPool   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);

  // Preload XPT interface info for B2G loader.
  // This function is called before XPCOM has been initialized.
  static void PreloadXPT(nsIFile* aFile);

  // Parsing functions of directives of manifest for XPT only parsing.
  struct XPTOnlyManifestProcessingContext
    XPTOnlyManifestProcessingContext(mozilla::FileLocation& aFile)
      : mFile(aFile)

    ~XPTOnlyManifestProcessingContext() {}

    mozilla::FileLocation mFile;
  static void XPTOnlyManifestManifest(XPTOnlyManifestProcessingContext& aCx,
                                      int aLineNo, char* const* aArgv);
  static void XPTOnlyManifestXPT(XPTOnlyManifestProcessingContext& aCx,
                                 int aLineNo, char* const* aArgv);


#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__