summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/xpcom/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/components')
-rw-r--r--src/libs/xpcom18a4/xpcom/components/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/components/Makefile.in107
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp799
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h159
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h88
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp3794
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManager.h339
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp271
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h185
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h196
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl101
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl132
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl109
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl111
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl351
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h43
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl243
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIFactory.idl79
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIModule.idl115
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl70
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl119
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h250
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h185
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsModule.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp1150
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h84
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h27
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp155
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h52
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp317
-rw-r--r--src/libs/xpcom18a4/xpcom/components/xcDll.cpp457
-rw-r--r--src/libs/xpcom18a4/xpcom/components/xcDll.h121
33 files changed, 10340 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/components/.cvsignore b/src/libs/xpcom18a4/xpcom/components/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/components/Makefile.in b/src/libs/xpcom18a4/xpcom/components/Makefile.in
new file mode 100644
index 00000000..68614854
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/Makefile.in
@@ -0,0 +1,107 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = xpcom_components
+LIBRARY_NAME = xpcomcomponents_s
+GRE_MODULE = 1
+
+REQUIRES = string \
+ $(NULL)
+
+CPPSRCS = \
+ nsCategoryManager.cpp \
+ nsComponentManager.cpp \
+ nsComponentManagerObsolete.cpp \
+ nsNativeComponentLoader.cpp \
+ nsServiceManagerObsolete.cpp \
+ xcDll.cpp \
+ $(NULL)
+
+ifdef MOZ_STATIC_COMPONENT_LOADER
+CPPSRCS += nsStaticComponentLoader.cpp
+endif
+
+EXPORTS = \
+ nsCategoryManagerUtils.h \
+ nsComponentManagerUtils.h \
+ nsComponentManagerObsolete.h \
+ nsIServiceManagerUtils.h \
+ nsIServiceManagerObsolete.h \
+ nsModule.h \
+ nsNativeComponentLoader.h \
+ nsStaticComponent.h \
+ nsObsoleteModuleLoading.h \
+ xcDll.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIComponentLoader.idl \
+ nsIComponentLoaderManager.idl \
+ nsIComponentManagerObsolete.idl \
+ nsINativeComponentLoader.idl \
+ $(NULL)
+
+SDK_XPIDLSRCS = \
+ nsIClassInfo.idl \
+ nsIComponentRegistrar.idl \
+ nsIFactory.idl \
+ nsIModule.idl \
+ nsIServiceManager.idl \
+ nsIComponentManager.idl \
+ nsICategoryManager.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+LOCAL_INCLUDES = -I$(srcdir)/../base -I$(srcdir)/../thread -I$(srcdir)/../ds -I..
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTI_API
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp
new file mode 100644
index 00000000..d7202bdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp
@@ -0,0 +1,799 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define PL_ARENA_CONST_ALIGN_MASK 7
+
+#include "nsICategoryManager.h"
+#include "nsCategoryManager.h"
+
+#include "plarena.h"
+#include "prio.h"
+#include "prprf.h"
+#include "prlock.h"
+#include "nsCOMPtr.h"
+#include "nsTHashtable.h"
+#include "nsClassHashtable.h"
+#include "nsIFactory.h"
+#include "nsIStringEnumerator.h"
+#include "nsSupportsPrimitives.h"
+#include "nsIServiceManagerUtils.h"
+#include "nsIObserver.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsEnumeratorUtils.h"
+
+class nsIComponentLoaderManager;
+
+/*
+ CategoryDatabase
+ contains 0 or more 1-1 mappings of string to Category
+ each Category contains 0 or more 1-1 mappings of string keys to string values
+
+ In other words, the CategoryDatabase is a tree, whose root is a hashtable.
+ Internal nodes (or Categories) are hashtables. Leaf nodes are strings.
+
+ The leaf strings are allocated in an arena, because we assume they're not
+ going to change much ;)
+*/
+
+#define NS_CATEGORYMANAGER_ARENA_SIZE (1024 * 8)
+
+// pulled in from nsComponentManager.cpp
+char* ArenaStrdup(const char* s, PLArenaPool* aArena);
+
+//
+// BaseStringEnumerator is subclassed by EntryEnumerator and
+// CategoryEnumerator
+//
+class BaseStringEnumerator
+ : public nsISimpleEnumerator,
+ nsIUTF8StringEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+ NS_DECL_NSIUTF8STRINGENUMERATOR
+
+protected:
+ BaseStringEnumerator()
+ : mArray(nsnull),
+ mCount(0),
+ mSimpleCurItem(0),
+ mStringCurItem(0) { }
+
+ // A virtual destructor is needed here because subclasses of
+ // BaseStringEnumerator do not implement their own Release() method.
+
+ virtual ~BaseStringEnumerator()
+ {
+ if (mArray)
+ delete[] mArray;
+ }
+
+ const char** mArray;
+ PRUint32 mCount;
+ PRUint32 mSimpleCurItem;
+ PRUint32 mStringCurItem;
+};
+
+NS_IMPL_ISUPPORTS2(BaseStringEnumerator, nsISimpleEnumerator, nsIUTF8StringEnumerator)
+
+NS_IMETHODIMP
+BaseStringEnumerator::HasMoreElements(PRBool *_retval)
+{
+ *_retval = (mSimpleCurItem < mCount);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::GetNext(nsISupports **_retval)
+{
+ if (mSimpleCurItem >= mCount)
+ return NS_ERROR_FAILURE;
+
+ nsSupportsDependentCString* str =
+ new nsSupportsDependentCString(mArray[mSimpleCurItem++]);
+ if (!str)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = str;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::HasMore(PRBool *_retval)
+{
+ *_retval = (mStringCurItem < mCount);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::GetNext(nsACString& _retval)
+{
+ if (mStringCurItem >= mCount)
+ return NS_ERROR_FAILURE;
+
+ _retval = nsDependentCString(mArray[mStringCurItem++]);
+ return NS_OK;
+}
+
+
+//
+// EntryEnumerator is the wrapper that allows nsICategoryManager::EnumerateCategory
+//
+class EntryEnumerator
+ : public BaseStringEnumerator
+{
+public:
+ static EntryEnumerator* Create(nsTHashtable<CategoryLeaf>& aTable);
+
+private:
+ static PLDHashOperator PR_CALLBACK
+ enumfunc_createenumerator(CategoryLeaf* aLeaf, void* userArg);
+};
+
+
+PLDHashOperator PR_CALLBACK
+EntryEnumerator::enumfunc_createenumerator(CategoryLeaf* aLeaf, void* userArg)
+{
+ EntryEnumerator* mythis = NS_STATIC_CAST(EntryEnumerator*, userArg);
+ mythis->mArray[mythis->mCount++] = aLeaf->GetKey();
+
+ return PL_DHASH_NEXT;
+}
+
+EntryEnumerator*
+EntryEnumerator::Create(nsTHashtable<CategoryLeaf>& aTable)
+{
+ EntryEnumerator* enumObj = new EntryEnumerator();
+ if (!enumObj)
+ return nsnull;
+
+ enumObj->mArray = new char const* [aTable.Count()];
+ if (!enumObj->mArray) {
+ delete enumObj;
+ return nsnull;
+ }
+
+ aTable.EnumerateEntries(enumfunc_createenumerator, enumObj);
+
+ return enumObj;
+}
+
+
+//
+// CategoryNode implementations
+//
+
+CategoryNode*
+CategoryNode::Create(PLArenaPool* aArena)
+{
+ CategoryNode* node = new(aArena) CategoryNode();
+ if (!node)
+ return nsnull;
+
+ if (!node->mTable.Init()) {
+ delete node;
+ return nsnull;
+ }
+
+ node->mLock = PR_NewLock();
+ if (!node->mLock) {
+ delete node;
+ return nsnull;
+ }
+
+ return node;
+}
+
+CategoryNode::~CategoryNode()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+void*
+CategoryNode::operator new(size_t aSize, PLArenaPool* aArena)
+{
+ void* p;
+ PL_ARENA_ALLOCATE(p, aArena, aSize);
+ return p;
+}
+
+NS_METHOD
+CategoryNode::GetLeaf(const char* aEntryName,
+ char** _retval)
+{
+ PR_Lock(mLock);
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ CategoryLeaf* ent =
+ mTable.GetEntry(aEntryName);
+
+ // we only want the non-persistent value
+ if (ent && ent->nonpValue) {
+ *_retval = nsCRT::strdup(ent->nonpValue);
+ if (*_retval)
+ rv = NS_OK;
+ }
+ PR_Unlock(mLock);
+
+ return rv;
+}
+
+NS_METHOD
+CategoryNode::AddLeaf(const char* aEntryName,
+ const char* aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char** _retval,
+ PLArenaPool* aArena)
+{
+ PR_Lock(mLock);
+ CategoryLeaf* leaf =
+ mTable.GetEntry(aEntryName);
+
+ nsresult rv = NS_OK;
+ if (leaf) {
+ //if the entry was found, aReplace must be specified
+ if (!aReplace && (leaf->nonpValue || (aPersist && leaf->pValue )))
+ rv = NS_ERROR_INVALID_ARG;
+ } else {
+ const char* arenaEntryName = ArenaStrdup(aEntryName, aArena);
+ if (!arenaEntryName) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ leaf = mTable.PutEntry(arenaEntryName);
+ if (!leaf)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ const char* arenaValue = ArenaStrdup(aValue, aArena);
+ if (!arenaValue) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ leaf->nonpValue = arenaValue;
+ if (aPersist)
+ leaf->pValue = arenaValue;
+ }
+ }
+
+ PR_Unlock(mLock);
+ return rv;
+}
+
+NS_METHOD
+CategoryNode::DeleteLeaf(const char* aEntryName,
+ PRBool aDontPersist)
+{
+ // we don't throw any errors, because it normally doesn't matter
+ // and it makes JS a lot cleaner
+ PR_Lock(mLock);
+
+ if (aDontPersist) {
+ // we can just remove the entire hash entry without introspection
+ mTable.RemoveEntry(aEntryName);
+ } else {
+ // if we are keeping the persistent value, we need to look at
+ // the contents of the current entry
+ CategoryLeaf* leaf = mTable.GetEntry(aEntryName);
+ if (leaf) {
+ if (leaf->pValue) {
+ leaf->nonpValue = nsnull;
+ } else {
+ // if there is no persistent value, just remove the entry
+ mTable.RawRemoveEntry(leaf);
+ }
+ }
+ }
+ PR_Unlock(mLock);
+
+ return NS_OK;
+}
+
+NS_METHOD
+CategoryNode::Enumerate(nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ EntryEnumerator* enumObj = EntryEnumerator::Create(mTable);
+ PR_Unlock(mLock);
+
+ if (!enumObj)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = enumObj;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+struct persistent_userstruct {
+ PRFileDesc* fd;
+ const char* categoryName;
+ PRBool success;
+};
+
+PLDHashOperator PR_CALLBACK
+enumfunc_pentries(CategoryLeaf* aLeaf, void* userArg)
+{
+ persistent_userstruct* args =
+ NS_STATIC_CAST(persistent_userstruct*, userArg);
+
+ PLDHashOperator status = PL_DHASH_NEXT;
+
+ if (aLeaf->pValue) {
+ if (PR_fprintf(args->fd,
+ "%s,%s,%s\n",
+ args->categoryName,
+ aLeaf->GetKey(),
+ aLeaf->pValue) == (PRUint32) -1) {
+ args->success = PR_FALSE;
+ status = PL_DHASH_STOP;
+ }
+ }
+
+ return status;
+}
+
+PRBool
+CategoryNode::WritePersistentEntries(PRFileDesc* fd, const char* aCategoryName)
+{
+ persistent_userstruct args = {
+ fd,
+ aCategoryName,
+ PR_TRUE
+ };
+
+ PR_Lock(mLock);
+ mTable.EnumerateEntries(enumfunc_pentries, &args);
+ PR_Unlock(mLock);
+
+ return args.success;
+}
+
+
+//
+// CategoryEnumerator class
+//
+
+class CategoryEnumerator
+ : public BaseStringEnumerator
+{
+public:
+ static CategoryEnumerator* Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>& aTable);
+
+private:
+ static PLDHashOperator PR_CALLBACK
+ enumfunc_createenumerator(const char* aStr,
+ CategoryNode* aNode,
+ void* userArg);
+};
+
+CategoryEnumerator*
+CategoryEnumerator::Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>& aTable)
+{
+ CategoryEnumerator* enumObj = new CategoryEnumerator();
+ if (!enumObj)
+ return nsnull;
+
+ enumObj->mArray = new const char* [aTable.Count()];
+ if (!enumObj->mArray) {
+ delete enumObj;
+ return nsnull;
+ }
+
+ aTable.EnumerateRead(enumfunc_createenumerator, enumObj);
+
+ return enumObj;
+}
+
+PLDHashOperator PR_CALLBACK
+CategoryEnumerator::enumfunc_createenumerator(const char* aStr, CategoryNode* aNode, void* userArg)
+{
+ CategoryEnumerator* mythis = NS_STATIC_CAST(CategoryEnumerator*, userArg);
+
+ // if a category has no entries, we pretend it doesn't exist
+ if (aNode->Count())
+ mythis->mArray[mythis->mCount++] = aStr;
+
+ return PL_DHASH_NEXT;
+}
+
+
+//
+// nsCategoryManager implementations
+//
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsCategoryManager, nsICategoryManager)
+
+nsCategoryManager*
+nsCategoryManager::Create()
+{
+ nsCategoryManager* manager = new nsCategoryManager();
+
+ if (!manager)
+ return nsnull;
+
+ PL_INIT_ARENA_POOL(&(manager->mArena), "CategoryManagerArena",
+ NS_CATEGORYMANAGER_ARENA_SIZE); // this never fails
+
+ if (!manager->mTable.Init()) {
+ delete manager;
+ return nsnull;
+ }
+
+ manager->mLock = PR_NewLock();
+
+ if (!manager->mLock) {
+ delete manager;
+ return nsnull;
+ }
+
+ return manager;
+}
+
+nsCategoryManager::~nsCategoryManager()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ // the hashtable contains entries that must be deleted before the arena is
+ // destroyed, or else you will have PRLocks undestroyed and other Really
+ // Bad Stuff (TM)
+ mTable.Clear();
+
+ PL_FinishArenaPool(&mArena);
+}
+
+inline CategoryNode*
+nsCategoryManager::get_category(const char* aName) {
+ CategoryNode* node;
+ if (!mTable.Get(aName, &node)) {
+ return nsnull;
+ }
+ return node;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::GetCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ char **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult status = NS_ERROR_NOT_AVAILABLE;
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (category) {
+ status = category->GetLeaf(aEntryName, _retval);
+ }
+
+ return status;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::AddCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ const char *aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+ NS_ENSURE_ARG_POINTER(aValue);
+
+ // Before we can insert a new entry, we'll need to
+ // find the |CategoryNode| to put it in...
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+
+ if (!category) {
+ // That category doesn't exist yet; let's make it.
+ category = CategoryNode::Create(&mArena);
+
+ char* categoryName = ArenaStrdup(aCategoryName, &mArena);
+ mTable.Put(categoryName, category);
+ }
+ PR_Unlock(mLock);
+
+ if (!category)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return category->AddLeaf(aEntryName,
+ aValue,
+ aPersist,
+ aReplace,
+ _retval,
+ &mArena);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ PRBool aDontPersist)
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+
+ /*
+ Note: no errors are reported since failure to delete
+ probably won't hurt you, and returning errors seriously
+ inconveniences JS clients
+ */
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (!category)
+ return NS_OK;
+
+ return category->DeleteLeaf(aEntryName,
+ aDontPersist);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategory( const char *aCategoryName )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+
+ // the categories are arena-allocated, so we don't
+ // actually delete them. We just remove all of the
+ // leaf nodes.
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (category)
+ category->Clear();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::EnumerateCategory( const char *aCategoryName,
+ nsISimpleEnumerator **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (!category) {
+ return NS_NewEmptyEnumerator(_retval);
+ }
+
+ return category->Enumerate(_retval);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::EnumerateCategories(nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ CategoryEnumerator* enumObj = CategoryEnumerator::Create(mTable);
+ PR_Unlock(mLock);
+
+ if (!enumObj)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = enumObj;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+struct writecat_struct {
+ PRFileDesc* fd;
+ PRBool success;
+};
+
+PLDHashOperator PR_CALLBACK
+enumfunc_categories(const char* aKey, CategoryNode* aCategory, void* userArg)
+{
+ writecat_struct* args = NS_STATIC_CAST(writecat_struct*, userArg);
+
+ PLDHashOperator result = PL_DHASH_NEXT;
+
+ if (!aCategory->WritePersistentEntries(args->fd, aKey)) {
+ args->success = PR_FALSE;
+ result = PL_DHASH_STOP;
+ }
+
+ return result;
+}
+
+NS_METHOD
+nsCategoryManager::WriteCategoryManagerToRegistry(PRFileDesc* fd)
+{
+ writecat_struct args = {
+ fd,
+ PR_TRUE
+ };
+
+ PR_Lock(mLock);
+ mTable.EnumerateRead(enumfunc_categories, &args);
+ PR_Unlock(mLock);
+
+ if (!args.success) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+class nsCategoryManagerFactory : public nsIFactory
+ {
+ public:
+ nsCategoryManagerFactory() { }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFACTORY
+ };
+
+NS_IMPL_ISUPPORTS1(nsCategoryManagerFactory, nsIFactory)
+
+NS_IMETHODIMP
+nsCategoryManagerFactory::CreateInstance( nsISupports* aOuter, const nsIID& aIID, void** aResult )
+ {
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = 0;
+
+ nsresult status = NS_OK;
+ if ( aOuter )
+ status = NS_ERROR_NO_AGGREGATION;
+ else
+ {
+ nsCategoryManager* raw_category_manager = nsCategoryManager::Create();
+ nsCOMPtr<nsICategoryManager> new_category_manager = raw_category_manager;
+ if ( new_category_manager )
+ status = new_category_manager->QueryInterface(aIID, aResult);
+ else
+ status = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return status;
+ }
+
+NS_IMETHODIMP
+nsCategoryManagerFactory::LockFactory( PRBool )
+ {
+ // Not implemented...
+ return NS_OK;
+ }
+
+nsresult
+NS_CategoryManagerGetFactory( nsIFactory** aFactory )
+ {
+ // assert(aFactory);
+
+ nsresult status;
+
+ *aFactory = 0;
+ nsIFactory* new_factory = NS_STATIC_CAST(nsIFactory*, new nsCategoryManagerFactory);
+ if (new_factory)
+ {
+ *aFactory = new_factory;
+ NS_ADDREF(*aFactory);
+ status = NS_OK;
+ }
+ else
+ status = NS_ERROR_OUT_OF_MEMORY;
+
+ return status;
+ }
+
+
+
+/*
+ * CreateServicesFromCategory()
+ *
+ * Given a category, this convenience functions enumerates the category and
+ * creates a service of every CID or ContractID registered under the category.
+ * If observerTopic is non null and the service implements nsIObserver,
+ * this will attempt to notify the observer with the origin, observerTopic string
+ * as parameter.
+ */
+NS_COM nsresult
+NS_CreateServicesFromCategory(const char *category,
+ nsISupports *origin,
+ const char *observerTopic)
+{
+ nsresult rv = NS_OK;
+
+ int nFailed = 0;
+ nsCOMPtr<nsICategoryManager> categoryManager =
+ do_GetService("@mozilla.org/categorymanager;1", &rv);
+ if (!categoryManager) return rv;
+
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ rv = categoryManager->EnumerateCategory(category,
+ getter_AddRefs(enumerator));
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
+ // From here on just skip any error we get.
+ nsCOMPtr<nsISupportsCString> catEntry = do_QueryInterface(entry, &rv);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+ nsCAutoString entryString;
+ rv = catEntry->GetData(entryString);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+ nsXPIDLCString contractID;
+ rv = categoryManager->GetCategoryEntry(category,entryString.get(), getter_Copies(contractID));
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+
+ nsCOMPtr<nsISupports> instance = do_GetService(contractID, &rv);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+
+ if (observerTopic) {
+ // try an observer, if it implements it.
+ nsCOMPtr<nsIObserver> observer = do_QueryInterface(instance, &rv);
+ if (NS_SUCCEEDED(rv) && observer)
+ observer->Observe(origin, observerTopic, EmptyString().get());
+ }
+ }
+ return (nFailed ? NS_ERROR_FAILURE : NS_OK);
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h
new file mode 100644
index 00000000..a5cdb59a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#ifndef NSCATEGORYMANAGER_H
+#define NSCATEGORYMANAGER_H
+
+#include "prio.h"
+#include "prlock.h"
+#include "plarena.h"
+#include "nsClassHashtable.h"
+#include "nsICategoryManager.h"
+
+#define NS_CATEGORYMANAGER_CLASSNAME "Category Manager"
+
+/* 16d222a6-1dd2-11b2-b693-f38b02c021b2 */
+#define NS_CATEGORYMANAGER_CID \
+{ 0x16d222a6, 0x1dd2, 0x11b2, \
+ {0xb6, 0x93, 0xf3, 0x8b, 0x02, 0xc0, 0x21, 0xb2} }
+
+/**
+ * a "leaf-node", managed by the nsCategoryNode hashtable.
+ *
+ * we need to keep a "persistent value" (which will be written to the registry)
+ * and a non-persistent value (for the current runtime): these are usually
+ * the same, except when aPersist==PR_FALSE. The strings are permanently arena-
+ * allocated, and will never go away.
+ */
+class CategoryLeaf : public nsDepCharHashKey
+{
+public:
+ CategoryLeaf(const char* aKey)
+ : nsDepCharHashKey(aKey),
+ pValue(nsnull),
+ nonpValue(nsnull) { }
+ const char* pValue;
+ const char* nonpValue;
+};
+
+
+/**
+ * CategoryNode keeps a hashtable of it's entries.
+ * the CategoryNode itself is permanently allocated in
+ * the arena.
+ */
+class CategoryNode
+{
+public:
+ NS_METHOD GetLeaf(const char* aEntryName,
+ char** _retval);
+
+ NS_METHOD AddLeaf(const char* aEntryName,
+ const char* aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char** _retval,
+ PLArenaPool* aArena);
+
+ NS_METHOD DeleteLeaf(const char* aEntryName,
+ PRBool aDontPersist);
+
+ void Clear() {
+ PR_Lock(mLock);
+ mTable.Clear();
+ PR_Unlock(mLock);
+ }
+
+ PRUint32 Count() {
+ PR_Lock(mLock);
+ PRUint32 tCount = mTable.Count();
+ PR_Unlock(mLock);
+ return tCount;
+ }
+
+ NS_METHOD Enumerate(nsISimpleEnumerator** _retval);
+
+ PRBool WritePersistentEntries(PRFileDesc* fd, const char* aCategoryName);
+
+ // CategoryNode is arena-allocated, with the strings
+ static CategoryNode* Create(PLArenaPool* aArena);
+ ~CategoryNode();
+ void operator delete(void*) { }
+
+private:
+ CategoryNode() : mLock(nsnull) { }
+ void* operator new(size_t aSize, PLArenaPool* aArena);
+
+ nsTHashtable<CategoryLeaf> mTable;
+ PRLock* mLock;
+};
+
+
+/**
+ * The main implementation of nsICategoryManager.
+ *
+ * This implementation is thread-safe.
+ */
+class nsCategoryManager
+ : public nsICategoryManager
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICATEGORYMANAGER
+
+ /**
+ * Write the categories to the XPCOM persistent registry.
+ * This is to be used by nsComponentManagerImpl (and NO ONE ELSE).
+ */
+ NS_METHOD WriteCategoryManagerToRegistry(PRFileDesc* fd);
+
+ nsCategoryManager() : mLock(nsnull) { }
+private:
+ friend class nsCategoryManagerFactory;
+ static nsCategoryManager* Create();
+
+ ~nsCategoryManager();
+
+ CategoryNode* get_category(const char* aName);
+
+ PLArenaPool mArena;
+ nsClassHashtable<nsDepCharHashKey, CategoryNode> mTable;
+ PRLock* mLock;
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h
new file mode 100644
index 00000000..54a9fcec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCategoryManagerUtils_h__
+#define nsCategoryManagerUtils_h__
+
+#include "nsICategoryManager.h"
+#include "nsCOMPtr.h"
+
+NS_COM nsresult
+NS_CreateServicesFromCategory(const char *category,
+ nsISupports *origin,
+ const char *observerTopic);
+
+class NS_COM nsCreateInstanceFromCategory : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceFromCategory(const char *aCategory, const char *aEntry,
+ nsISupports *aOuter, nsresult *aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do;
+ }
+ virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** aInstancePtr) const;
+
+private:
+ const char *mCategory; // Do not free. This char * is not owned.
+ const char *mEntry; // Do not free. This char * is not owned.
+
+ nsISupports *mOuter;
+ nsresult *mErrorPtr;
+
+};
+
+inline
+const nsCreateInstanceFromCategory
+do_CreateInstanceFromCategory( const char *aCategory, const char *aEntry,
+ nsresult *aErrorPtr = 0)
+{
+ return nsCreateInstanceFromCategory(aCategory, aEntry, 0, aErrorPtr);
+}
+
+inline
+const nsCreateInstanceFromCategory
+do_CreateInstanceFromCategory( const char *aCategory, const char *aEntry,
+ nsISupports *aOuter, nsresult *aErrorPtr = 0)
+{
+ return nsCreateInstanceFromCategory(aCategory, aEntry, aOuter, aErrorPtr);
+}
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp
new file mode 100644
index 00000000..980b0565
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp
@@ -0,0 +1,3794 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+#include <stdlib.h>
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nspr.h"
+#include "nsCRT.h" // for atoll
+// Arena used by component manager for storing contractid string, dll
+// location strings and small objects
+// CAUTION: Arena align mask needs to be defined before including plarena.h
+// currently from nsComponentManager.h
+#define PL_ARENA_CONST_ALIGN_MASK 7
+#define NS_CM_BLOCK_SIZE (1024 * 8)
+
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCategoryManager.h"
+#include "nsCategoryManagerUtils.h"
+#include "nsIComponentLoader.h"
+#include "nsIEnumerator.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsIModule.h"
+#include "nsIObserverService.h"
+#include "nsISimpleEnumerator.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsLocalFile.h"
+#include "nsNativeComponentLoader.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#include "prcmon.h"
+#include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
+
+#include "nsInt64.h"
+#include "nsManifestLineReader.h"
+
+#include NEW_H // for placement new
+
+
+#ifdef XP_BEOS
+#include <FindDirectory.h>
+#include <Path.h>
+#endif
+
+#include "prlog.h"
+
+PRLogModuleInfo* nsComponentManagerLog = nsnull;
+
+#if 0 || defined (DEBUG_timeless)
+ #define SHOW_DENIED_ON_SHUTDOWN
+ #define SHOW_CI_ON_EXISTING_SERVICE
+ #define XPCOM_CHECK_PENDING_CIDS
+#endif
+
+// Loader Types
+#define NS_LOADER_DATA_ALLOC_STEP 6
+
+// Bloated registry buffer size to improve startup performance -- needs to
+// be big enough to fit the entire file into memory or it'll thrash.
+// 512K is big enough to allow for some future growth in the registry.
+#define BIG_REGISTRY_BUFLEN (512*1024)
+
+// Common Key Names
+const char classIDKeyName[]="classID";
+const char classesKeyName[]="contractID";
+const char componentLoadersKeyName[]="componentLoaders";
+const char componentsKeyName[]="components";
+const char xpcomComponentsKeyName[]="software/mozilla/XPCOM/components";
+const char xpcomKeyName[]="software/mozilla/XPCOM";
+
+// Common Value Names
+const char classIDValueName[]="ClassID";
+const char classNameValueName[]="ClassName";
+const char componentCountValueName[]="ComponentsCount";
+const char componentTypeValueName[]="ComponentType";
+const char contractIDValueName[]="ContractID";
+const char fileSizeValueName[]="FileSize";
+const char inprocServerValueName[]="InprocServer";
+const char lastModValueName[]="LastModTimeStamp";
+const char nativeComponentType[]="application/x-mozilla-native";
+const char staticComponentType[]="application/x-mozilla-static";
+const char versionValueName[]="VersionString";
+
+const static char XPCOM_ABSCOMPONENT_PREFIX[] = "abs:";
+const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:";
+const static char XPCOM_GRECOMPONENT_PREFIX[] = "gre:";
+
+static const char gIDFormat[] =
+ "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
+
+
+#define NS_EMPTY_IID \
+{ \
+ 0x00000000, \
+ 0x0000, \
+ 0x0000, \
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
+}
+
+NS_DEFINE_CID(kEmptyCID, NS_EMPTY_IID);
+NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
+
+#define UID_STRING_LENGTH 39
+
+// Set to true from NS_ShutdownXPCOM.
+extern PRBool gXPCOMShuttingDown;
+
+static void GetIDString(const nsID& aCID, char buf[UID_STRING_LENGTH])
+{
+ PR_snprintf(buf, UID_STRING_LENGTH, gIDFormat,
+ aCID.m0, (PRUint32) aCID.m1, (PRUint32) aCID.m2,
+ (PRUint32) aCID.m3[0], (PRUint32) aCID.m3[1],
+ (PRUint32) aCID.m3[2], (PRUint32) aCID.m3[3],
+ (PRUint32) aCID.m3[4], (PRUint32) aCID.m3[5],
+ (PRUint32) aCID.m3[6], (PRUint32) aCID.m3[7]);
+}
+
+nsresult
+nsCreateInstanceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
+{
+ /*
+ * If I were a real man, I would consolidate this with
+ * nsGetServiceFromContractID::operator().
+ */
+ nsresult rv;
+ nsXPIDLCString value;
+ nsCOMPtr<nsIComponentManager> compMgr;
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(kCategoryManagerCID, &rv);
+
+ if (NS_FAILED(rv)) goto error;
+
+ if (!mCategory || !mEntry) {
+ // when categories have defaults, use that for null mEntry
+ rv = NS_ERROR_NULL_POINTER;
+ goto error;
+ }
+
+ /* find the contractID for category.entry */
+ rv = catman->GetCategoryEntry(mCategory, mEntry,
+ getter_Copies(value));
+ if (NS_FAILED(rv)) goto error;
+ if (!value) {
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ goto error;
+ }
+ NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (!compMgr)
+ return NS_ERROR_FAILURE;
+ compMgr->CreateInstanceByContractID(value,
+ mOuter,
+ aIID,
+ aInstancePtr);
+ if (NS_FAILED(rv)) {
+ error:
+ *aInstancePtr = 0;
+ }
+
+ *mErrorPtr = rv;
+ return rv;
+}
+
+
+nsresult
+nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
+{
+ nsresult rv;
+ nsXPIDLCString value;
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(kCategoryManagerCID, &rv);
+ if (NS_FAILED(rv)) goto error;
+ if (!mCategory || !mEntry) {
+ // when categories have defaults, use that for null mEntry
+ rv = NS_ERROR_NULL_POINTER;
+ goto error;
+ }
+ /* find the contractID for category.entry */
+ rv = catman->GetCategoryEntry(mCategory, mEntry,
+ getter_Copies(value));
+ if (NS_FAILED(rv)) goto error;
+ if (!value) {
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ goto error;
+ }
+ if (mServiceManager) {
+ rv = mServiceManager->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ rv = mgr->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
+ }
+ if (NS_FAILED(rv)) {
+ error:
+ *aInstancePtr = 0;
+ }
+ *mErrorPtr = rv;
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Arena helper functions
+////////////////////////////////////////////////////////////////////////////////
+char *
+ArenaStrndup(const char *s, PRUint32 len, PLArenaPool *arena)
+{
+ void *mem;
+ // Include trailing null in the len
+ PL_ARENA_ALLOCATE(mem, arena, len+1);
+ if (mem)
+ memcpy(mem, s, len+1);
+ return NS_STATIC_CAST(char *, mem);
+}
+
+char*
+ArenaStrdup(const char *s, PLArenaPool *arena)
+{
+ return ArenaStrndup(s, strlen(s), arena);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Hashtable Callbacks
+////////////////////////////////////////////////////////////////////////////////
+
+PRBool PR_CALLBACK
+nsFactoryEntry_Destroy(nsHashKey *aKey, void *aData, void* closure);
+
+PR_STATIC_CALLBACK(const void *)
+factory_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+
+ return &entry->mFactoryEntry->mCid;
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+factory_HashKey(PLDHashTable *aTable, const void *aKey)
+{
+ const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
+
+ return cidp->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+factory_MatchEntry(PLDHashTable *aTable, const PLDHashEntryHdr *aHdr,
+ const void *aKey)
+{
+ const nsFactoryTableEntry* entry =
+ NS_STATIC_CAST(const nsFactoryTableEntry*, aHdr);
+ const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
+
+ return (entry->mFactoryEntry->mCid).Equals(*cidp);
+}
+
+PR_STATIC_CALLBACK(void)
+factory_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ entry->mFactoryEntry->~nsFactoryEntry();
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps factory_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ factory_GetKey,
+ factory_HashKey,
+ factory_MatchEntry,
+ PL_DHashMoveEntryStub,
+ factory_ClearEntry,
+ PL_DHashFinalizeStub,
+};
+
+PR_STATIC_CALLBACK(void)
+contractID_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+ if (entry->mFactoryEntry->mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY &&
+ entry->mFactoryEntry->mCid.Equals(kEmptyCID)) {
+ // this object is owned by the hash.
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ entry->mFactoryEntry->~nsFactoryEntry();
+ }
+
+ // contractIDs are arena allocated. No need to free them.
+
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps contractID_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashStringKey,
+ PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub,
+ contractID_ClearEntry,
+ PL_DHashFinalizeStub,
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsFactoryEntry
+////////////////////////////////////////////////////////////////////////////////
+
+MOZ_DECL_CTOR_COUNTER(nsFactoryEntry)
+nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
+ const char *aLocation,
+ PRUint32 locationlen,
+ int aType,
+ class nsFactoryEntry* parent)
+: mCid(aClass), mTypeIndex(aType), mParent(parent)
+{
+ // Arena allocate the location string
+ mLocation = ArenaStrndup(aLocation, locationlen, &nsComponentManagerImpl::gComponentManager->mArena);
+}
+
+nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
+ nsIFactory *aFactory,
+ class nsFactoryEntry* parent)
+: mCid(aClass), mTypeIndex(NS_COMPONENT_TYPE_FACTORY_ONLY), mParent(parent)
+{
+ mFactory = aFactory;
+ mLocation = nsnull;
+}
+
+// nsFactoryEntry is usually arena allocated including the strings it
+// holds. So we call destructor by hand.
+nsFactoryEntry::~nsFactoryEntry(void)
+{
+ // Release the reference to the factory
+ mFactory = nsnull;
+
+ // Release any service reference
+ mServiceObject = nsnull;
+
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ if (mParent)
+ mParent->~nsFactoryEntry();
+}
+
+nsresult
+nsFactoryEntry::ReInit(const nsCID &aClass, const char *aLocation, int aType)
+{
+ NS_ENSURE_TRUE(mTypeIndex != NS_COMPONENT_TYPE_FACTORY_ONLY, NS_ERROR_INVALID_ARG);
+ // cid has to match
+ // SERVICE_ONLY entries can be promoted to an entry of another type
+ NS_ENSURE_TRUE((mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || mCid.Equals(aClass)),
+ NS_ERROR_INVALID_ARG);
+
+ // Arena allocate the location string
+ mLocation = ArenaStrdup(aLocation, &nsComponentManagerImpl::gComponentManager->mArena);
+
+ mTypeIndex = aType;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Hashtable Enumeration
+////////////////////////////////////////////////////////////////////////////////
+typedef NS_CALLBACK(EnumeratorConverter)(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data,
+ nsISupports **retval);
+
+class PLDHashTableEnumeratorImpl : public nsIBidirectionalEnumerator,
+ public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIENUMERATOR
+ NS_DECL_NSIBIDIRECTIONALENUMERATOR
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ PLDHashTableEnumeratorImpl(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData);
+ PRInt32 Count() { return mCount; }
+private:
+ PLDHashTableEnumeratorImpl(); /* no implementation */
+
+ ~PLDHashTableEnumeratorImpl();
+ NS_IMETHODIMP ReleaseElements();
+
+ nsVoidArray mElements;
+ PRInt32 mCount, mCurrent;
+ PRMonitor* mMonitor;
+
+ struct Closure {
+ PRBool succeeded;
+ EnumeratorConverter converter;
+ void *data;
+ PLDHashTableEnumeratorImpl *impl;
+ };
+
+ static PLDHashOperator PR_CALLBACK Enumerator(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *data);
+};
+
+// static
+PLDHashOperator PR_CALLBACK
+PLDHashTableEnumeratorImpl::Enumerator(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *data)
+{
+ Closure *c = NS_REINTERPRET_CAST(Closure *, data);
+ nsISupports *converted;
+ if (NS_FAILED(c->converter(table, hdr, c->data, &converted)) ||
+ !c->impl->mElements.AppendElement(converted)) {
+ c->succeeded = PR_FALSE;
+ return PL_DHASH_STOP;
+ }
+
+ c->succeeded = PR_TRUE;
+ return PL_DHASH_NEXT;
+}
+
+PLDHashTableEnumeratorImpl::PLDHashTableEnumeratorImpl(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData)
+: mCurrent(0)
+{
+ mMonitor = nsAutoMonitor::NewMonitor("PLDHashTableEnumeratorImpl");
+ NS_ASSERTION(mMonitor, "NULL Monitor");
+
+ nsAutoMonitor mon(mMonitor);
+
+ Closure c = { PR_FALSE, converter, converterData, this };
+ mCount = PL_DHashTableEnumerate(table, Enumerator, &c);
+ if (!c.succeeded) {
+ ReleaseElements();
+ mCount = 0;
+ }
+}
+
+NS_IMPL_ISUPPORTS3(PLDHashTableEnumeratorImpl,
+ nsIBidirectionalEnumerator,
+ nsIEnumerator,
+ nsISimpleEnumerator)
+
+PLDHashTableEnumeratorImpl::~PLDHashTableEnumeratorImpl()
+{
+ (void) ReleaseElements();
+
+ // Destroy the Lock
+ if (mMonitor)
+ nsAutoMonitor::DestroyMonitor(mMonitor);
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::ReleaseElements()
+{
+ for (PRInt32 i = 0; i < mCount; i++) {
+ nsISupports *supports = NS_REINTERPRET_CAST(nsISupports *,
+ mElements[i]);
+ NS_IF_RELEASE(supports);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PL_NewDHashTableEnumerator(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData,
+ PLDHashTableEnumeratorImpl **retval)
+{
+ PLDHashTableEnumeratorImpl *impl =
+ new PLDHashTableEnumeratorImpl(table, converter, converterData);
+
+ if (!impl)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(impl);
+
+ if (impl->Count() == -1) {
+ // conversion failed
+ NS_RELEASE(impl);
+ return NS_ERROR_FAILURE;
+ }
+
+ *retval = impl;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::First()
+{
+ if (!mCount)
+ return NS_ERROR_FAILURE;
+
+ mCurrent = 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Last()
+{
+ if (!mCount)
+ return NS_ERROR_FAILURE;
+ mCurrent = mCount - 1;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Prev()
+{
+ if (!mCurrent)
+ return NS_ERROR_FAILURE;
+
+ mCurrent--;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Next()
+{
+ // If empty or we're past the end, or we are at the end return error
+ if (!mCount || (mCurrent == mCount) || (++mCurrent == mCount))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::CurrentItem(nsISupports **retval)
+{
+ if (!mCount || mCurrent == mCount)
+ return NS_ERROR_FAILURE;
+
+ *retval = NS_REINTERPRET_CAST(nsISupports *, mElements[mCurrent]);
+ if (*retval)
+ NS_ADDREF(*retval);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::IsDone()
+{
+ if (!mCount || (mCurrent == mCount))
+ return NS_OK;
+
+ return NS_ENUMERATOR_FALSE;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::HasMoreElements(PRBool *_retval)
+{
+ if (!mCount || (mCurrent == mCount))
+ *_retval = PR_FALSE;
+ else
+ *_retval = PR_TRUE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::GetNext(nsISupports **_retval)
+{
+ nsresult rv = Next();
+ if (NS_FAILED(rv)) return rv;
+
+ return CurrentItem(_retval);
+}
+
+static NS_IMETHODIMP
+ConvertFactoryEntryToCID(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data, nsISupports **retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupportsID> wrapper;
+
+ nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
+
+ rv = cm->CreateInstanceByContractID(NS_SUPPORTS_ID_CONTRACTID, nsnull,
+ NS_GET_IID(nsISupportsID), getter_AddRefs(wrapper));
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const nsFactoryTableEntry *entry =
+ NS_REINTERPRET_CAST(const nsFactoryTableEntry *, hdr);
+ if (entry) {
+ nsFactoryEntry *fe = entry->mFactoryEntry;
+
+ wrapper->SetData(&fe->mCid);
+ *retval = wrapper;
+ NS_ADDREF(*retval);
+ return NS_OK;
+ }
+ *retval = nsnull;
+
+ return rv;
+}
+
+static NS_IMETHODIMP
+ConvertContractIDKeyToString(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data, nsISupports **retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupportsCString> wrapper;
+
+ nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
+
+ rv = cm->CreateInstanceByContractID(NS_SUPPORTS_CSTRING_CONTRACTID, nsnull,
+ NS_GET_IID(nsISupportsCString), getter_AddRefs(wrapper));
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const nsContractIDTableEntry *entry =
+ NS_REINTERPRET_CAST(const nsContractIDTableEntry *, hdr);
+
+ wrapper->SetData(nsDependentCString(entry->mContractID,
+ entry->mContractIDLen));
+ *retval = wrapper;
+ NS_ADDREF(*retval);
+ return NS_OK;
+}
+
+// this is safe to call during InitXPCOM
+static nsresult GetLocationFromDirectoryService(const char* prop,
+ nsIFile** aDirectory)
+{
+ nsCOMPtr<nsIProperties> directoryService;
+ nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ getter_AddRefs(directoryService));
+
+ if (!directoryService)
+ return NS_ERROR_FAILURE;
+
+ return directoryService->Get(prop,
+ NS_GET_IID(nsIFile),
+ (void**)aDirectory);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsComponentManagerImpl
+////////////////////////////////////////////////////////////////////////////////
+
+
+nsComponentManagerImpl::nsComponentManagerImpl()
+ :
+ mMon(NULL),
+ mNativeComponentLoader(0),
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ mStaticComponentLoader(0),
+#endif
+ mShuttingDown(NS_SHUTDOWN_NEVERHAPPENED),
+ mLoaderData(nsnull),
+ mRegistryDirty(PR_FALSE)
+{
+ mFactories.ops = nsnull;
+ mContractIDs.ops = nsnull;
+}
+
+nsresult nsComponentManagerImpl::Init(void)
+{
+ PR_ASSERT(mShuttingDown != NS_SHUTDOWN_INPROGRESS);
+ if (mShuttingDown == NS_SHUTDOWN_INPROGRESS)
+ return NS_ERROR_FAILURE;
+
+ mShuttingDown = NS_SHUTDOWN_NEVERHAPPENED;
+
+ if (nsComponentManagerLog == nsnull)
+ {
+ nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
+ }
+
+ // Initialize our arena
+ PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
+
+ if (!mFactories.ops) {
+ if (!PL_DHashTableInit(&mFactories, &factory_DHashTableOps,
+ 0, sizeof(nsFactoryTableEntry),
+ 1024)) {
+ mFactories.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // Minimum alpha uses k=2 because nsFactoryTableEntry saves two
+ // words compared to what a chained hash table requires.
+ PL_DHashTableSetAlphaBounds(&mFactories,
+ 0.875,
+ PL_DHASH_MIN_ALPHA(&mFactories, 2));
+ }
+
+ if (!mContractIDs.ops) {
+ if (!PL_DHashTableInit(&mContractIDs, &contractID_DHashTableOps,
+ 0, sizeof(nsContractIDTableEntry),
+ 1024)) {
+ mContractIDs.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // Minimum alpha uses k=1 because nsContractIDTableEntry saves one
+ // word compared to what a chained hash table requires.
+#if 0
+ PL_DHashTableSetAlphaBounds(&mContractIDs,
+ 0.875,
+ PL_DHASH_MIN_ALPHA(&mContractIDs, 1));
+#endif
+ }
+ if (mMon == nsnull) {
+ mMon = nsAutoMonitor::NewMonitor("nsComponentManagerImpl");
+ if (mMon == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (mNativeComponentLoader == nsnull) {
+ /* Create the NativeComponentLoader */
+ mNativeComponentLoader = new nsNativeComponentLoader();
+ if (!mNativeComponentLoader)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(mNativeComponentLoader);
+
+ nsresult rv = mNativeComponentLoader->Init(this, nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Add predefined loaders
+ mLoaderData = (nsLoaderdata *) PR_Malloc(sizeof(nsLoaderdata) * NS_LOADER_DATA_ALLOC_STEP);
+ if (!mLoaderData)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mMaxNLoaderData = NS_LOADER_DATA_ALLOC_STEP;
+
+ mNLoaderData = NS_COMPONENT_TYPE_NATIVE;
+ mLoaderData[mNLoaderData].type = PL_strdup(nativeComponentType);
+ mLoaderData[mNLoaderData].loader = mNativeComponentLoader;
+ NS_ADDREF(mLoaderData[mNLoaderData].loader);
+ mNLoaderData++;
+
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ if (mStaticComponentLoader == nsnull) {
+ extern nsresult NS_NewStaticComponentLoader(nsIComponentLoader **);
+ NS_NewStaticComponentLoader(&mStaticComponentLoader);
+ if (!mStaticComponentLoader)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ mLoaderData[mNLoaderData].type = PL_strdup(staticComponentType);
+ mLoaderData[mNLoaderData].loader = mStaticComponentLoader;
+ NS_ADDREF(mLoaderData[mNLoaderData].loader);
+ mNLoaderData++;
+
+ if (mStaticComponentLoader) {
+ /* Init the static loader */
+ mStaticComponentLoader->Init(this, nsnull);
+ }
+#endif
+ GetLocationFromDirectoryService(NS_XPCOM_COMPONENT_DIR, getter_AddRefs(mComponentsDir));
+ if (!mComponentsDir)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCAutoString componentDescriptor;
+ nsresult rv = mComponentsDir->GetNativePath(componentDescriptor);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mComponentsOffset = componentDescriptor.Length();
+
+ GetLocationFromDirectoryService(NS_GRE_COMPONENT_DIR, getter_AddRefs(mGREComponentsDir));
+ if (mGREComponentsDir) {
+ nsresult rv = mGREComponentsDir->GetNativePath(componentDescriptor);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("No GRE component manager");
+ return rv;
+ }
+ mGREComponentsOffset = componentDescriptor.Length();
+ }
+
+ GetLocationFromDirectoryService(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ getter_AddRefs(mRegistryFile));
+
+ if(!mRegistryFile) {
+ NS_WARNING("No Component Registry file was found in the directory service");
+ return NS_ERROR_FAILURE;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsComponentManager: Initialized."));
+
+ return NS_OK;
+}
+
+PRIntn PR_CALLBACK AutoRegEntryDestroy(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ delete (AutoRegEntry*)aData;
+ return kHashEnumerateNext;
+}
+
+nsresult nsComponentManagerImpl::Shutdown(void)
+{
+ PR_ASSERT(mShuttingDown == NS_SHUTDOWN_NEVERHAPPENED);
+ if (mShuttingDown != NS_SHUTDOWN_NEVERHAPPENED)
+ return NS_ERROR_FAILURE;
+
+ mShuttingDown = NS_SHUTDOWN_INPROGRESS;
+
+ // Shutdown the component manager
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
+
+ PRInt32 i;
+
+ // Write out our component data file.
+ if (mRegistryDirty) {
+ nsresult rv = WritePersistentRegistry();
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, ("nsComponentManager: Could not write out perisistant registry."));
+#ifdef DEBUG
+ printf("Could not write out perisistant registry!\n");
+#endif
+ }
+ }
+
+ mAutoRegEntries.Reset(AutoRegEntryDestroy);
+
+ // Release all cached factories
+ if (mContractIDs.ops) {
+ PL_DHashTableFinish(&mContractIDs);
+ mContractIDs.ops = nsnull;
+ }
+ if (mFactories.ops) {
+ PL_DHashTableFinish(&mFactories);
+ mFactories.ops = nsnull;
+ }
+ // Unload libraries
+ UnloadLibraries(nsnull, NS_Shutdown);
+
+ // delete arena for strings and small objects
+ PL_FinishArenaPool(&mArena);
+
+ mComponentsDir = 0;
+
+ mCategoryManager = 0;
+
+ // Release all the component data - loaders and type strings
+ for (i=0; i < mNLoaderData; i++) {
+ NS_IF_RELEASE(mLoaderData[i].loader);
+ PL_strfree((char *)mLoaderData[i].type);
+ }
+ PR_Free(mLoaderData);
+ mLoaderData = nsnull;
+
+ // we have an extra reference on this one, which is probably a good thing
+ NS_IF_RELEASE(mNativeComponentLoader);
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ NS_IF_RELEASE(mStaticComponentLoader);
+#endif
+
+ mShuttingDown = NS_SHUTDOWN_COMPLETE;
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Shutdown complete."));
+
+ return NS_OK;
+}
+
+nsComponentManagerImpl::~nsComponentManagerImpl()
+{
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction."));
+
+ if (mShuttingDown != NS_SHUTDOWN_COMPLETE)
+ Shutdown();
+
+ if (mMon) {
+ nsAutoMonitor::DestroyMonitor(mMon);
+ }
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS8(nsComponentManagerImpl,
+ nsIComponentManager,
+ nsIServiceManager,
+ nsISupportsWeakReference,
+ nsIInterfaceRequestor,
+ nsIComponentRegistrar,
+ nsIServiceManagerObsolete,
+ nsIComponentManagerObsolete,
+ nsIComponentLoaderManager)
+
+
+nsresult
+nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
+{
+ if (uuid.Equals(NS_GET_IID(nsINativeComponentLoader)))
+ {
+ if (!mNativeComponentLoader)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ return mNativeComponentLoader->QueryInterface(uuid, result);
+ }
+
+ NS_WARNING("This isn't supported");
+ // fall through to QI as anything QIable is a superset of what can be
+ // got via the GetInterface()
+ return QueryInterface(uuid, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsComponentManagerImpl: Platform methods
+////////////////////////////////////////////////////////////////////////////////
+
+#define PERSISTENT_REGISTRY_VERSION_MINOR 5
+#define PERSISTENT_REGISTRY_VERSION_MAJOR 0
+
+
+AutoRegEntry::AutoRegEntry(const nsACString& name, PRInt64* modDate) :
+ mName(ToNewCString(name)),
+ mNameLen(name.Length()),
+ mData(nsnull),
+ mModDate(*modDate)
+{
+}
+
+AutoRegEntry::~AutoRegEntry()
+{
+ if (mName) PL_strfree(mName);
+ if (mData) PL_strfree(mData);
+}
+
+PRBool
+AutoRegEntry::Modified(PRInt64 *date)
+{
+ return !LL_EQ(*date, mModDate);
+}
+
+void
+AutoRegEntry::SetOptionalData(const char* data)
+{
+ if (mData)
+ PL_strfree(mData);
+
+ if (!data) {
+ mData = nsnull;
+ return;
+ }
+
+ mData = PL_strdup(data);
+}
+
+static
+PRBool ReadSectionHeader(nsManifestLineReader& reader, const char *token)
+{
+ while (1)
+ {
+ if (*reader.LinePtr() == '[')
+ {
+ char* p = reader.LinePtr() + (reader.LineLength() - 1);
+ if (*p != ']')
+ break;
+ *p = 0;
+
+ char* values[1];
+ int lengths[1];
+ if (2 != reader.ParseLine(values, lengths, 1))
+ break;
+
+ // ignore the leading '['
+ if (0 != PL_strcmp(values[0]+1, token))
+ break;
+
+ return PR_TRUE;
+ }
+
+ if (!reader.NextLine())
+ break;
+ }
+ return PR_FALSE;
+}
+
+nsresult
+nsComponentManagerImpl::ReadPersistentRegistry()
+{
+
+ // populate Category Manager. need to get this early so that we don't get
+ // skipped by 'goto out'
+ nsresult rv = GetService(kCategoryManagerCID,
+ NS_GET_IID(nsICategoryManager),
+ getter_AddRefs(mCategoryManager));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsAutoMonitor mon(mMon);
+ nsManifestLineReader reader;
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED; // this should have been set by Init().
+
+ PRFileDesc* fd = nsnull;
+
+ // Set From Init
+ if (!mRegistryFile) {
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ nsCOMPtr<nsIFile> file;
+ mRegistryFile->Clone(getter_AddRefs(file));
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
+
+ rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 fileSize;
+ rv = localFile->GetFileSize(&fileSize);
+ if (NS_FAILED(rv))
+ {
+ PR_Close(fd);
+ return rv;
+ }
+
+ PRInt32 flen = nsInt64(fileSize);
+ if (flen == 0)
+ {
+ PR_Close(fd);
+ NS_WARNING("Persistent Registry Empty!");
+ return NS_OK; // ERROR CONDITION
+ }
+
+ char* registry = new char[flen+1];
+ if (!registry)
+ goto out;
+
+ if (flen > PR_Read(fd, registry, flen))
+ {
+ rv = NS_ERROR_FAILURE;
+ goto out;
+ }
+ registry[flen] = '\0';
+
+ reader.Init(registry, flen);
+
+ if (ReadSectionHeader(reader, "HEADER"))
+ goto out;
+
+ if (!reader.NextLine())
+ goto out;
+
+ char* values[6];
+ int lengths[6];
+
+ // VersionLiteral,major,minor
+ if (3 != reader.ParseLine(values, lengths, 3))
+ goto out;
+
+ // VersionLiteral
+ if (!nsDependentCString(values[0], lengths[0]).EqualsLiteral("Version"))
+ goto out;
+
+ // major
+ if (PERSISTENT_REGISTRY_VERSION_MAJOR != atoi(values[1]))
+ goto out;
+
+ // minor
+ if (PERSISTENT_REGISTRY_VERSION_MINOR != atoi(values[2]))
+ goto out;
+
+ if (ReadSectionHeader(reader, "COMPONENTS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //name,last_modification_date[,optionaldata]
+ int parts = reader.ParseLine(values, lengths, 3);
+ if (2 > parts)
+ break;
+
+ PRInt64 a = nsCRT::atoll(values[1]);
+ AutoRegEntry *entry =
+ new AutoRegEntry(nsDependentCString(values[0], lengths[0]), &a);
+
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (parts == 3)
+ entry->SetOptionalData(values[2]);
+
+ nsCStringKey key((const char*)values[0]);
+ mAutoRegEntries.Put(&key, entry);
+ }
+
+ if (ReadSectionHeader(reader, "CLASSIDS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ // cid,contract_id,type,class_name,inproc_server
+ if (5 != reader.ParseLine(values, lengths, 5))
+ break;
+
+ nsCID aClass;
+ if (!aClass.Parse(values[0]))
+ continue;
+
+ int loadertype = GetLoaderType(values[2]);
+ if (loadertype < 0) {
+ rv = AddLoaderType(values[2], &loadertype);
+ if (NS_FAILED(rv))
+ continue;
+ }
+
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsFactoryEntry *entry = new (mem) nsFactoryEntry(aClass, values[4], lengths[4], loadertype);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories,
+ &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+
+ }
+
+ if (ReadSectionHeader(reader, "CONTRACTIDS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //contractID,cid
+ if (2 != reader.ParseLine(values, lengths, 2))
+ break;
+
+ nsCID aClass;
+ if (!aClass.Parse(values[1]))
+ continue;
+
+
+ //need to find the location for this cid.
+ nsFactoryEntry *cidEntry = GetFactoryEntry(aClass);
+ if (!cidEntry || cidEntry->mTypeIndex < 0)
+ continue; //what should we really do?
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs,
+ values[0],
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry) {
+ continue;
+ }
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID = ArenaStrndup(values[0], lengths[0], &mArena);
+ contractIDTableEntry->mContractIDLen = lengths[0];
+ }
+
+ contractIDTableEntry->mFactoryEntry = cidEntry;
+ }
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ {
+/*
+ * If you get Asserts when you define SHOW_CI_ON_EXISTING_SERVICE and want to
+ * track down their cause, then you should add the contracts listed by the
+ * assertion to abusedContracts. The next time you run your xpcom app, xpcom
+ * will assert the first time the object associated with the contract is
+ * instantiated (which in many cases is the source of the problem).
+ *
+ * If you're doing this then you might want to NOP and soft breakpoint the
+ * lines labeled: NOP_AND_BREAK.
+ *
+ * Otherwise XPCOM will refuse to create the object for the caller, which
+ * while reasonable at some level, will almost certainly cause the app to
+ * stop functioning normally.
+ */
+ static char abusedContracts[][128] = {
+ /*// Example contracts:
+ "@mozilla.org/rdf/container;1",
+ "@mozilla.org/intl/charsetalias;1",
+ "@mozilla.org/locale/win32-locale;1",
+ "@mozilla.org/widget/lookandfeel/win;1",
+ // */
+ { 0 }
+ };
+ for (int i=0; abusedContracts[i] && *abusedContracts[i]; i++) {
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, abusedContracts[i],
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ AddPendingCID(entry->mCid);
+ }
+ }
+ }
+#endif
+
+ if (ReadSectionHeader(reader, "CATEGORIES"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //type,name,value
+ if (3 != reader.ParseLine(values, lengths, 3))
+ break;
+
+ mCategoryManager->AddCategoryEntry(values[0],
+ values[1],
+ values[2],
+ PR_TRUE,
+ PR_TRUE,
+ 0);
+ }
+
+ mRegistryDirty = PR_FALSE;
+out:
+ if (fd)
+ PR_Close(fd);
+
+ if (registry)
+ delete [] registry;
+
+ return rv;
+}
+
+struct PersistentWriterArgs
+{
+ PRFileDesc *mFD;
+ nsLoaderdata *mLoaderData;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+ContractIDWriter(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg)
+{
+ char *contractID = ((nsContractIDTableEntry*)hdr)->mContractID;
+ nsFactoryEntry *factoryEntry = ((nsContractIDTableEntry*)hdr)->mFactoryEntry;
+
+ // for now, we only save out the top most parent.
+ while (factoryEntry->mParent)
+ factoryEntry = factoryEntry->mParent;
+
+ if (factoryEntry->mTypeIndex < 0)
+ return PL_DHASH_NEXT;
+
+ PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
+
+ char cidString[UID_STRING_LENGTH];
+ GetIDString(factoryEntry->mCid, cidString);
+ PR_fprintf(fd, "%s,%s\n", contractID, cidString); // what if this fails?
+ return PL_DHASH_NEXT;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+ClassIDWriter(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg)
+{
+ nsFactoryEntry *factoryEntry = ((nsFactoryTableEntry*)hdr)->mFactoryEntry;
+ PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
+ nsLoaderdata *loaderData = ((PersistentWriterArgs*)arg)->mLoaderData;
+
+ // for now, we only save out the top most parent.
+ while (factoryEntry->mParent)
+ factoryEntry = factoryEntry->mParent;
+
+ if (factoryEntry->mTypeIndex < 0) {
+ return PL_DHASH_NEXT;
+ }
+
+ char cidString[UID_STRING_LENGTH];
+ GetIDString(factoryEntry->mCid, cidString);
+
+ char *contractID = nsnull, *className = nsnull;
+
+ nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(factoryEntry->mFactory);
+ if (classInfo)
+ {
+ classInfo->GetContractID(&contractID);
+ classInfo->GetClassDescription(&className);
+ }
+
+ const char * loaderName = nsnull;
+ if (factoryEntry->mTypeIndex)
+ loaderName = loaderData[factoryEntry->mTypeIndex].type;
+
+ char* location = factoryEntry->mLocation;
+
+ // cid,contract_id,type,class_name,inproc_server
+ PR_fprintf(fd,
+ "%s,%s,%s,%s,%s\n",
+ cidString,
+ (contractID ? contractID : ""),
+ (loaderName ? loaderName : ""),
+ (className ? className : ""),
+ (location ? location : ""));
+
+ if (contractID)
+ PR_Free(contractID);
+ if (className)
+ PR_Free(className);
+
+ return PL_DHASH_NEXT;
+}
+
+PRIntn PR_CALLBACK
+AutoRegEntryWriter(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ PRFileDesc* fd = (PRFileDesc*) aClosure;
+ AutoRegEntry* entry = (AutoRegEntry*) aData;
+
+ const char* extraData = entry->GetOptionalData();
+ const char *fmt;
+ if (extraData)
+ fmt = "%s,%lld,%s\n";
+ else
+ fmt = "%s,%lld\n";
+ PR_fprintf(fd, fmt, entry->GetName().get(), entry->GetDate(), extraData);
+
+ return PR_TRUE;
+}
+
+nsresult
+nsComponentManagerImpl::WritePersistentRegistry()
+{
+ if (!mRegistryFile)
+ return NS_ERROR_FAILURE; // this should have been set by Init().
+
+ nsCOMPtr<nsIFile> file;
+ mRegistryFile->Clone(getter_AddRefs(file));
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
+
+ nsCAutoString originalLeafName;
+ localFile->GetNativeLeafName(originalLeafName);
+
+ nsCAutoString leafName;
+ leafName.Assign(originalLeafName + NS_LITERAL_CSTRING(".tmp"));
+
+ localFile->SetNativeLeafName(leafName);
+
+ PRFileDesc* fd = nsnull;
+ nsresult rv = localFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (PR_fprintf(fd, "Generated File. Do not edit.\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ if (PR_fprintf(fd, "\n[HEADER]\nVersion,%d,%d\n",
+ PERSISTENT_REGISTRY_VERSION_MAJOR,
+ PERSISTENT_REGISTRY_VERSION_MINOR) == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ if (PR_fprintf(fd, "\n[COMPONENTS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ mAutoRegEntries.Enumerate(AutoRegEntryWriter, (void*)fd);
+
+ PersistentWriterArgs args;
+ args.mFD = fd;
+ args.mLoaderData = mLoaderData;
+
+ if (PR_fprintf(fd, "\n[CLASSIDS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ PL_DHashTableEnumerate(&mFactories, ClassIDWriter, (void*)&args);
+
+ if (PR_fprintf(fd, "\n[CONTRACTIDS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ PL_DHashTableEnumerate(&mContractIDs, ContractIDWriter, (void*)&args);
+
+ if (PR_fprintf(fd, "\n[CATEGORIES]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ if (!mCategoryManager) {
+ NS_WARNING("Could not access category manager. Will not be able to save categories!");
+ rv = NS_ERROR_UNEXPECTED;
+ } else {
+ rv = mCategoryManager->WriteCategoryManagerToRegistry(fd);
+ }
+
+out:
+ if (fd)
+ PR_Close(fd);
+
+ // don't create the file is there was a problem????
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mRegistryFile)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ PRBool exists;
+ if(NS_FAILED(mRegistryFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(mRegistryFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> parent;
+ mRegistryFile->GetParent(getter_AddRefs(parent));
+
+ rv = localFile->MoveToNative(parent, originalLeafName);
+ mRegistryDirty = PR_FALSE;
+
+ return rv;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Hash Functions
+////////////////////////////////////////////////////////////////////////////////
+nsresult
+nsComponentManagerImpl::HashContractID(const char *aContractID,
+ PRUint32 aContractIDLen,
+ nsFactoryEntry *fe)
+{
+ if(!aContractID || !aContractIDLen)
+ return NS_ERROR_NULL_POINTER;
+
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(!contractIDTableEntry->mContractID || !strcmp(contractIDTableEntry->mContractID, aContractID), "contractid conflict");
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID = ArenaStrndup(aContractID, aContractIDLen, &mArena);
+ contractIDTableEntry->mContractIDLen = aContractIDLen;
+ }
+
+ contractIDTableEntry->mFactoryEntry = fe;
+
+ return NS_OK;
+}
+
+/**
+ * LoadFactory()
+ *
+ * Given a FactoryEntry, this loads the dll if it has to, find the NSGetFactory
+ * symbol, calls the routine to create a new factory and returns it to the
+ * caller.
+ *
+ * No attempt is made to store the factory in any form anywhere.
+ */
+nsresult
+nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
+ nsIFactory **aFactory)
+{
+
+ if (!aFactory)
+ return NS_ERROR_NULL_POINTER;
+ *aFactory = nsnull;
+
+ nsresult rv;
+ rv = aEntry->GetFactory(aFactory, this);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsComponentManager: FAILED to load factory from %s (%s)\n",
+ (const char *)aEntry->mLocation, mLoaderData[aEntry->mTypeIndex].type));
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+nsFactoryEntry *
+nsComponentManagerImpl::GetFactoryEntry(const char *aContractID,
+ PRUint32 aContractIDLen)
+{
+ nsFactoryEntry *fe = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ fe = contractIDTableEntry->mFactoryEntry;
+ }
+ } //exit monitor
+
+ return fe;
+}
+
+
+nsFactoryEntry *
+nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass)
+{
+ nsFactoryEntry *entry = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+ } // exit monitor
+
+ return entry;
+}
+
+
+/**
+ * FindFactory()
+ *
+ * Given a classID, this finds the factory for this CID by first searching the
+ * local CID<->factory mapping. Next it searches for a Dll that implements
+ * this classID and calls LoadFactory() to create the factory.
+ *
+ * Again, no attempt is made at storing the factory.
+ */
+nsresult
+nsComponentManagerImpl::FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory)
+{
+ PR_ASSERT(aFactory != nsnull);
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ return entry->GetFactory(aFactory, this);
+}
+
+
+nsresult
+nsComponentManagerImpl::FindFactory(const char *contractID,
+ PRUint32 aContractIDLen,
+ nsIFactory **aFactory)
+{
+ PR_ASSERT(aFactory != nsnull);
+
+ nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ return entry->GetFactory(aFactory, this);
+}
+
+/**
+ * GetClassObject()
+ *
+ * Given a classID, this finds the singleton ClassObject that implements the CID.
+ * Returns an interface of type aIID off the singleton classobject.
+ */
+nsresult
+nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIFactory> factory;
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
+ {
+ char *buf = aClass.ToString();
+ PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ PR_ASSERT(aResult != nsnull);
+
+ rv = FindFactory(aClass, getter_AddRefs(factory));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = factory->QueryInterface(aIID, aResult);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+
+nsresult
+nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIFactory> factory;
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
+ {
+ PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
+ }
+#endif
+
+ PR_ASSERT(aResult != nsnull);
+
+ rv = FindFactory(contractID, strlen(contractID), getter_AddRefs(factory));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = factory->QueryInterface(aIID, aResult);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+/**
+ * ContractIDToClassID()
+ *
+ * Mapping function from a ContractID to a classID. Directly talks to the registry.
+ *
+ */
+nsresult
+nsComponentManagerImpl::ContractIDToClassID(const char *aContractID, nsCID *aClass)
+{
+ NS_PRECONDITION(aContractID != nsnull, "null ptr");
+ if (!aContractID)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aClass != nsnull, "null ptr");
+ if (!aClass)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ nsFactoryEntry *fe = GetFactoryEntry(aContractID, strlen(aContractID));
+ if (fe) {
+ *aClass = fe->mCid;
+ rv = NS_OK;
+ }
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING)) {
+ char *buf = 0;
+ if (NS_SUCCEEDED(rv))
+ buf = aClass->ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: ContractIDToClassID(%s)->%s", aContractID,
+ NS_SUCCEEDED(rv) ? buf : "[FAILED]"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ return rv;
+}
+
+/**
+ * CLSIDToContractID()
+ *
+ * Translates a classID to a {ContractID, Class Name}. Does direct registry
+ * access to do the translation.
+ *
+ * NOTE: Since this isn't heavily used, we arent caching this.
+ */
+nsresult
+nsComponentManagerImpl::CLSIDToContractID(const nsCID &aClass,
+ char* *aClassName,
+ char* *aContractID)
+{
+ NS_WARNING("Need to implement CLSIDToContractID");
+
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CLSIDToContractID(%s)->%s", buf,
+ NS_SUCCEEDED(rv) ? *aContractID : "[FAILED]"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ return rv;
+}
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+
+// This method must be called from within the mMon monitor
+nsresult
+nsComponentManagerImpl::AddPendingCID(const nsCID &aClass)
+{
+ int max = mPendingCIDs.Count();
+ for (int index = 0; index < max; index++)
+ {
+ nsCID *cidp = (nsCID*) mPendingCIDs.ElementAt(index);
+ NS_ASSERTION(cidp, "Bad CID in pending list");
+ if (cidp->Equals(aClass)) {
+ nsXPIDLCString cid;
+ cid.Adopt(aClass.ToString());
+ nsCAutoString message;
+ message = NS_LITERAL_CSTRING("Creation of \"") +
+ cid + NS_LITERAL_CSTRING("\" in progress (Reentrant GS - see bug 194568)");
+ // Note that you may see this assertion by near-simultaneous
+ // calls to GetService on multiple threads.
+ NS_WARNING(message.get());
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ }
+ mPendingCIDs.AppendElement((void*)&aClass);
+ return NS_OK;
+}
+
+// This method must be called from within the mMon monitor
+void
+nsComponentManagerImpl::RemovePendingCID(const nsCID &aClass)
+{
+ mPendingCIDs.RemoveElement((void*)&aClass);
+}
+#endif
+/**
+ * CreateInstance()
+ *
+ * Create an instance of an object that implements an interface and belongs
+ * to the implementation aClass using the factory. The factory is immediately
+ * released and not held onto for any longer.
+ */
+nsresult
+nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ // test this first, since there's no point in creating a component during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ if (aResult == nsnull)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aResult = nsnull;
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+#ifdef SHOW_CI_ON_EXISTING_SERVICE
+ if (entry->mServiceObject) {
+ nsXPIDLCString cid;
+ cid.Adopt(aClass.ToString());
+ nsCAutoString message;
+ message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
+ cid + NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
+ NS_ERROR(message.get());
+ }
+#endif
+
+ nsIFactory *factory = nsnull;
+ nsresult rv = entry->GetFactory(&factory, this);
+
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = factory->CreateInstance(aDelegate, aIID, aResult);
+ NS_RELEASE(factory);
+ }
+ else
+ {
+ // Translate error values
+ rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CreateInstance(%s) %s", buf,
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ return rv;
+}
+
+/**
+ * CreateInstanceByContractID()
+ *
+ * A variant of CreateInstance() that creates an instance of the object that
+ * implements the interface aIID and whose implementation has a contractID aContractID.
+ *
+ * This is only a convenience routine that turns around can calls the
+ * CreateInstance() with classid and iid.
+ */
+nsresult
+nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ // test this first, since there's no point in creating a component during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ if (aResult == nsnull)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aResult = nsnull;
+
+ nsFactoryEntry *entry = GetFactoryEntry(aContractID, strlen(aContractID));
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+#ifdef SHOW_CI_ON_EXISTING_SERVICE
+ if (entry->mServiceObject) {
+ nsCAutoString message;
+ message =
+ NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
+ nsDependentCString(aContractID) +
+ NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
+ "Add it to abusedContracts to track down the service consumer.");
+ NS_ERROR(message.get());
+ }
+#endif
+
+ nsIFactory *factory = nsnull;
+ nsresult rv = entry->GetFactory(&factory, this);
+
+ if (NS_SUCCEEDED(rv))
+ {
+
+ rv = factory->CreateInstance(aDelegate, aIID, aResult);
+ NS_RELEASE(factory);
+ }
+ else
+ {
+ // Translate error values
+ if (rv != NS_ERROR_SOCKET_FAIL)
+ rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+// Service Manager Impl
+static
+PLDHashOperator PR_CALLBACK
+FreeServiceFactoryEntryEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ factoryEntry->mServiceObject = nsnull;
+ return PL_DHASH_NEXT;
+}
+
+static
+PLDHashOperator PR_CALLBACK
+FreeServiceContractIDEntryEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ factoryEntry->mServiceObject = nsnull;
+ return PL_DHASH_NEXT;
+}
+
+nsresult
+nsComponentManagerImpl::FreeServices()
+{
+ NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services");
+
+ if (!gXPCOMShuttingDown)
+ return NS_ERROR_FAILURE;
+
+ if (mContractIDs.ops) {
+ PL_DHashTableEnumerate(&mContractIDs, FreeServiceContractIDEntryEnumerate, nsnull);
+ }
+
+
+ if (mFactories.ops) {
+ PL_DHashTableEnumerate(&mFactories, FreeServiceFactoryEntryEnumerate, nsnull);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const nsCID& aClass,
+ const nsIID& aIID,
+ void* *result)
+{
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Getting service on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsAutoMonitor mon(mMon);
+
+ nsresult rv = NS_OK;
+ nsIDKey key(aClass);
+ nsFactoryEntry* entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && entry->mServiceObject) {
+ return entry->mServiceObject->QueryInterface(aIID, result);
+ }
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ rv = AddPendingCID(aClass);
+ if (NS_FAILED(rv))
+ return rv; // NOP_AND_BREAK
+#endif
+ nsCOMPtr<nsISupports> service;
+ // We need to not be holding the service manager's monitor while calling
+ // CreateInstance, because it invokes user code which could try to re-enter
+ // the service manager:
+ mon.Exit();
+
+ rv = CreateInstance(aClass, nsnull, aIID, getter_AddRefs(service));
+
+ mon.Enter();
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ RemovePendingCID(aClass);
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!entry) { // second hash lookup for GetService
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+ NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
+ if (!entry) return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = service;
+ *result = service.get();
+ NS_ADDREF(NS_STATIC_CAST(nsISupports*, (*result)));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterService(const nsCID& aClass, nsISupports* aService)
+{
+ nsAutoMonitor mon(mMon);
+
+ // check to see if we have a factory entry for the service
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry = new (mem) nsFactoryEntry(aClass, nsnull);
+
+ entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_ADD));
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+ }
+ else {
+ if (entry->mServiceObject)
+ return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = aService;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterService(const nsCID& aClass)
+{
+ nsresult rv = NS_OK;
+
+ nsFactoryEntry* entry = nsnull;
+
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (!entry || !entry->mServiceObject)
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+
+ entry->mServiceObject = nsnull;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterService(const char* aContractID, nsISupports* aService)
+{
+
+ nsAutoMonitor mon(mMon);
+
+ // check to see if we have a factory entry for the service
+ PRUint32 contractIDLen = strlen(aContractID);
+ nsFactoryEntry *entry = GetFactoryEntry(aContractID, contractIDLen);
+
+ if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry = new (mem) nsFactoryEntry(kEmptyCID, nsnull);
+
+ entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry) {
+ delete entry;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID =
+ ArenaStrndup(aContractID, contractIDLen, &mArena);
+
+ contractIDTableEntry->mContractIDLen = contractIDLen;
+ }
+
+ contractIDTableEntry->mFactoryEntry = entry;
+ }
+ else {
+ if (entry->mServiceObject)
+ return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = aService;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass,
+ const nsIID& aIID,
+ PRBool *result)
+{
+ // Now we want to get the service if we already got it. If not, we dont want
+ // to create an instance of it. mmh!
+
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Checking for service on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ nsFactoryEntry* entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && entry->mServiceObject) {
+ nsCOMPtr<nsISupports> service;
+ rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
+ *result = (service!=nsnull);
+ }
+ return rv;
+
+}
+
+NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID,
+ const nsIID& aIID,
+ PRBool *result)
+{
+ // Now we want to get the service if we already got it. If not, we dont want
+ // to create an instance of it. mmh!
+
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Checking for service on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ nsFactoryEntry *entry = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+ } // exit monitor
+
+ if (entry && entry->mServiceObject) {
+ nsCOMPtr<nsISupports> service;
+ rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
+ *result = (service!=nsnull);
+ }
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterService(const char* aContractID)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+
+ if (!entry || !entry->mServiceObject)
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+
+ entry->mServiceObject = nsnull;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
+ const nsIID& aIID,
+ void* *result)
+{
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Getting service on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsAutoMonitor mon(mMon);
+
+ nsresult rv = NS_OK;
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+
+ if (entry) {
+ if (entry->mServiceObject) {
+ return entry->mServiceObject->QueryInterface(aIID, result);
+ }
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ rv = AddPendingCID(entry->mCid);
+ if (NS_FAILED(rv))
+ return rv; // NOP_AND_BREAK
+#endif
+ }
+
+ nsCOMPtr<nsISupports> service;
+ // We need to not be holding the service manager's monitor while calling
+ // CreateInstance, because it invokes user code which could try to re-enter
+ // the service manager:
+ mon.Exit();
+
+ rv = CreateInstanceByContractID(aContractID, nsnull, aIID, getter_AddRefs(service));
+
+ mon.Enter();
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ if (entry)
+ RemovePendingCID(entry->mCid);
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!entry) { // second hash lookup for GetService
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+ NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
+ if (!entry) return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = service;
+ *result = service.get();
+ NS_ADDREF(NS_STATIC_CAST(nsISupports*, *result));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+ return GetService(aClass, aIID, (void**)result);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+ return GetServiceByContractID(aContractID, aIID, (void**)result);
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+/*
+ * I want an efficient way to allocate a buffer to the right size
+ * and stick the prefix and dllName in, then be able to hand that buffer
+ * off to the FactoryEntry. Is that so wrong?
+ *
+ * *regName is allocated on success.
+ *
+ * This should live in nsNativeComponentLoader.cpp, I think.
+ */
+static nsresult
+MakeRegistryName(const char *aDllName, const char *prefix, char **regName)
+{
+ char *registryName;
+
+ PRUint32 len = strlen(prefix);
+
+ PRUint32 registryNameLen = strlen(aDllName) + len;
+ registryName = (char *)nsMemory::Alloc(registryNameLen + 1);
+
+ // from here on it, we want len sans terminating NUL
+
+ if (!registryName)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ memcpy(registryName, prefix, len);
+ strcpy(registryName + len, aDllName);
+ registryName[registryNameLen] = '\0';
+ *regName = registryName;
+
+#ifdef DEBUG_shaver_off
+ fprintf(stderr, "MakeRegistryName(%s, %s, &[%s])\n",
+ aDllName, prefix, *regName);
+#endif
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::RegistryLocationForSpec(nsIFile *aSpec,
+ char **aRegistryName)
+{
+ nsresult rv;
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ if (!aSpec) {
+ *aRegistryName = PL_strdup("");
+ return NS_OK;
+ }
+
+
+ // First check to see if this component is in the application
+ // components directory
+ PRBool containedIn;
+ mComponentsDir->Contains(aSpec, PR_TRUE, &containedIn);
+
+ nsCAutoString nativePathString;
+
+ if (containedIn){
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* relativeLocation = nativePathString.get() + mComponentsOffset + 1;
+ return MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX, aRegistryName);
+ }
+
+ // Next check to see if this component is in the GRE
+ // components directory
+
+ mGREComponentsDir->Contains(aSpec, PR_TRUE, &containedIn);
+
+ if (containedIn){
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* relativeLocation = nativePathString.get() + mGREComponentsOffset + 1;
+ return MakeRegistryName(relativeLocation, XPCOM_GRECOMPONENT_PREFIX, aRegistryName);
+ }
+
+ /* absolute names include volume info on Mac, so persistent descriptor */
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+ return MakeRegistryName(nativePathString.get(), XPCOM_ABSCOMPONENT_PREFIX, aRegistryName);
+}
+
+nsresult
+nsComponentManagerImpl::SpecForRegistryLocation(const char *aLocation,
+ nsIFile **aSpec)
+{
+ // i18n: assuming aLocation is encoded for the current locale
+
+ nsresult rv;
+ if (!aLocation || !aSpec)
+ return NS_ERROR_NULL_POINTER;
+
+ /* abs:/full/path/to/libcomponent.so */
+ if (!strncmp(aLocation, XPCOM_ABSCOMPONENT_PREFIX, 4)) {
+
+ nsLocalFile* file = new nsLocalFile;
+ if (!file) return NS_ERROR_FAILURE;
+
+ rv = file->InitWithNativePath(nsDependentCString((char *)aLocation + 4));
+ file->QueryInterface(NS_GET_IID(nsILocalFile), (void**)aSpec);
+ return rv;
+ }
+
+ if (!strncmp(aLocation, XPCOM_RELCOMPONENT_PREFIX, 4)) {
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsILocalFile* file = nsnull;
+ rv = mComponentsDir->Clone((nsIFile**)&file);
+
+ if (NS_FAILED(rv)) return rv;
+
+ rv = file->AppendRelativeNativePath(nsDependentCString(aLocation + 4));
+ *aSpec = file;
+ return rv;
+ }
+
+ if (!strncmp(aLocation, XPCOM_GRECOMPONENT_PREFIX, 4)) {
+
+ if (!mGREComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsILocalFile* file = nsnull;
+ rv = mGREComponentsDir->Clone((nsIFile**)&file);
+
+ if (NS_FAILED(rv)) return rv;
+
+ rv = file->AppendRelativeNativePath(nsDependentCString(aLocation + 4));
+ *aSpec = file;
+ return rv;
+ }
+
+ *aSpec = nsnull;
+ return NS_ERROR_INVALID_ARG;
+}
+
+/**
+ * RegisterFactory()
+ *
+ * Register a factory to be responsible for creation of implementation of
+ * classID aClass. Plus creates as association of aClassName and aContractID
+ * to the classID. If replace is PR_TRUE, we replace any existing registrations
+ * with this one.
+ *
+ * Once registration is complete, we add the class to the factories cache
+ * that we maintain. The factories cache is the ONLY place where these
+ * registrations are ever kept.
+ *
+ * The other RegisterFunctions create a loader mapping and persistent
+ * location, but we just slam it into the cache here. And we don't call the
+ * loader's OnRegister function, either.
+ */
+nsresult
+nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace)
+{
+ nsAutoMonitor mon(mMon);
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: RegisterFactory(%s, %s)", buf,
+ (aContractID ? aContractID : "(null)")));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ nsFactoryEntry *entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry = NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories,
+ &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && !aReplace)
+ {
+ // Already registered
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tFactory already registered."));
+ return NS_ERROR_FACTORY_EXISTS;
+ }
+
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ entry = new (mem) nsFactoryEntry(aClass, aFactory, entry);
+
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+
+ // Update the ContractID->CLSID Map
+ if (aContractID) {
+ nsresult rv = HashContractID(aContractID, strlen(aContractID), entry);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tFactory register succeeded. "
+ "Hashing contractid (%s) FAILED.", aContractID));
+ return rv;
+ }
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tFactory register succeeded contractid=%s.",
+ aContractID ? aContractID : "<none>"));
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ return RegisterComponentCommon(aClass, aClassName,
+ aContractID,
+ aContractID ? strlen(aContractID) : 0,
+ aPersistentDescriptor,
+ aPersistentDescriptor ?
+ strlen(aPersistentDescriptor) : 0,
+ aReplace, aPersist,
+ nativeComponentType);
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponentWithType(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aSpec,
+ const char *aLocation,
+ PRBool aReplace,
+ PRBool aPersist,
+ const char *aType)
+{
+ return RegisterComponentCommon(aClass, aClassName,
+ aContractID,
+ aContractID ? strlen(aContractID) : 0,
+ aLocation,
+ aLocation ? strlen(aLocation) : 0,
+ aReplace, aPersist,
+ aType);
+}
+
+/*
+ * Register a component, using whatever they stuck in the nsIFile.
+ */
+nsresult
+nsComponentManagerImpl::RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrarySpec,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = RegisterComponentWithType(aClass, aClassName,
+ aContractID,
+ aLibrarySpec,
+ registryName,
+ aReplace, aPersist,
+ nativeComponentType);
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aDllName,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ // deprecated and obsolete.
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/*
+ * Add a component to the known universe of components.
+
+ * Once we enter this function, we own aRegistryName, and must free it
+ * or hand it to nsFactoryEntry. Common exit point ``out'' helps keep us
+ * sane.
+ */
+
+nsresult
+nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ PRUint32 aContractIDLen,
+ const char *aRegistryName,
+ PRUint32 aRegistryNameLen,
+ PRBool aReplace,
+ PRBool aPersist,
+ const char *aType)
+{
+ nsIDKey key(aClass);
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ // Normalize proid and classname
+ const char *contractID = (aContractID && *aContractID) ? aContractID : nsnull;
+ const char *className = (aClassName && *aClassName) ? aClassName : nsnull;
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: RegisterComponentCommon(%s, %s, %s, %s)",
+ buf,
+ contractID ? contractID : "(null)",
+ aRegistryName, aType));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ if (entry && !aReplace) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tFactory already registered."));
+ return NS_ERROR_FACTORY_EXISTS;
+ }
+
+ int typeIndex = GetLoaderType(aType);
+
+ nsCOMPtr<nsIComponentLoader> loader;
+ nsresult rv = GetLoaderForType(typeIndex, getter_AddRefs(loader));
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tgetting loader for %s FAILED\n", aType));
+ return rv;
+ }
+
+ if (entry) {
+ entry->ReInit(aClass, aRegistryName, typeIndex);
+ }
+ else {
+
+ // Arena allocate the nsFactoryEntry
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mRegistryDirty = PR_TRUE;
+ entry = new (mem) nsFactoryEntry(aClass,
+ aRegistryName, aRegistryNameLen,
+ typeIndex);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+ }
+
+ // Update the ContractID->CLSID Map
+ if (contractID) {
+ rv = HashContractID(contractID, aContractIDLen, entry);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tHashContractID(%s) FAILED\n", contractID));
+ return rv;
+ }
+ }
+ return rv;
+}
+
+
+nsresult
+nsComponentManagerImpl::GetLoaderForType(int aType,
+ nsIComponentLoader **aLoader)
+{
+ nsresult rv;
+
+ // Make sure we have a valid type
+ if (aType < 0 || aType >= mNLoaderData)
+ return NS_ERROR_INVALID_ARG;
+
+ *aLoader = mLoaderData[aType].loader;
+ if (*aLoader) {
+ NS_ADDREF(*aLoader);
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIComponentLoader> loader;
+ loader = do_GetServiceFromCategory("component-loader", mLoaderData[aType].type, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = loader->Init(this, nsnull);
+
+ if (NS_SUCCEEDED(rv)) {
+ mLoaderData[aType].loader = loader;
+ NS_ADDREF(mLoaderData[aType].loader);
+ *aLoader = loader;
+ NS_ADDREF(*aLoader);
+ }
+ return rv;
+}
+
+
+
+// Convert a loader type string into an index into the component data
+// array. Empty loader types are converted to NATIVE. Returns -1 if
+// loader type cannot be determined.
+int
+nsComponentManagerImpl::GetLoaderType(const char *typeStr)
+{
+ if (!typeStr || !*typeStr) {
+ // Empty type strings are NATIVE
+ return NS_COMPONENT_TYPE_NATIVE;
+ }
+
+ for (int i=NS_COMPONENT_TYPE_NATIVE; i<mNLoaderData; i++) {
+ if (!strcmp(typeStr, mLoaderData[i].type))
+ return i;
+ }
+ // Not found
+ return NS_COMPONENT_TYPE_FACTORY_ONLY;
+}
+
+// Add a loader type if not already known. Out the typeIndex
+// if the loader type is either added or already there.
+nsresult
+nsComponentManagerImpl::AddLoaderType(const char *typeStr, int *aTypeIndex)
+{
+ int typeIndex = GetLoaderType(typeStr);
+ if (typeIndex >= 0) {
+ *aTypeIndex = typeIndex;
+ return NS_OK;
+ }
+
+ // Add the loader type
+ if (mNLoaderData >= mMaxNLoaderData) {
+ NS_ASSERTION(mNLoaderData == mMaxNLoaderData,
+ "Memory corruption. nsComponentManagerImpl::mLoaderData array overrun.");
+ // Need to increase our loader array
+ nsLoaderdata *new_mLoaderData = (nsLoaderdata *) PR_Realloc(mLoaderData, (mMaxNLoaderData + NS_LOADER_DATA_ALLOC_STEP) * sizeof(nsLoaderdata));
+ if (!new_mLoaderData)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mLoaderData = new_mLoaderData;
+ mMaxNLoaderData += NS_LOADER_DATA_ALLOC_STEP;
+ }
+
+ typeIndex = mNLoaderData;
+ mLoaderData[typeIndex].type = PL_strdup(typeStr);
+ if (!mLoaderData[typeIndex].type) {
+ // mmh! no memory. return failure.
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mLoaderData[typeIndex].loader = nsnull;
+ mNLoaderData++;
+
+ *aTypeIndex = typeIndex;
+ return NS_OK;
+}
+
+typedef struct
+{
+ const nsCID* cid;
+ const char* regName;
+ nsIFactory* factory;
+} UnregisterConditions;
+
+static PLDHashOperator PR_CALLBACK
+DeleteFoundCIDs(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ UnregisterConditions* data = (UnregisterConditions*)aData;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ if (data->cid->Equals(factoryEntry->mCid) &&
+ ((data->regName && !PL_strcasecmp(factoryEntry->mLocation, data->regName)) ||
+ (data->factory && data->factory == factoryEntry->mFactory.get())))
+ return PL_DHASH_REMOVE;
+
+ return PL_DHASH_NEXT;
+}
+
+void
+nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, const char*registryName)
+{
+ UnregisterConditions aData;
+ aData.cid = aClass;
+ aData.regName = registryName;
+ aData.factory = nsnull;
+ PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
+
+}
+
+void
+nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory)
+{
+ UnregisterConditions aData;
+ aData.cid = aClass;
+ aData.regName = nsnull;
+ aData.factory = factory;
+ PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory)
+{
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: UnregisterFactory(%s)", buf));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ nsFactoryEntry *old;
+
+ // first delete all contract id entries that are registered with this cid.
+ DeleteContractIDEntriesByCID(&aClass, aFactory);
+
+ // next check to see if there is a CID registered
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ old = GetFactoryEntry(aClass);
+
+ if (old && (old->mFactory.get() == aFactory))
+ {
+ nsAutoMonitor mon(mMon);
+ PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
+ rv = NS_OK;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tUnregisterFactory() %s",
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
+ const char *registryName)
+{
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: UnregisterComponent(%s)", buf));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ NS_ENSURE_ARG_POINTER(registryName);
+ nsFactoryEntry *old;
+
+ // first delete all contract id entries that are registered with this cid.
+ DeleteContractIDEntriesByCID(&aClass, registryName);
+
+ // next check to see if there is a CID registered
+ old = GetFactoryEntry(aClass);
+ if (old && old->mLocation && !PL_strcasecmp(old->mLocation, registryName))
+ {
+ nsAutoMonitor mon(mMon);
+ PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: Factory unregister(%s) succeeded.", registryName));
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
+ if (NS_FAILED(rv)) return rv;
+ return UnregisterComponent(aClass, registryName);
+}
+
+// XXX Need to pass in aWhen and servicemanager
+nsresult
+nsComponentManagerImpl::FreeLibraries(void)
+{
+ return UnloadLibraries(NS_STATIC_CAST(nsIServiceManager*, this), NS_Timer); // XXX when
+}
+
+// Private implementation of unloading libraries
+nsresult
+nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 aWhen)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoMonitor mon(mMon);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: Unloading Libraries."));
+
+ // UnloadAll the loaders
+ /* iterate over all known loaders and ask them to autoregister. */
+ // Skip mNativeComponentLoader
+ for (int i=NS_COMPONENT_TYPE_NATIVE + 1; i<mNLoaderData; i++) {
+ if (mLoaderData[i].loader) {
+ rv = mLoaderData[i].loader->UnloadAll(aWhen);
+ if (NS_FAILED(rv))
+ break;
+ }
+ }
+
+ // UnloadAll the native loader
+ rv = mNativeComponentLoader->UnloadAll(aWhen);
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * AutoRegister(RegistrationInstant, const char *directory)
+ *
+ * Given a directory in the following format, this will ensure proper registration
+ * of all components. No default directory is looked at.
+ *
+ * Directory and fullname are what NSPR will accept. For eg.
+ * WIN y:/home/dp/mozilla/dist/bin
+ * UNIX /home/dp/mozilla/dist/bin
+ * MAC /Hard drive/mozilla/dist/apprunner
+ *
+ * This will take care not loading already registered dlls, finding and
+ * registering new dlls, re-registration of modified dlls
+ *
+ */
+
+nsresult
+nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
+{
+ return AutoRegisterImpl(when, inDirSpec);
+}
+
+nsresult
+nsComponentManagerImpl::AutoRegisterImpl(PRInt32 when,
+ nsIFile *inDirSpec,
+ PRBool fileIsCompDir)
+{
+ nsCOMPtr<nsIFile> dir;
+ nsresult rv;
+
+#ifdef DEBUG
+ // testing release behaviour
+ if (getenv("XPCOM_NO_AUTOREG"))
+ return NS_OK;
+#endif
+ if (inDirSpec)
+ {
+ // Use supplied components' directory
+ dir = inDirSpec;
+ }
+ else
+ {
+ mComponentsDir->Clone(getter_AddRefs(dir));
+ if (!dir)
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim =
+ dont_AddRef(XPTI_GetInterfaceInfoManager());
+
+ if (!iim)
+ return NS_ERROR_UNEXPECTED;
+
+ // Notify observers of xpcom autoregistration start
+ NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ nsnull,
+ "start");
+
+ /* do the native loader first, so we can find other loaders */
+ rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ rv = mStaticComponentLoader->AutoRegisterComponents((PRInt32)when, inDirSpec);
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ /* do InterfaceInfoManager after native loader so it can use components. */
+ rv = iim->AutoRegisterInterfaces();
+ if (NS_FAILED(rv)) return rv;
+
+ if (!mCategoryManager) {
+ NS_WARNING("mCategoryManager is null");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> loaderEnum;
+ rv = mCategoryManager->EnumerateCategory("component-loader",
+ getter_AddRefs(loaderEnum));
+ if (NS_FAILED(rv)) return rv;
+
+ PRBool hasMore;
+ while (NS_SUCCEEDED(loaderEnum->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> supports;
+ if (NS_FAILED(loaderEnum->GetNext(getter_AddRefs(supports))))
+ continue;
+
+ nsCOMPtr<nsISupportsCString> supStr = do_QueryInterface(supports);
+ if (!supStr)
+ continue;
+
+ nsCAutoString loaderType;
+ if (NS_FAILED(supStr->GetData(loaderType)))
+ continue;
+
+ // We depend on the loader being created. Add the loader type and
+ // create the loader object too.
+ nsCOMPtr<nsIComponentLoader> loader;
+ int typeIndex;
+ rv = AddLoaderType(loaderType.get(), &typeIndex);
+ if (NS_FAILED(rv))
+ return rv;
+ GetLoaderForType(typeIndex, getter_AddRefs(loader));
+ }
+
+ rv = AutoRegisterNonNativeComponents(dir.get());
+
+ // Notify observers of xpcom autoregistration completion
+ NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ nsnull,
+ "end");
+
+ if (mRegistryDirty)
+ FlushPersistentStore(PR_TRUE);
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::AutoRegisterNonNativeComponents(nsIFile* spec)
+{
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIFile> directory = spec;
+
+ if (!directory) {
+ mComponentsDir->Clone(getter_AddRefs(directory));
+ if (!directory)
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ for (int i = 1; i < mNLoaderData; i++) {
+ if (!mLoaderData[i].loader) {
+ rv = GetLoaderForType(i, &mLoaderData[i].loader);
+ if (NS_FAILED(rv))
+ continue;
+ }
+ rv = mLoaderData[i].loader->AutoRegisterComponents(0, directory);
+ if (NS_FAILED(rv))
+ break;
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ PRBool registered;
+ do {
+ registered = PR_FALSE;
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool b = PR_FALSE;
+ if (mLoaderData[i].loader) {
+ rv = mLoaderData[i].loader->RegisterDeferredComponents(0, &b);
+ if (NS_FAILED(rv))
+ continue;
+ registered |= b;
+ }
+ }
+ } while (NS_SUCCEEDED(rv) && registered);
+ }
+ return rv;
+}
+nsresult
+nsComponentManagerImpl::AutoRegisterComponent(PRInt32 when,
+ nsIFile *component)
+{
+ nsresult rv = NS_OK, res = NS_ERROR_FACTORY_NOT_REGISTERED;
+ /*
+ * Do we have to give the native loader first crack at it?
+ * I vote ``no''.
+ */
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool didRegister;
+ if (!mLoaderData[i].loader) {
+ nsCOMPtr<nsIComponentLoader> loader;
+ rv = GetLoaderForType(i, getter_AddRefs(loader));
+ if (NS_FAILED(rv))
+ continue;
+ // |GetLoaderForType| has filled in |mLoaderData[i].loader|:
+ NS_ASSERTION(loader == mLoaderData[i].loader, "oops");
+ }
+ rv = mLoaderData[i].loader->AutoRegisterComponent((int)when, component, &didRegister);
+ if (NS_FAILED(rv)) {
+ res = rv;
+ } else if (didRegister) {
+ return rv;
+ }
+ }
+ return res;
+}
+
+nsresult
+nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component)
+{
+ nsresult rv = NS_OK;
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool didUnRegister;
+ if (!mLoaderData[i].loader) {
+ rv = GetLoaderForType(i, &mLoaderData[i].loader);
+ if (NS_FAILED(rv))
+ continue;
+ }
+ rv = mLoaderData[i].loader->AutoUnregisterComponent(when, component, &didUnRegister);
+ if (NS_SUCCEEDED(rv) && didUnRegister) {
+ // we need to remove this file from our list of known libraries.
+ RemoveFileInfo(component, nsnull);
+ mRegistryDirty = PR_TRUE;
+ break;
+ }
+ }
+ return NS_FAILED(rv) ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered)
+{
+ if (!aRegistered)
+ {
+ NS_ASSERTION(0, "null ptr");
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aRegistered = (nsnull != GetFactoryEntry(aClass));
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mFactories,
+ ConvertFactoryEntryToCID,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::EnumerateContractIDs(nsIEnumerator** aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mContractIDs,
+ ConvertContractIDKeyToString,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
+ return NS_OK;
+}
+
+// nsIComponentRegistrar
+
+NS_IMETHODIMP
+nsComponentManagerImpl::AutoRegister(nsIFile *aSpec)
+{
+ if (aSpec == nsnull)
+ return AutoRegisterImpl(0, aSpec);
+
+ PRBool directory;
+ aSpec->IsDirectory(&directory);
+
+ if (directory)
+ return AutoRegisterImpl(0, aSpec, PR_FALSE);
+
+ return AutoRegisterComponent(0, aSpec);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::AutoUnregister(nsIFile *aSpec)
+{
+ // unregistering a complete directory is not implmeneted yet...FIX
+ if (aSpec == nsnull)
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+ PRBool directory;
+ aSpec->IsDirectory(&directory);
+
+ if (directory)
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+ return AutoUnregisterComponent(0, aSpec);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterFactory(const nsCID & aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory)
+{
+ return RegisterFactory(aClass,
+ aClassName,
+ aContractID,
+ aFactory,
+ PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterFactoryLocation(const nsCID & aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aFile,
+ const char *loaderStr,
+ const char *aType)
+{
+ nsXPIDLCString registryName;
+
+ if (!loaderStr)
+ {
+ nsresult rv = RegistryLocationForSpec(aFile, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ nsresult rv;
+ rv = RegisterComponentWithType(aClass,
+ aClassName,
+ aContractID,
+ aFile,
+ (loaderStr ? loaderStr : registryName.get()),
+ PR_TRUE,
+ PR_TRUE,
+ (aType ? aType : nativeComponentType));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID & aClass,
+ nsIFile *aFile)
+{
+ return UnregisterComponentSpec(aClass, aFile);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
+ PRBool *_retval)
+{
+ return IsRegistered(aClass, _retval);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsContractIDRegistered(const char *aClass,
+ PRBool *_retval)
+{
+ nsFactoryEntry *entry = GetFactoryEntry(aClass, strlen(aClass));
+
+ if (entry)
+ *_retval = PR_TRUE;
+ else
+ *_retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+
+ if (!aEnumerator)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mFactories,
+ ConvertFactoryEntryToCID,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mContractIDs,
+ ConvertContractIDKeyToString,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::CIDToContractID(const nsCID & aClass,
+ char **_retval)
+{
+ return CLSIDToContractID(aClass,
+ nsnull,
+ _retval);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
+ nsCID * *_retval)
+{
+ *_retval = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = ContractIDToClassID(aContractID, *_retval);
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(*_retval);
+ *_retval = nsnull;
+ }
+ return rv;
+}
+
+// end nsIComponentRegistrar
+
+
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::HasFileChanged(nsIFile *file, const char *loaderString, PRInt64 modDate, PRBool *_retval)
+{
+ *_retval = PR_TRUE;
+
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+ if (entry)
+ *_retval = entry->Modified(&modDate);
+ else
+ *_retval = PR_TRUE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::SaveFileInfo(nsIFile *file, const char *loaderString, PRInt64 modDate)
+{
+ mRegistryDirty = PR_TRUE;
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // check to see if exists in the array before adding it so that we don't have dups.
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+
+ if (entry)
+ {
+ entry->SetDate(&modDate);
+ return NS_OK;
+ }
+
+ entry = new AutoRegEntry(registryName, &modDate);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAutoRegEntries.Put(&key, entry);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RemoveFileInfo(nsIFile *file, const char *loaderString)
+{
+ mRegistryDirty = PR_TRUE;
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Remove(&key);
+ if (entry)
+ delete entry;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetOptionalData(nsIFile *file,
+ const char *loaderString,
+ char **_retval)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+ if (!entry) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ const char* opData = entry->GetOptionalData();
+
+ if (opData)
+ *_retval = ToNewCString(nsDependentCString(opData));
+ else
+ *_retval = nsnull;
+ return NS_OK;
+ }
+
+NS_IMETHODIMP
+nsComponentManagerImpl::SetOptionalData(nsIFile *file,
+ const char *loaderString,
+ const char *data)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+
+ if (!entry) {
+ PRInt64 zero = LL_Zero();
+ entry = new AutoRegEntry(registryName, &zero);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAutoRegEntries.Put(&key, entry);
+ }
+
+ entry->SetOptionalData(data);
+
+ return NS_OK;
+ }
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::FlushPersistentStore(PRBool now)
+{
+ mRegistryDirty = PR_TRUE;
+ if (now)
+ return WritePersistentRegistry();
+
+ return NS_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Static Access Functions
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_GetGlobalComponentManager(nsIComponentManager* *result)
+{
+#ifdef DEBUG_dougt
+ // NS_WARNING("DEPRECATED FUNCTION: Use NS_GetComponentManager");
+#endif
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ // NO ADDREF since this is never intended to be released.
+ // See nsComponentManagerObsolete.h for the reason for such
+ // casting uglyness
+ *result = (nsIComponentManager*)(void*)(nsIComponentManagerObsolete*) nsComponentManagerImpl::gComponentManager;
+ }
+
+ return rv;
+}
+
+NS_COM nsresult
+NS_GetComponentManager(nsIComponentManager* *result)
+{
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ *result = NS_STATIC_CAST(nsIComponentManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_GetServiceManager(nsIServiceManager* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+#ifdef VBOX
+ // While XPCOM might need initialization, we're not in a position
+ // to pass the right values to this call. This is actually triggered
+ // on object destruction, so there is no point in re-initializing,
+ // and actually the attempt would lead to nested calls to
+ // xptiInterfaceInfoManager::BuildFileSearchPath, which it detects
+ // as unsafe in debug builds. Just fail, no real problem.
+#ifdef DEBUG
+ printf("NS_GetServiceManager: no current instance, suppressed XPCOM initialization!\n");
+#endif
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+#else /* !VBOX */
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+#endif /* !VBOX */
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIServiceManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+
+NS_COM nsresult
+NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIComponentRegistrar*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+
+// nsIComponentLoaderManager is not frozen, but is defined here
+// so that I can use it internally in xpcom.
+nsresult
+NS_GetComponentLoaderManager(nsIComponentLoaderManager* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == NULL)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIComponentLoaderManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h
new file mode 100644
index 00000000..df128125
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h
@@ -0,0 +1,339 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsComponentManager_h__
+#define nsComponentManager_h__
+
+#include "nsXPCOM.h"
+
+#include "nsIComponentLoader.h"
+#include "xpcom-private.h"
+#include "nsNativeComponentLoader.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManagerObsolete.h"
+#include "nsIComponentLoaderManager.h"
+#include "nsCategoryManager.h"
+#include "nsIServiceManager.h"
+#include "nsIFactory.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "pldhash.h"
+#include "prtime.h"
+#include "prmon.h"
+#include "nsCOMPtr.h"
+#include "nsWeakReference.h"
+#include "nsXPIDLString.h"
+#include "nsIFile.h"
+#include "plarena.h"
+
+class nsFactoryEntry;
+class nsDll;
+class nsIServiceManager;
+
+
+// Predefined loader types. Do not change the numbers.
+// NATIVE should be 0 as it is being used as the first array index.
+#define NS_COMPONENT_TYPE_NATIVE 0
+#define NS_COMPONENT_TYPE_FACTORY_ONLY -1
+// this define means that the factory entry only has a ContractID
+// to service mapping and has no cid mapping.
+#define NS_COMPONENT_TYPE_SERVICE_ONLY -2
+
+
+#ifdef DEBUG
+#define XPCOM_CHECK_PENDING_CIDS
+#endif
+////////////////////////////////////////////////////////////////////////////////
+
+// Array of Loaders and their type strings
+struct nsLoaderdata {
+ nsIComponentLoader *loader;
+ const char *type;
+};
+
+class nsComponentManagerImpl
+ : public nsIComponentManager,
+ public nsIServiceManager,
+ public nsIComponentRegistrar,
+ public nsSupportsWeakReference,
+ public nsIInterfaceRequestor,
+ public nsIComponentLoaderManager,
+ public nsIServiceManagerObsolete,
+ public nsIComponentManagerObsolete
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEREQUESTOR
+ // Since the nsIComponentManagerObsolete and nsIComponentManager share some of the
+ // same interface function names, we have to manually define the functions here.
+ // The only function that is in nsIComponentManagerObsolete and is in nsIComponentManager
+ // is GetClassObjectContractID.
+ //
+ // nsIComponentManager function not in nsIComponentManagerObsolete:
+ NS_IMETHOD GetClassObjectByContractID(const char *aContractID,
+ const nsIID &aIID,
+ void **_retval);
+
+
+ NS_DECL_NSICOMPONENTMANAGEROBSOLETE
+
+ // Since the nsIComponentManagerObsolete and nsIComponentRegistrar share some of the
+ // same interface function names, we have to manually define the functions here.
+ // the only function that is shared is UnregisterFactory
+ NS_IMETHOD AutoRegister(nsIFile *aSpec);
+ NS_IMETHOD AutoUnregister(nsIFile *aSpec);
+ NS_IMETHOD RegisterFactory(const nsCID & aClass, const char *aClassName, const char *aContractID, nsIFactory *aFactory);
+ // NS_IMETHOD UnregisterFactory(const nsCID & aClass, nsIFactory *aFactory);
+ NS_IMETHOD RegisterFactoryLocation(const nsCID & aClass, const char *aClassName, const char *aContractID, nsIFile *aFile, const char *loaderStr, const char *aType);
+ NS_IMETHOD UnregisterFactoryLocation(const nsCID & aClass, nsIFile *aFile);
+ NS_IMETHOD IsCIDRegistered(const nsCID & aClass, PRBool *_retval);
+ NS_IMETHOD IsContractIDRegistered(const char *aClass, PRBool *_retval);
+ NS_IMETHOD EnumerateCIDs(nsISimpleEnumerator **_retval);
+ NS_IMETHOD EnumerateContractIDs(nsISimpleEnumerator **_retval);
+ NS_IMETHOD CIDToContractID(const nsCID & aClass, char **_retval);
+ NS_IMETHOD ContractIDToCID(const char *aContractID, nsCID * *_retval);
+
+ NS_DECL_NSISERVICEMANAGER
+ NS_DECL_NSISERVICEMANAGEROBSOLETE
+ NS_DECL_NSICOMPONENTLOADERMANAGER
+
+ // nsComponentManagerImpl methods:
+ nsComponentManagerImpl();
+
+ static nsComponentManagerImpl* gComponentManager;
+ nsresult Init(void);
+
+ nsresult WritePersistentRegistry();
+ nsresult ReadPersistentRegistry();
+
+ nsresult Shutdown(void);
+
+ nsresult FreeServices();
+
+ nsresult
+ NS_GetService(const char *aContractID, const nsIID& aIID, PRBool aDontCreate, nsISupports** result);
+
+ nsresult RegisterComponentCommon(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ PRUint32 aContractIDLen,
+ const char *aRegistryName,
+ PRUint32 aRegistryNameLen,
+ PRBool aReplace, PRBool aPersist,
+ const char *aType);
+ nsresult GetLoaderForType(int aType,
+ nsIComponentLoader **aLoader);
+ nsresult FindFactory(const char *contractID, PRUint32 aContractIDLen, nsIFactory **aFactory) ;
+ nsresult LoadFactory(nsFactoryEntry *aEntry, nsIFactory **aFactory);
+
+ nsFactoryEntry *GetFactoryEntry(const char *aContractID,
+ PRUint32 aContractIDLen);
+ nsFactoryEntry *GetFactoryEntry(const nsCID &aClass);
+
+ nsresult SyncComponentsInDir(PRInt32 when, nsIFile *dirSpec);
+ nsresult SelfRegisterDll(nsDll *dll);
+ nsresult SelfUnregisterDll(nsDll *dll);
+ nsresult HashContractID(const char *acontractID, PRUint32 aContractIDLen,
+ nsFactoryEntry *fe_ptr);
+
+ void DeleteContractIDEntriesByCID(const nsCID* aClass, const char*registryName);
+ void DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory);
+
+ nsresult UnloadLibraries(nsIServiceManager *servmgr, PRInt32 when);
+
+ // Convert a loader type string into an index into the loader data
+ // array. Empty loader types are converted to NATIVE. Returns -1 if
+ // loader type cannot be determined.
+ int GetLoaderType(const char *typeStr);
+
+ // Add a loader type if not already known. Out the typeIndex
+ // if the loader type is either added or already there;
+ // returns NS_OK or an error on failure.
+ nsresult AddLoaderType(const char *typeStr, int *typeIndex);
+
+ int GetLoaderCount() { return mNLoaderData + 1; }
+
+ // registers only the files in spec's location by loaders other than the
+ // native loader. This is an optimization method only.
+ nsresult AutoRegisterNonNativeComponents(nsIFile* spec);
+
+ nsresult AutoRegisterImpl(PRInt32 when, nsIFile *inDirSpec, PRBool fileIsCompDir=PR_TRUE);
+ nsresult RemoveEntries(nsIFile* file);
+
+ PLDHashTable mFactories;
+ PLDHashTable mContractIDs;
+ PRMonitor* mMon;
+
+ nsNativeComponentLoader *mNativeComponentLoader;
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ nsIComponentLoader *mStaticComponentLoader;
+#endif
+ nsCOMPtr<nsIFile> mComponentsDir;
+ PRInt32 mComponentsOffset;
+
+ nsCOMPtr<nsIFile> mGREComponentsDir;
+ PRInt32 mGREComponentsOffset;
+
+ nsCOMPtr<nsIFile> mRegistryFile;
+
+ // Shutdown
+ #define NS_SHUTDOWN_NEVERHAPPENED 0
+ #define NS_SHUTDOWN_INPROGRESS 1
+ #define NS_SHUTDOWN_COMPLETE 2
+ PRUint32 mShuttingDown;
+
+ nsLoaderdata *mLoaderData;
+ int mNLoaderData;
+ int mMaxNLoaderData;
+
+ PRBool mRegistryDirty;
+ nsHashtable mAutoRegEntries;
+ nsCOMPtr<nsCategoryManager> mCategoryManager;
+
+ PLArenaPool mArena;
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ nsresult AddPendingCID(const nsCID &aClass);
+ void RemovePendingCID(const nsCID &aClass);
+
+ nsVoidArray mPendingCIDs;
+#endif
+
+private:
+ ~nsComponentManagerImpl();
+};
+
+
+#define NS_MAX_FILENAME_LEN 1024
+
+#define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24)
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Class: nsFactoryEntry()
+ *
+ * There are two types of FactoryEntries.
+ *
+ * 1. {CID, dll} mapping.
+ * Factory is a consequence of the dll. These can be either session
+ * specific or persistent based on whether we write this
+ * to the registry or not.
+ *
+ * 2. {CID, factory} mapping
+ * These are strictly session specific and in memory only.
+ */
+
+class nsFactoryEntry {
+public:
+ nsFactoryEntry(const nsCID &aClass,
+ const char *location, PRUint32 locationlen, int aType, class nsFactoryEntry* parent = nsnull);
+ nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory, class nsFactoryEntry* parent = nsnull);
+ ~nsFactoryEntry();
+
+ nsresult ReInit(const nsCID &aClass, const char *location, int aType);
+
+ nsresult GetFactory(nsIFactory **aFactory,
+ nsComponentManagerImpl * mgr) {
+ if (mFactory) {
+ *aFactory = mFactory.get();
+ NS_ADDREF(*aFactory);
+ return NS_OK;
+ }
+
+ if (mTypeIndex < 0)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ nsCOMPtr<nsIComponentLoader> loader;
+ rv = mgr->GetLoaderForType(mTypeIndex, getter_AddRefs(loader));
+ if(NS_FAILED(rv))
+ return rv;
+
+ rv = loader->GetFactory(mCid, mLocation, mgr->mLoaderData[mTypeIndex].type, aFactory);
+ if (NS_SUCCEEDED(rv))
+ mFactory = do_QueryInterface(*aFactory);
+ return rv;
+ }
+
+ nsCID mCid;
+ nsCOMPtr<nsIFactory> mFactory;
+ // This is an index into the mLoaderData array that holds the type string and the loader
+ int mTypeIndex;
+ nsCOMPtr<nsISupports> mServiceObject;
+ char* mLocation;
+ class nsFactoryEntry* mParent;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct nsFactoryTableEntry : public PLDHashEntryHdr {
+ nsFactoryEntry *mFactoryEntry;
+};
+
+struct nsContractIDTableEntry : public PLDHashEntryHdr {
+ char *mContractID;
+ PRUint32 mContractIDLen;
+ nsFactoryEntry *mFactoryEntry;
+};
+
+
+class AutoRegEntry
+{
+public:
+ AutoRegEntry(const nsACString& name, PRInt64* modDate);
+ ~AutoRegEntry();
+
+ const nsDependentCString GetName()
+ { return nsDependentCString(mName, mNameLen); }
+ PRInt64 GetDate() {return mModDate;}
+ void SetDate(PRInt64 *date) { mModDate = *date;}
+ PRBool Modified(PRInt64 *date);
+
+ // this is the optional field line in the compreg.dat.
+ // it must not contain any comma's and it must be null terminated.
+ char* GetOptionalData() {return mData;};
+ void SetOptionalData(const char* data);
+
+private:
+ char* mName;
+ PRUint32 mNameLen;
+ char* mData;
+ PRInt64 mModDate;
+};
+#endif // nsComponentManager_h__
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp
new file mode 100644
index 00000000..fca77cf7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp
@@ -0,0 +1,271 @@
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+////////////////////////////////////////////////////////////////////////////////
+// Global Static Component Manager Methods
+// (for when you need to link with xpcom)
+
+#include "nsIComponentManagerObsolete.h"
+#include "nsComponentManagerObsolete.h"
+
+
+nsresult
+nsComponentManager::Initialize(void)
+{
+ return NS_OK;
+}
+
+nsresult
+nsComponentManager::FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->FindFactory(aClass, aFactory);
+}
+
+nsresult
+nsComponentManager::GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->GetClassObject(aClass, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::ContractIDToClassID(const char *aContractID,
+ nsCID *aClass)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->ContractIDToClassID(aContractID, aClass);
+}
+
+nsresult
+nsComponentManager::CLSIDToContractID(nsCID *aClass,
+ char* *aClassName,
+ char* *aContractID)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CLSIDToContractID(*aClass, aClassName, aContractID);
+}
+
+nsresult
+nsComponentManager::CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CreateInstance(aClass, aDelegate, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::CreateInstance(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CreateInstanceByContractID(aContractID, aDelegate, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterFactory(aClass, aClassName, aContractID,
+ aFactory, aReplace);
+}
+
+nsresult
+nsComponentManager::RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLibraryPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponent(aClass, aClassName, aContractID,
+ aLibraryPersistentDescriptor, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrary,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponentSpec(aClass, aClassName, aContractID,
+ aLibrary, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *adllName,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponentLib(aClass, aClassName, aContractID,
+ adllName, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterFactory(aClass, aFactory);
+}
+
+nsresult
+nsComponentManager::UnregisterComponent(const nsCID &aClass,
+ const char *aLibrary)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterComponent(aClass, aLibrary);
+}
+
+nsresult
+nsComponentManager::UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterComponentSpec(aClass, aLibrarySpec);
+}
+
+nsresult
+nsComponentManager::FreeLibraries(void)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->FreeLibraries();
+}
+
+nsresult
+nsComponentManager::AutoRegister(PRInt32 when, nsIFile *directory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoRegister(when, directory);
+}
+
+nsresult
+nsComponentManager::AutoRegisterComponent(PRInt32 when,
+ nsIFile *fullname)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoRegisterComponent(when, fullname);
+}
+
+nsresult
+nsComponentManager::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *fullname)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoUnregisterComponent(when, fullname);
+}
+
+nsresult
+nsComponentManager::IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->IsRegistered(aClass, aRegistered);
+}
+
+nsresult
+nsComponentManager::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->EnumerateCLSIDs(aEnumerator);
+}
+
+nsresult
+nsComponentManager::EnumerateContractIDs(nsIEnumerator** aEnumerator)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->EnumerateContractIDs(aEnumerator);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h
new file mode 100644
index 00000000..dfcde87a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsComponentManagerObsolete_h___
+#define nsComponentManagerObsolete_h___
+
+#include "nsIComponentManager.h"
+#include "nsIComponentManagerObsolete.h"
+
+class nsIEnumerator;
+class nsIFactory;
+class nsIFile;
+////////////////////////////////////////////////////////////////////
+//
+// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+//
+// Functions, classes, interfaces and types in this file are
+// obsolete. Use at your own risk.
+// Please see nsIComponentManager.idl for the supported interface
+// to the component manager.
+//
+////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////////////
+// God save me from this evilness. Below is a very bad
+// function. Its out var is really a nsIComponentManagerObsolete
+// but it has been cast to a nsIComponentManager.
+// The reason for such uglyness is that this function is require for
+// backward compatiblity of some plugins. This funciton will
+// be removed at some point.
+////////////////////////////////////////////////////////////////////
+
+extern NS_COM nsresult
+NS_GetGlobalComponentManager(nsIComponentManager* *result);
+
+
+
+
+class NS_COM nsComponentManager {
+public:
+ static nsresult Initialize(void);
+
+ // Finds a factory for a specific class ID
+ static nsresult FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory);
+
+ // Get the singleton class object that implements the CID aClass
+ static nsresult GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult);
+
+ // Finds a class ID for a specific Program ID
+ static nsresult ContractIDToClassID(const char *aContractID,
+ nsCID *aClass);
+
+ // Finds a Program ID for a specific class ID
+ // caller frees the result with delete[]
+ static nsresult CLSIDToContractID(nsCID *aClass,
+ char* *aClassName,
+ char* *aContractID);
+
+ // Creates a class instance for a specific class ID
+ static nsresult CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ // Convenience routine, creates a class instance for a specific ContractID
+ static nsresult CreateInstance(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ // Manually registry a factory for a class
+ static nsresult RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace);
+
+ // Manually register a dynamically loaded component.
+ // The libraryPersistentDescriptor is what gets passed to the library
+ // self register function from ComponentManager. The format of this string
+ // is the same as nsIFile::GetPath()
+ //
+ // This function will go away in favour of RegisterComponentSpec. In fact,
+ // it internally turns around and calls RegisterComponentSpec.
+ static nsresult RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLibraryPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist);
+
+ // Register a component using its FileSpec as its identification
+ // This is the more prevalent use.
+ static nsresult RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrary,
+ PRBool aReplace,
+ PRBool aPersist);
+
+ // Register a component using its dllName. This could be a dll name with
+ // no path so that LD_LIBRARY_PATH on unix or PATH on win can load it. Or
+ // this could be a code fragment name on the Mac.
+ static nsresult RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *adllName,
+ PRBool aReplace,
+ PRBool aPersist);
+
+
+ // Manually unregister a factory for a class
+ static nsresult UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory);
+
+ // Manually unregister a dynamically loaded component
+ static nsresult UnregisterComponent(const nsCID &aClass,
+ const char *aLibrary);
+
+ // Manually unregister a dynamically loaded component
+ static nsresult UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec);
+
+ // Unload dynamically loaded factories that are not in use
+ static nsresult FreeLibraries(void);
+ //////////////////////////////////////////////////////////////////////////////
+ // DLL registration support
+
+ // If directory is NULL, then AutoRegister will try registering components
+ // in the default components directory.
+ static nsresult AutoRegister(PRInt32 when, nsIFile* directory);
+ static nsresult AutoRegisterComponent(PRInt32 when, nsIFile *component);
+ static nsresult AutoUnregisterComponent(PRInt32 when, nsIFile *component);
+
+ // Is the given CID currently registered?
+ static nsresult IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered);
+
+ // Get an enumeration of all the CIDs
+ static nsresult EnumerateCLSIDs(nsIEnumerator** aEmumerator);
+
+ // Get an enumeration of all the ContractIDs
+ static nsresult EnumerateContractIDs(nsIEnumerator** aEmumerator);
+
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h
new file mode 100644
index 00000000..cda56416
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsComponentManagerUtils_h__
+#define nsComponentManagerUtils_h__
+
+/*
+ * Do not include this file directly. Instead,
+ * |#include "nsIComponentManager.h"|.
+ */
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+#ifndef nsComponentManagerObsolete_h___
+#include "nsComponentManagerObsolete.h"
+#endif
+
+#define NS_COMPONENTMANAGER_CID \
+{ /* 91775d60-d5dc-11d2-92fb-00e09805570f */ \
+ 0x91775d60, \
+ 0xd5dc, \
+ 0x11d2, \
+ {0x92, 0xfb, 0x00, 0xe0, 0x98, 0x05, 0x57, 0x0f} \
+}
+
+class NS_COM nsCreateInstanceByCID : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceByCID( const nsCID& aCID, nsISupports* aOuter, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mOuter(aOuter),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+private:
+ const nsCID& mCID;
+ nsISupports* mOuter;
+ nsresult* mErrorPtr;
+};
+
+class NS_COM nsCreateInstanceByContractID : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceByContractID( const char* aContractID, nsISupports* aOuter, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mOuter(aOuter),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+private:
+ const char* mContractID;
+ nsISupports* mOuter;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsCreateInstanceByCID
+do_CreateInstance( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsCreateInstanceByCID(aCID, 0, error);
+}
+
+inline
+const nsCreateInstanceByCID
+do_CreateInstance( const nsCID& aCID, nsISupports* aOuter, nsresult* error = 0 )
+{
+ return nsCreateInstanceByCID(aCID, aOuter, error);
+}
+
+inline
+const nsCreateInstanceByContractID
+do_CreateInstance( const char* aContractID, nsresult* error = 0 )
+{
+ return nsCreateInstanceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsCreateInstanceByContractID
+do_CreateInstance( const char* aContractID, nsISupports* aOuter, nsresult* error = 0 )
+{
+ return nsCreateInstanceByContractID(aContractID, aOuter, error);
+}
+
+// type-safe shortcuts for calling |CreateInstance|
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const nsCID &aClass,
+ nsISupports *aDelegate,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aClass, aDelegate,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const nsCID &aClass,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aClass, nsnull,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const char *aContractID,
+ nsISupports *aDelegate,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aContractID,
+ aDelegate,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const char *aContractID,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aContractID, nsnull,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+/* 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[];
+
+#endif /* nsComponentManagerUtils_h__ */
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl b/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl
new file mode 100644
index 00000000..509f7870
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsISimpleEnumerator.idl"
+
+/*
+ * nsICategoryManager
+ * @status FROZEN
+ */
+
+[scriptable, uuid(3275b2cd-af6d-429a-80d7-f0c5120342ac)]
+interface nsICategoryManager : nsISupports
+{
+ /**
+ * Get the value for the given category's entry.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry you're looking for ("http")
+ * @return The value.
+ */
+ string getCategoryEntry(in string aCategory, in string aEntry);
+
+ /**
+ * Add an entry to a category.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry to be added ("http")
+ * @param aValue The value for the entry ("moz.httprulez.1")
+ * @param aPersist Should this data persist between invocations?
+ * @param aReplace Should we replace an existing entry?
+ * @return Previous entry, if any
+ */
+ string addCategoryEntry(in string aCategory, in string aEntry,
+ in string aValue, in boolean aPersist,
+ in boolean aReplace);
+
+ /**
+ * Delete an entry from the category.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry to be added ("http")
+ * @param aPersist Delete persistent data from registry, if present?
+ */
+ void deleteCategoryEntry(in string aCategory, in string aEntry,
+ in boolean aPersist);
+
+ /**
+ * Delete a category and all entries.
+ * @param aCategory The category to be deleted.
+ */
+ void deleteCategory(in string aCategory);
+
+ /**
+ * Enumerate the entries in a category.
+ * @param aCategory The category to be enumerated.
+ * @return a simple enumerator, each result QIs to
+ * nsISupportsCString.
+ */
+ nsISimpleEnumerator enumerateCategory(in string aCategory);
+
+ /**
+ * Enumerate all existing categories
+ * @param aCategory The category to be enumerated.
+ * @return a simple enumerator, each result QIs to
+ * nsISupportsCString.
+ */
+ nsISimpleEnumerator enumerateCategories();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl b/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl
new file mode 100644
index 00000000..e934057c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIProgrammingLanguage.idl"
+
+/**
+ * Provides information about a specific implementation class
+ * @status FROZEN
+ */
+
+[scriptable, uuid(986c11d0-f340-11d4-9075-0010a4e73d9a)]
+interface nsIClassInfo : nsISupports
+{
+ /**
+ * Get an ordered list of the interface ids that instances of the class
+ * promise to implement. Note that nsISupports is an implicit member
+ * of any such list and need not be included.
+ *
+ * Should set *count = 0 and *array = null and return NS_OK if getting the
+ * list is not supported.
+ */
+ void getInterfaces(out PRUint32 count,
+ [array, size_is(count), retval] out nsIIDPtr array);
+
+ /**
+ * Get a language mapping specific helper object that may assist in using
+ * objects of this class in a specific lanaguage. For instance, if asked
+ * for the helper for nsIProgrammingLanguage::JAVASCRIPT this might return
+ * an object that can be QI'd into the nsIXPCScriptable interface to assist
+ * XPConnect in supplying JavaScript specific behavior to callers of the
+ * instance object.
+ *
+ * see: nsIProgrammingLanguage.idl
+ *
+ * Should return null if no helper available for given language.
+ */
+ nsISupports getHelperForLanguage(in PRUint32 language);
+
+ /**
+ * A contract ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|), or null.
+ */
+ readonly attribute string contractID;
+
+ /**
+ * A human readable string naming the class, or null.
+ */
+ readonly attribute string classDescription;
+
+ /**
+ * A class ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|), or null.
+ */
+ readonly attribute nsCIDPtr classID;
+
+ /**
+ * Return language type from list in nsIProgrammingLanguage
+ */
+
+ readonly attribute PRUint32 implementationLanguage;
+
+ /**
+ * Bitflags for 'flags' attribute.
+ */
+ const PRUint32 SINGLETON = 1 << 0;
+ const PRUint32 THREADSAFE = 1 << 1;
+ const PRUint32 MAIN_THREAD_ONLY = 1 << 2;
+ const PRUint32 DOM_OBJECT = 1 << 3;
+ const PRUint32 PLUGIN_OBJECT = 1 << 4;
+ const PRUint32 EAGER_CLASSINFO = 1 << 5;
+ /**
+ * 'flags' attribute bitflag: whether objects of this type implement
+ * nsIContent.
+ */
+ const PRUint32 CONTENT_NODE = 1 << 6;
+
+ // The high order bit is RESERVED for consumers of these flags.
+ // No implementor of this interface should ever return flags
+ // with this bit set.
+ const PRUint32 RESERVED = 1 << 31;
+
+
+ readonly attribute PRUint32 flags;
+
+ /**
+ * Also a class ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|). If the class does
+ * not have a CID, it should return NS_ERROR_NOT_AVAILABLE. This attribute
+ * exists so C++ callers can avoid allocating and freeing a CID, as would
+ * happen if they used classID.
+ */
+ [notxpcom] readonly attribute nsCID classIDNoAlloc;
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl
new file mode 100644
index 00000000..d1b4be6e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIFactory.idl"
+#include "nsIFile.idl"
+#include "nsIComponentManager.idl"
+
+[object, uuid(c073cfc0-567c-11d3-aec1-0000f8e25c06)]
+interface nsIComponentLoader : nsISupports {
+
+ /**
+ * Get the factory for a given component.
+ */
+ nsIFactory getFactory(in nsIIDRef aCID, in string aLocation,
+ in string aType);
+
+ /**
+ * Initialize the loader.
+ *
+ * We use nsISupports here because nsIRegistry isn't IDLized yet.
+ */
+ void init(in nsIComponentManager aCompMgr, in nsISupports aRegistry);
+
+ /**
+ * Called when a component of the appropriate type is registered,
+ * to give the component loader an opportunity to do things like
+ * annotate the registry and such.
+ */
+ void onRegister(in nsIIDRef aCID, in string aType,
+ in string aClassName, in string aContractID,
+ in string aLocation, in boolean aReplace,
+ in boolean aPersist);
+
+ /**
+ * When is AutoRegistration occuring?
+ */
+ const long Startup = 0;
+ const long Component = 1;
+ const long Timer = 2;
+
+ /**
+ * AutoRegister components in the given directory.
+ */
+ void autoRegisterComponents(in long aWhen, in nsIFile aDirectory);
+
+ /**
+ * AutoRegister the given component.
+ *
+ * Returns true if the component was registered, false if it couldn't
+ * attempt to register the component (wrong type) and ``throws'' an
+ * NS_FAILED code if there was an error during registration.
+ */
+ boolean autoRegisterComponent(in long aWhen, in nsIFile aComponent);
+
+ /**
+ * AutoUnregister the given component.
+ * Returns true if the component was unregistered, false if it coudln't
+ * attempt to unregister the component (not found, wrong type).
+ */
+ boolean autoUnregisterComponent(in long aWhen, in nsIFile aComponent);
+
+ /**
+ * Register any deferred (NS_ERROR_FACTORY_REGISTER_AGAIN) components.
+ * Return registered-any-components?
+ */
+ boolean registerDeferredComponents(in long aWhen);
+
+ /**
+ * Unload all components that are willing.
+ */
+ void unloadAll(in long aWhen);
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl
new file mode 100644
index 00000000..9f1784d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The nsIComponentRegistrar interface.
+ * @status EXPERIMENTAL
+ *
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+[uuid(fce83d37-a3c0-4e09-ad9f-6842a984dbdf)]
+interface nsIComponentLoaderManager : nsISupports
+{
+ boolean hasFileChanged(in nsIFile file, in string loaderString, in PRInt64 modDate);
+ void saveFileInfo(in nsIFile file, in string loaderString, in PRInt64 modDate);
+ void removeFileInfo(in nsIFile file, in string loaderString);
+ void flushPersistentStore(in boolean now);
+
+ string getOptionalData(in nsIFile file, in string loaderString);
+ void setOptionalData(in nsIFile file, in string loaderString, in string value);
+};
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl
new file mode 100644
index 00000000..20661803
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl
@@ -0,0 +1,111 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The nsIComponentManager interface.
+ * @status FROZEN
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFactory;
+
+[scriptable, uuid(a88e5a60-205a-4bb1-94e1-2628daf51eae)]
+interface nsIComponentManager : nsISupports
+{
+ /**
+ * getClassObject
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ void getClassObject(in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * getClassObjectByContractID
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ void getClassObjectByContractID(in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+
+ /**
+ * createInstance
+ *
+ * Create an instance of the CID aClass and return the interface aIID.
+ *
+ * @param aClass : ClassID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ void createInstance(in nsCIDRef aClass,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * createInstanceByContractID
+ *
+ * Create an instance of the CID that implements aContractID and return the
+ * interface aIID.
+ *
+ * @param aContractID : aContractID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ void createInstanceByContractID(in string aContractID,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+};
+
+
+%{ C++
+#ifndef MOZILLA_STRICT_API
+#include "nsComponentManagerUtils.h"
+#include "nsComponentManagerObsolete.h"
+#endif
+%} C++
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl
new file mode 100644
index 00000000..ac5f7975
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl
@@ -0,0 +1,351 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIFactory.idl"
+
+interface nsIFile;
+interface nsIEnumerator;
+
+[scriptable, uuid(8458a740-d5dc-11d2-92fb-00e09805570f)]
+interface nsIComponentManagerObsolete : nsISupports
+{
+ /**
+ * findFactory
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ nsIFactory findFactory(in nsCIDRef aClass);
+
+ /**
+ * getClassObject
+ *
+ * @param aClass : CID of the class whose class object is requested
+ * @param aIID : IID of an interface that the class object is known to
+ * to implement. nsISupports and nsIFactory are known to
+ * be implemented by the class object.
+ */
+ [noscript] voidPtr getClassObject(in nsCIDRef aClass, in nsIIDRef aIID);
+
+ /**
+ * contractIDToClassID
+ *
+ * Get the ClassID for a given ContractID. Many ClassIDs may implement a
+ * ContractID. In such a situation, this returns the preferred ClassID, which
+ * happens to be the last registered ClassID.
+ *
+ * @param aContractID : Contractid for which ClassID is requested
+ * @return aClass : ClassID return
+ */
+ [notxpcom] nsresult contractIDToClassID(in string aContractID, out nsCID aClass);
+
+ /**
+ * classIDToContractid
+ *
+ * Get the ContractID for a given ClassID. A ClassIDs may implement multiple
+ * ContractIDs. This function return the last registered ContractID.
+ *
+ * @param aClass : ClassID for which ContractID is requested.
+ * @return aClassName : returns class name asssociated with aClass
+ * @return : ContractID last registered for aClass
+ */
+ string CLSIDToContractID(in nsCIDRef aClass, out string aClassName);
+
+ /**
+ * createInstance
+ *
+ * Create an instance of the CID aClass and return the interface aIID.
+ *
+ * @param aClass : ClassID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ [noscript] voidPtr createInstance(in nsCIDRef aClass,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID);
+
+ /**
+ * createInstanceByContractID
+ *
+ * Create an instance of the CID that implements aContractID and return the
+ * interface aIID. This is a convenience function that effectively does
+ * ContractIDToClassID() followed by CreateInstance().
+ *
+ * @param aContractID : aContractID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ [noscript] voidPtr createInstanceByContractID(in string aContractID,
+ in nsISupports aDelegate,
+ in nsIIDRef IID);
+ /**
+ * registryLocationForSpec
+ *
+ * Given a file specification, return the registry representation of
+ * the filename. Files that are found relative to the components
+ * directory will have a registry representation
+ * "rel:<relative-native-path>" while filenames that are not, will have
+ * "abs:<full-native-path>".
+ */
+ string registryLocationForSpec(in nsIFile aSpec);
+
+ /**
+ * specForRegistyLocation
+ *
+ * Create a file specification for the registry representation (rel:/abs:)
+ * got via registryLocationForSpec.
+ */
+ nsIFile specForRegistryLocation(in string aLocation);
+
+ /**
+ * registerFactory
+ *
+ * Register a factory and ContractID associated with CID aClass
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFactory : Factory that will be registered for CID aClass
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * registration for the CID aClass.
+ */
+ void registerFactory(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFactory aFactory,
+ in boolean aReplace);
+
+ /**
+ * registerComponent
+ *
+ * Register a native dll module via its registry representation as returned
+ * by registryLocationForSpec() as the container of CID implemenation
+ * aClass and associate aContractID and aClassName to the CID aClass. Native
+ * dll component type is assumed.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aLocation : Location of module (dll). Format of this is the
+ * registry representation as returned by
+ * registryLocationForSpec()
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponent(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in string aLocation,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * registerComponentWithType
+ *
+ * Register a module's location via its registry representation
+ * as returned by registryLocationForSpec() as the container of CID implemenation
+ * aClass of type aType and associate aContractID and aClassName to the CID aClass.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aSpec : Filename spec for module's location.
+ * @param aLocation : Location of module of type aType. Format of this string
+ * is the registry representation as returned by
+ * registryLocationForSpec()
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * loader registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ * @param aType : Component Type of CID aClass.
+ */
+ void registerComponentWithType(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFile aSpec,
+ in string aLocation, in boolean aReplace,
+ in boolean aPersist, in string aType);
+
+ /**
+ * registerComponentSpec
+ *
+ * Register a native dll module via its file specification as the container
+ * of CID implemenation aClass and associate aContractID and aClassName to the
+ * CID aClass. Native dll component type is assumed.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aLibrary : File specification Location of module (dll).
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponentSpec(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFile aLibrary,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * registerComponentLib
+ *
+ * Register a native dll module via its dll name (not full path) as the
+ * container of CID implemenation aClass and associate aContractID and aClassName
+ * to the CID aClass. Native dll component type is assumed and the system
+ * services will be used to load this dll.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aDllNameLocation : Dll name of module.
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponentLib(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in string aDllName,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * unregisterFactory
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : ClassID being unregistered
+ * @param aFactory : Factory previously registered to create instances of
+ * ClassID aClass.
+ */
+ void unregisterFactory(in nsCIDRef aClass, in nsIFactory aFactory);
+
+ /**
+ * unregisterComponent
+ *
+ * Disassociate module aLocation represented as registry location as returned
+ * by registryLocationForSpec() as containing ClassID aClass.
+ *
+ * @param aClass : ClassID being unregistered
+ * @param aLocation : Location of module. Format of this is the registry
+ * representation as returned by registryLocationForSpec().
+ * Components of any type will be unregistered.
+ */
+ void unregisterComponent(in nsCIDRef aClass, in string aLocation);
+
+ /**
+ * unregisterComponentSpec
+ *
+ * Disassociate module references by file specification aLibrarySpec as
+ * containing ClassID aClass.
+ */
+ void unregisterComponentSpec(in nsCIDRef aClass, in nsIFile aLibrarySpec);
+
+ /**
+ * freeLibraries
+ *
+ * Enumerates all loaded modules and unloads unused modules.
+ */
+ void freeLibraries();
+
+ /**
+ * ID values for 'when'
+ */
+ const long NS_Startup = 0;
+ const long NS_Script = 1;
+ const long NS_Timer = 2;
+ const long NS_Shutdown = 3;
+
+ /**
+ * autoRegister
+ *
+ * Enumerates directory looking for modules of all types and registers
+ * modules who have changed (modtime or size) since the last time
+ * autoRegister() was invoked.
+ *
+ * @param when : ID values of when the call is being made.
+ * @param directory : Directory the will be enumerated.
+ */
+ void autoRegister(in long when, in nsIFile directory);
+
+ /**
+ * autoRegisterComponent
+ *
+ * Loads module using appropriate loader and gives it an opportunity to
+ * register its CIDs if module's modtime or size changed since the last
+ * time this was called.
+ *
+ * @param when : ID values of when the call is being made.
+ * @param aFileLocation : File specification of module.
+ */
+ void autoRegisterComponent(in long when, in nsIFile aFileLocation);
+
+ /**
+ * autoUnregisterComponent
+ *
+ * Loads module using approriate loader and gives it an opportunity to
+ * unregister its CIDs
+ */
+ void autoUnregisterComponent(in long when, in nsIFile aFileLocation);
+
+ /**
+ * isRegistered
+ *
+ * Returns true if a factory or module is registered for CID aClass.
+ *
+ * @param aClass : ClassID queried for registeration
+ * @return : true if a factory or module is registered for CID aClass.
+ * false otherwise.
+ */
+ boolean isRegistered(in nsCIDRef aClass);
+
+ /**
+ * enumerateCLSIDs
+ *
+ * Enumerate the list of all registered ClassIDs.
+ *
+ * @return : enumerator for ClassIDs.
+ */
+ nsIEnumerator enumerateCLSIDs();
+
+ /**
+ * enumerateContractIDs
+ *
+ * Enumerate the list of all registered ContractIDs.
+ *
+ * @return : enumerator for ContractIDs.
+ */
+ nsIEnumerator enumerateContractIDs();
+};
+
+%{ C++
+/* include after the class def'n, because it needs to see it. */
+#include "nsComponentManagerUtils.h"
+%} C++
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h
new file mode 100644
index 00000000..a21ee7e3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIComponentManagerUtils_h__
+#define nsIComponentManagerUtils_h__
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl
new file mode 100644
index 00000000..2a4a55db
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl
@@ -0,0 +1,243 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The nsIComponentRegistrar interface.
+ * @status FROZEN
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+interface nsIFactory;
+interface nsISimpleEnumerator;
+
+[scriptable, uuid(2417cbfe-65ad-48a6-b4b6-eb84db174392)]
+interface nsIComponentRegistrar : nsISupports
+{
+ /**
+ * autoRegister
+ *
+ * Register a component file or all component files in a directory.
+ *
+ * Component files must have an associated loader and export the required
+ * symbols which this loader defines. For example, if the given file is a
+ * native library (which is built into XPCOM), it must export the symbol
+ * "NSGetModule". Other loaders may have different semantics.
+ *
+ * This method may only be called from the main thread.
+ *
+ * @param aSpec : Filename spec for component file's location. If aSpec
+ * is a directory, then every component file in the
+ * directory will be registered.
+ * If the aSpec is null, then the application component's
+ * directory as defined by NS_XPCOM_COMPONENT_DIR will be
+ * registered (see nsIDirectoryService.idl)
+ *
+ * @return NS_OK : Registration was successful.
+ * NS_ERROR: Method failure.
+ */
+ void autoRegister(in nsIFile aSpec);
+
+ /**
+ * autoUnregister
+ *
+ * Unregister a component file or all component files in a directory.
+ * This method may only be called from the main thread.
+ *
+ * @param aSpec : Filename spec for component file's location. If aSpec
+ * is a directory, the every component file in the directory
+ * will be registered.
+ * If aSpec is null, then the application component's
+ * directory as defined by NS_XPCOM_COMPONENT_DIR will be
+ * registered. (see nsIDirectoryService.idl)
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void autoUnregister(in nsIFile aSpec);
+
+
+ /**
+ * registerFactory
+ *
+ * Register a factory with a given ContractID, CID and Class Name.
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFactory : Factory that will be registered for CID aClass
+ *
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* method failure.
+ */
+ void registerFactory(in nsCIDRef aClass,
+ in string aClassName,
+ in string aContractID,
+ in nsIFactory aFactory);
+
+ /**
+ * unregisterFactory
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : CID being unregistered
+ * @param aFactory : Factory previously registered to create instances of
+ * CID aClass.
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void unregisterFactory(in nsCIDRef aClass,
+ in nsIFactory aFactory);
+
+ /**
+ * registerFactoryLocation
+ *
+ * Register a factory with a given ContractID, CID and Class Name
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFile : Component File. This file must have an associated
+ * loader and export the required symbols which this
+ * loader specifies.
+ * @param aLoaderStr : Opaque loader specific string. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ * @param aType : Component Type of CID aClass. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ *
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void registerFactoryLocation(in nsCIDRef aClass,
+ in string aClassName,
+ in string aContractID,
+ in nsIFile aFile,
+ in string aLoaderStr,
+ in string aType);
+
+ /**
+ * unregisterFactoryLocation
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : CID being unregistered
+ * @param aFile : Component File previously registered
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void unregisterFactoryLocation(in nsCIDRef aClass,
+ in nsIFile aFile);
+
+ /**
+ * isCIDRegistered
+ *
+ * Returns true if a factory is registered for the CID.
+ *
+ * @param aClass : CID queried for registeration
+ * @return : true if a factory is registered for CID
+ * false otherwise.
+ */
+ boolean isCIDRegistered(in nsCIDRef aClass);
+
+ /**
+ * isContractIDRegistered
+ *
+ * Returns true if a factory is registered for the contract id.
+ *
+ * @param aClass : contract id queried for registeration
+ * @return : true if a factory is registered for contract id
+ * false otherwise.
+ */
+ boolean isContractIDRegistered(in string aContractID);
+
+ /**
+ * enumerateCIDs
+ *
+ * Enumerate the list of all registered CIDs.
+ *
+ * @return : enumerator for CIDs. Elements of the enumeration can be QI'ed
+ * for the nsISupportsID interface. From the nsISupportsID, you
+ * can obtain the actual CID.
+ */
+ nsISimpleEnumerator enumerateCIDs();
+
+ /**
+ * enumerateContractIDs
+ *
+ * Enumerate the list of all registered ContractIDs.
+ *
+ * @return : enumerator for ContractIDs. Elements of the enumeration can be
+ * QI'ed for the nsISupportsCString interface. From the
+ * nsISupportsCString interface, you can obtain the actual
+ * Contract ID string.
+ */
+ nsISimpleEnumerator enumerateContractIDs();
+
+ /**
+ * CIDToContractID
+ *
+ * Returns the Contract ID for a given CID, if one exists and is registered.
+ *
+ * @return : Contract ID.
+ */
+ string CIDToContractID(in nsCIDRef aClass);
+
+ /**
+ * contractIDToCID
+ *
+ * Returns the CID for a given Contract ID, if one exists and is registered.
+ *
+ * @return : Contract ID.
+ */
+ nsCIDPtr contractIDToCID(in string aContractID);
+
+};
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl b/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl
new file mode 100644
index 00000000..bda0b43a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl
@@ -0,0 +1,79 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * A class factory allows the creation of nsISupports derived
+ * components without specifying a concrete base class.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, object, uuid(00000001-0000-0000-c000-000000000046)]
+interface nsIFactory : nsISupports {
+ /**
+ * Creates an instance of a component.
+ *
+ * @param aOuter Pointer to a component that wishes to be aggregated
+ * in the resulting instance. This will be nsnull if no
+ * aggregation is requested.
+ * @param iid The IID of the interface being requested in
+ * the component which is being currently created.
+ * @param result [out] Pointer to the newly created instance, if successful.
+ * @return NS_OK - Component successfully created and the interface
+ * being requested was successfully returned in result.
+ * NS_NOINTERFACE - Interface not accessible.
+ * NS_ERROR_NO_AGGREGATION - if an 'outer' object is supplied, but the
+ * component is not aggregatable.
+ * NS_ERROR* - Method failure.
+ */
+ void createInstance(in nsISupports aOuter, in nsIIDRef iid,
+ [retval, iid_is(iid)] out nsQIResult result);
+
+ /**
+ * LockFactory provides the client a way to keep the component
+ * in memory until it is finished with it. The client can call
+ * LockFactory(PR_TRUE) to lock the factory and LockFactory(PR_FALSE)
+ * to release the factory.
+ *
+ * @param lock - Must be PR_TRUE or PR_FALSE
+ * @return NS_OK - If the lock operation was successful.
+ * NS_ERROR* - Method failure.
+ */
+ void lockFactory(in PRBool lock);
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIModule.idl b/src/libs/xpcom18a4/xpcom/components/nsIModule.idl
new file mode 100644
index 00000000..a71b9b13
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIModule.idl
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+interface nsIComponentManager;
+
+/**
+ * The nsIModule interface.
+ * @status FROZEN
+ */
+
+[scriptable, uuid(7392D032-5371-11d3-994E-00805FD26FEE)]
+interface nsIModule : nsISupports
+{
+ /**
+ * Object Instance Creation
+ *
+ * Obtains a Class Object from a nsIModule for a given CID and IID pair.
+ * This class object can either be query to a nsIFactory or a may be
+ * query to a nsIClassInfo.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aClass : ClassID of object instance requested
+ * @param aIID : IID of interface requested
+ *
+ */
+ void getClassObject(in nsIComponentManager aCompMgr,
+ in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [retval, iid_is(aIID)] out nsQIResult aResult);
+
+
+ /**
+ * One time registration callback
+ *
+ * When the nsIModule is discovered, this method will be
+ * called so that any setup registration can be preformed.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aLocation : The location of the nsIModule on disk
+ * @param aLoaderStr: Opaque loader specific string
+ * @param aType : Loader Type being used to load this module
+ */
+ void registerSelf(in nsIComponentManager aCompMgr,
+ in nsIFile aLocation,
+ in string aLoaderStr,
+ in string aType);
+ /**
+ * One time unregistration callback
+ *
+ * When the nsIModule is being unregistered, this method will be
+ * called so that any unregistration can be preformed
+ *
+ * @param aCompMgr : The global component manager
+ * @param aLocation : The location of the nsIModule on disk
+ * @param aLoaderStr : Opaque loader specific string
+ *
+ */
+ void unregisterSelf(in nsIComponentManager aCompMgr,
+ in nsIFile aLocation,
+ in string aLoaderStr);
+
+ /**
+ * Module load management
+ *
+ * @param aCompMgr : The global component manager
+ *
+ * @return indicates to the caller if the module can be unloaded.
+ * Returning PR_TRUE isn't a guarantee that the module will be
+ * unloaded. It constitues only willingness of the module to be
+ * unloaded. It is very important to ensure that no outstanding
+ * references to the module's code/data exist before returning
+ * PR_TRUE.
+ * Returning PR_FALSE guaratees that the module wont be unloaded.
+ */
+ boolean canUnload(in nsIComponentManager aCompMgr);
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl b/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl
new file mode 100644
index 00000000..c5d18111
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+[uuid(10d1a2a2-d816-458d-a4c3-0805ff0f7b31)]
+interface nsINativeComponentLoader : nsISupports
+{
+
+ /**
+ * addDependentLibrary
+ *
+ * This method informs the native component loader that the
+ * given component library referenced by |aFile| requires
+ * symbols that can be found in the library named |aLibName|.
+ *
+ * The native component loader is expected to resolve these
+ * external symobls prior to loading the component library.
+ *
+ * @param aFile
+ * The native component file location that is declaring a
+ * a dependency. This file is expected to be a DSO/DLL.
+ *
+ * @param aLibName
+ * This is a name of a library that the component requires.
+ * This file name is found in either the GRE bin directory
+ * or the application's bin directory. Full file path are
+ * also accepted. Passing nsnull for the |aLibName| will
+ * clear all dependencies. Note that non null aLibName
+ * values are expected to be in the native charset.
+ */
+
+ void addDependentLibrary(in nsIFile aFile, in string aLibName);
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl
new file mode 100644
index 00000000..200c2a69
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl
@@ -0,0 +1,119 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+
+/**
+ * The nsIServiceManager manager interface provides a means to obtain
+ * global services in an application. The service manager depends on the
+ * repository to find and instantiate factories to obtain services.
+ *
+ * Users of the service manager must first obtain a pointer to the global
+ * service manager by calling NS_GetServiceManager. After that,
+ * they can request specific services by calling GetService. When they are
+ * finished they can NS_RELEASE() the service as usual.
+ *
+ * A user of a service may keep references to particular services indefinitely
+ * and only must call Release when it shuts down.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(8bb35ed9-e332-462d-9155-4a002ab5c958)]
+interface nsIServiceManager : nsISupports
+{
+ /**
+ * getServiceByContractID
+ *
+ * Returns the instance that implements aClass or aContractID and the
+ * interface aIID. This may result in the instance being created.
+ *
+ * @param aClass or aContractID : aClass or aContractID of object
+ * instance requested
+ * @param aIID : IID of interface requested
+ * @param result : resulting service
+ */
+ void getService(in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ void getServiceByContractID(in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * isServiceInstantiated
+ *
+ * isServiceInstantiated will return a true if the service has already
+ * been created, otherwise false
+ *
+ * @param aClass or aContractID : aClass or aContractID of object
+ * instance requested
+ * @param aIID : IID of interface requested
+ * @param aIID : IID of interface requested
+ */
+ boolean isServiceInstantiated(in nsCIDRef aClass, in nsIIDRef aIID);
+ boolean isServiceInstantiatedByContractID(in string aContractID, in nsIIDRef aIID);
+};
+
+
+%{C++
+#define NS_ERROR_SERVICE_NOT_AVAILABLE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 22)
+/**
+ * @status DEPRECATED
+ */
+#define NS_ERROR_SERVICE_NOT_FOUND NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 22)
+/**
+ * @status DEPRECATED
+ */
+#define NS_ERROR_SERVICE_IN_USE NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 23)
+
+// Observing xpcom startup. If you component has not been created, it will be.
+#define NS_XPCOM_STARTUP_OBSERVER_ID "xpcom-startup"
+
+// Observing xpcom shutdown
+#define NS_XPCOM_SHUTDOWN_OBSERVER_ID "xpcom-shutdown"
+
+// Observing xpcom autoregistration. Topics will be 'start' and 'stop'.
+#define NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID "xpcom-autoregistration"
+
+#ifndef MOZILLA_STRICT_API
+#include "nsXPCOM.h"
+#include "nsIServiceManagerUtils.h"
+#include "nsIServiceManagerObsolete.h"
+#endif
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h
new file mode 100644
index 00000000..dc229c76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIServiceManagerObsolete_h___
+#define nsIServiceManagerObsolete_h___
+
+////////////////////////////////////////////////////////////////////
+//
+// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+//
+// Functions, classes, interfaces and types in this file are
+// obsolete. Use at your own risk.
+// Please see nsIServiceManager.idl for the supported interface
+// to the service manager.
+//
+////////////////////////////////////////////////////////////////////
+
+#include "nsIComponentManager.h"
+#include "nsID.h"
+
+#ifndef nsCOMPtr_h___
+#include "nsCOMPtr.h"
+#endif
+
+class nsIServiceManager;
+class nsIShutdownListener;
+class nsIDirectoryServiceProvider;
+
+class nsServiceManagerObsolete;
+
+#define NS_ISERVICEMANAGER_OBSOLETE_IID \
+{ /* cf0df3b0-3401-11d2-8163-006008119d7a */ \
+ 0xcf0df3b0, \
+ 0x3401, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+/**
+ * The nsIServiceManagerObsolete manager is obsolete. Please refer
+ * to nsIServiceManager.
+ */
+class nsIServiceManagerObsolete : public nsISupports {
+public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISERVICEMANAGER_OBSOLETE_IID);
+
+ /**
+ * RegisterService may be called explicitly to register a service
+ * with the service manager. If a service is not registered explicitly,
+ * the component manager will be used to create an instance according
+ * to the class ID specified.
+ */
+ NS_IMETHOD
+ RegisterService(const nsCID& aClass, nsISupports* aService) = 0;
+
+ /**
+ * Requests a service to be shut down, possibly unloading its DLL.
+ *
+ * @returns NS_OK - if shutdown was successful and service was unloaded,
+ * @returns NS_ERROR_SERVICE_NOT_FOUND - if shutdown failed because
+ * the service was not currently loaded
+ * @returns NS_ERROR_SERVICE_IN_USE - if shutdown failed because some
+ * user of the service wouldn't voluntarily release it by using
+ * a shutdown listener.
+ */
+ NS_IMETHOD
+ UnregisterService(const nsCID& aClass) = 0;
+
+ NS_IMETHOD
+ GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ NS_IMETHOD
+ ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // let's do it again, this time with ContractIDs...
+
+ NS_IMETHOD
+ RegisterService(const char* aContractID, nsISupports* aService) = 0;
+
+ NS_IMETHOD
+ UnregisterService(const char* aContractID) = 0;
+
+ NS_IMETHOD
+ GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ /* OBSOLETE */
+ NS_IMETHOD
+ ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+};
+
+// Interface to Global Services
+class NS_COM nsServiceManager {
+public:
+
+ static nsresult
+ RegisterService(const nsCID& aClass, nsISupports* aService);
+
+ static nsresult
+ UnregisterService(const nsCID& aClass);
+
+ static nsresult
+ GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ static nsresult
+ ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // let's do it again, this time with ContractIDs...
+
+ static nsresult
+ RegisterService(const char* aContractID, nsISupports* aService);
+
+ static nsresult
+ UnregisterService(const char* aContractID);
+
+ static nsresult
+ GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ static nsresult
+ ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // These methods return really nsIServiceManagerObsolete, but they are
+ // statically cast to nsIServiceManager to preserve backwards compatiblity.
+ static nsresult GetGlobalServiceManager(nsIServiceManager* *result);
+ static nsresult ShutdownGlobalServiceManager(nsIServiceManager* *result);
+};
+
+
+#define NS_DECL_NSISERVICEMANAGEROBSOLETE \
+ NS_IMETHOD RegisterService(const nsCID& aClass, nsISupports* aService); \
+ NS_IMETHOD UnregisterService(const nsCID& aClass);\
+ NS_IMETHOD GetService(const nsCID& aClass, const nsIID& aIID, nsISupports* *result, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD ReleaseService(const nsCID& aClass, nsISupports* service, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD RegisterService(const char* aContractID, nsISupports* aService);\
+ NS_IMETHOD UnregisterService(const char* aContractID);\
+ NS_IMETHOD GetService(const char* aContractID, const nsIID& aIID, nsISupports* *result, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD ReleaseService(const char* aContractID, nsISupports* service, nsIShutdownListener* shutdownListener);
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define NS_ISHUTDOWNLISTENER_IID \
+{ /* 56decae0-3406-11d2-8163-006008119d7a */ \
+ 0x56decae0, \
+ 0x3406, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+class nsIShutdownListener;
+
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ nsIShutdownListener* shutdownListener,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsServiceManager::GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(nsISupports**, aDestination),
+ shutdownListener);
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ nsIShutdownListener* shutdownListener,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsServiceManager::GetService(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(nsISupports**, aDestination),
+ shutdownListener);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+#endif /* nsIServiceManagerObsolete_h___ */
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h
new file mode 100644
index 00000000..b7b432af
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIServiceManagerUtils_h__
+#define nsIServiceManagerUtils_h__
+
+#include "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Using servicemanager with COMPtrs
+class NS_COM nsGetServiceByCID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByCID( const nsCID& aCID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const nsCID& mCID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, 0, error);
+}
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, aServiceManager, error);
+}
+
+class NS_COM nsGetServiceByContractID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByContractID( const char* aContractID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+ // Implement a dummy destructor to workaround linking issue on Solaris gcc 4.8.2 (see @bugref{5838})
+ ~nsGetServiceByContractID() {}
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const char* mContractID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, aServiceManager, error);
+}
+
+class nsGetServiceFromCategory : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceFromCategory(const char* aCategory, const char* aEntry,
+ nsISupports* aServiceManager,
+ nsresult* aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+ protected:
+ const char* mCategory;
+ const char* mEntry;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceFromCategory
+do_GetServiceFromCategory( const char* category, const char* entry,
+ nsresult* error = 0)
+{
+ return nsGetServiceFromCategory(category, entry, 0, error);
+}
+
+// type-safe shortcuts for calling |GetService|
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetServiceByContractID(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsModule.h b/src/libs/xpcom18a4/xpcom/components/nsModule.h
new file mode 100644
index 00000000..56a06354
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsModule.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Marco Pesenti Gritti <marco@gnome.org>
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsModule_h__
+#define nsModule_h__
+
+#include "nsIModule.h"
+#include "nsIFile.h"
+#include "nsIComponentManager.h"
+
+// Exported Function from module dll to Create the nsIModule
+#define NS_GET_MODULE_SYMBOL "NSGetModule"
+
+extern "C" NS_EXPORT nsresult PR_CALLBACK
+NSGetModule(nsIComponentManager *aCompMgr,
+ nsIFile* location,
+ nsIModule** return_cobj);
+
+typedef nsresult (PR_CALLBACK *nsGetModuleProc)(nsIComponentManager *aCompMgr,
+ nsIFile* location,
+ nsIModule** return_cobj);
+
+
+#endif /* nsModule_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp
new file mode 100644
index 00000000..a3fd5df8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp
@@ -0,0 +1,1150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+
+#include "prmem.h"
+#include "prerror.h"
+#include "prsystem.h" // PR_GetDirectorySeparator
+#include "nsNativeComponentLoader.h"
+#include "nsComponentManager.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsIModule.h"
+#include "xcDll.h"
+#include "nsHashtable.h"
+#include "nsXPIDLString.h"
+#include "nsCRT.h"
+#include "nsIObserverService.h"
+
+#if defined(XP_MAC) // sdagley dougt fix
+#include <Files.h>
+#include <Errors.h>
+#include "nsILocalFileMac.h"
+#endif
+
+#include "prlog.h"
+extern PRLogModuleInfo *nsComponentManagerLog;
+
+static PRBool PR_CALLBACK
+DLLStore_Destroy(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsDll* entry = NS_STATIC_CAST(nsDll*, aData);
+ delete entry;
+ return PR_TRUE;
+}
+
+nsNativeComponentLoader::nsNativeComponentLoader() :
+ mCompMgr(nsnull),
+ mLoadedDependentLibs(16, PR_TRUE),
+ mDllStore(nsnull, nsnull, DLLStore_Destroy,
+ nsnull, 256, PR_TRUE)
+{
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsNativeComponentLoader,
+ nsIComponentLoader,
+ nsINativeComponentLoader)
+
+NS_IMETHODIMP
+nsNativeComponentLoader::GetFactory(const nsIID & aCID,
+ const char *aLocation,
+ const char *aType,
+ nsIFactory **_retval)
+{
+ nsresult rv;
+
+ if (!_retval)
+ return NS_ERROR_NULL_POINTER;
+
+ /* use a hashtable of WeakRefs to store the factory object? */
+
+ /* Should this all live in xcDll? */
+ nsDll *dll;
+ rv = CreateDll(nsnull, aLocation, &dll);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!dll)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!dll->IsLoaded()) {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: loading \"%s\"",
+ displayPath.get()));
+#endif
+ if (!dll->Load()) {
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsNativeComponentLoader: load FAILED"));
+
+ char errorMsg[1024] = "<unknown; can't get error from NSPR>";
+
+ if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
+ PR_GetErrorText(errorMsg);
+
+ DumpLoadError(dll, "GetFactory", errorMsg);
+
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ /* Get service manager for factory */
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(rv))
+ return rv; // XXX translate error code?
+
+ rv = GetFactoryFromModule(dll, aCID, _retval);
+
+ PR_LOG(nsComponentManagerLog, NS_SUCCEEDED(rv) ? PR_LOG_DEBUG : PR_LOG_ERROR,
+ ("nsNativeComponentLoader: Factory creation %s for %s",
+ (NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"),
+ aLocation));
+
+ // If the dll failed to get us a factory. But the dll registered that
+ // it would be able to create a factory for this CID. mmh!
+ // We cannot just delete the dll as the dll could be hosting
+ // other CID for which factory creation can pass.
+ // We will just let it be. The effect will be next time we try
+ // creating the object, we will query the dll again. Since the
+ // dll is loaded, this aint a big hit. So for optimized builds
+ // this is ok to limp along.
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Factory creation failed");
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
+{
+ mCompMgr = aCompMgr;
+ if (!mCompMgr)
+ return NS_ERROR_INVALID_ARG;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNativeComponentLoader::AutoRegisterComponents(PRInt32 aWhen,
+ nsIFile *aDirectory)
+{
+#ifdef DEBUG
+ /* do we _really_ want to print this every time? */
+ fprintf(stderr, "nsNativeComponentLoader: autoregistering begins.\n");
+#endif
+
+ nsresult rv = RegisterComponentsInDir(aWhen, aDirectory);
+
+#ifdef DEBUG
+ fprintf(stderr, "nsNativeComponentLoader: autoregistering %s\n",
+ NS_FAILED(rv) ? "FAILED" : "succeeded");
+#endif
+
+ return rv;
+}
+
+nsresult
+nsNativeComponentLoader::RegisterComponentsInDir(PRInt32 when,
+ nsIFile *dir)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+ PRBool isDir = PR_FALSE;
+
+#if 0
+ // Going to many of these checks is a performance hit on the mac.
+ // Since these routines are called relatively infrequently and
+ // we will fail anyway down the line if a directory aint there,
+ // we are commenting this check out.
+
+ // Make sure we are dealing with a directory
+ rv = dir->IsDirectory(&isDir);
+ if (NS_FAILED(rv)) return rv;
+
+ if (!isDir)
+ return NS_ERROR_INVALID_ARG;
+#endif /* 0 */
+
+ // Create a directory iterator
+ nsCOMPtr<nsISimpleEnumerator> dirIterator;
+ rv = dir->GetDirectoryEntries(getter_AddRefs(dirIterator));
+
+ if (NS_FAILED(rv)) return rv;
+
+ // whip through the directory to register every file
+ nsCOMPtr<nsIFile> dirEntry;
+ PRBool more = PR_FALSE;
+
+ rv = dirIterator->HasMoreElements(&more);
+ if (NS_FAILED(rv)) return rv;
+ while (more == PR_TRUE)
+ {
+ rv = dirIterator->GetNext((nsISupports**)getter_AddRefs(dirEntry));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = dirEntry->IsDirectory(&isDir);
+ if (NS_SUCCEEDED(rv))
+ {
+ if (isDir == PR_TRUE)
+ {
+ // This is a directory. Grovel for components into the directory.
+#ifdef RT_OS_DARWIN // But not if it's a debug bundle.
+ nsCAutoString leafName;
+ rv = dirEntry->GetNativeLeafName(leafName);
+ if ( NS_FAILED(rv)
+ || leafName.Length() < sizeof(".dSYM")
+ || PL_strcasecmp(leafName.get() + (leafName.Length() - sizeof(".dSYM") + 1), ".dSYM"))
+#endif
+ rv = RegisterComponentsInDir(when, dirEntry);
+ }
+ else
+ {
+ PRBool registered;
+ // This is a file. Try to register it.
+ rv = AutoRegisterComponent(when, dirEntry, &registered);
+ }
+ }
+ }
+ rv = dirIterator->HasMoreElements(&more);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return rv;
+}
+
+static nsresult PR_CALLBACK
+nsFreeLibrary(nsDll *dll, nsIServiceManager *serviceMgr, PRInt32 when)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (!dll || dll->IsLoaded() == PR_FALSE)
+ {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // Get if the dll was marked for unload in an earlier round
+ PRBool dllMarkedForUnload = dll->IsMarkedForUnload();
+
+ // Reset dll marking for unload just in case we return with
+ // an error.
+ dll->MarkForUnload(PR_FALSE);
+
+ PRBool canUnload = PR_FALSE;
+
+ // Get the module object
+ nsCOMPtr<nsIModule> mobj;
+ /* XXXshaver cheat and use the global component manager */
+ rv = dll->GetModule(NS_STATIC_CAST(nsIComponentManager*, nsComponentManagerImpl::gComponentManager),
+ getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = mobj->CanUnload(nsComponentManagerImpl::gComponentManager, &canUnload);
+ }
+
+ mobj = nsnull; // Release our reference to the module object
+ // When shutting down, whether we can unload the dll or not,
+ // we will shutdown the dll to release any memory it has got
+ if (when == nsIComponentManagerObsolete::NS_Shutdown)
+ {
+ dll->Shutdown();
+ }
+
+ // Check error status on CanUnload() call
+ if (NS_FAILED(rv))
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: nsIModule::CanUnload() returned error for %s.",
+ displayPath.get()));
+#endif
+ return rv;
+ }
+
+ if (canUnload)
+ {
+ if (dllMarkedForUnload)
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + Unloading \"%s\".", displayPath.get()));
+#endif
+
+#ifdef DEBUG_dougt
+ // XXX dlls aren't counting their outstanding instances correctly
+ // XXX hence, dont unload until this gets enforced.
+ rv = dll->Unload();
+#endif /* 0 */
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: Ready for unload \"%s\".", displayPath.get()));
+#endif
+ }
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: NOT ready for unload %s", displayPath.get()));
+#endif
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+struct freeLibrariesClosure
+{
+ nsIServiceManager *serviceMgr;
+ PRInt32 when;
+};
+
+static PRBool PR_CALLBACK
+nsFreeLibraryEnum(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsDll *dll = (nsDll *) aData;
+ struct freeLibrariesClosure *callData = (struct freeLibrariesClosure *) closure;
+ nsFreeLibrary(dll,
+ (callData ? callData->serviceMgr : NULL),
+ (callData ? callData->when : nsIComponentManagerObsolete::NS_Timer));
+ return PR_TRUE;
+}
+
+/*
+ * SelfRegisterDll
+ *
+ * Given a dll abstraction, this will load, selfregister the dll and
+ * unload the dll.
+ *
+ */
+nsresult
+nsNativeComponentLoader::SelfRegisterDll(nsDll *dll,
+ const char *registryLocation,
+ PRBool deferred)
+{
+ // Precondition: dll is not loaded already, unless we're deferred
+ PR_ASSERT(deferred || dll->IsLoaded() == PR_FALSE);
+
+ nsresult res;
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(res)) return res;
+
+ if (dll->Load() == PR_FALSE)
+ {
+ // Cannot load. Probably not a dll.
+ char errorMsg[1024] = "Cannot get error from nspr. Not enough memory.";
+ if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
+ PR_GetErrorText(errorMsg);
+
+ DumpLoadError(dll, "SelfRegisterDll", errorMsg);
+
+ return NS_ERROR_FAILURE;
+ }
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: Loaded \"%s\".", displayPath.get()));
+#endif
+
+ // Tell the module to self register
+ nsCOMPtr<nsIFile> fs;
+ nsCOMPtr<nsIModule> mobj;
+ res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(res))
+ {
+ /*************************************************************
+ * WARNING: Why are use introducing 'res2' here and then *
+ * later assigning it to 'res' rather than just using 'res'? *
+ * This is because this code turns up a code-generation bug *
+ * in VC6 on NT. Assigning to 'res' on the next line causes *
+ * the value of 'dll' to get nulled out! The two seem to be *
+ * getting aliased together during compilation. *
+ *************************************************************/
+ nsresult res2 = dll->GetDllSpec(getter_AddRefs(fs)); // don't change 'res2' -- see warning, above
+ if (NS_SUCCEEDED(res2)) {
+ // in the case of re-registering a component, we want to remove
+ // any optional data that this file may have had.
+ AddDependentLibrary(fs, nsnull);
+
+ res = mobj->RegisterSelf(mCompMgr, fs, registryLocation,
+ nativeComponentType);
+ }
+ else
+ {
+ res = res2; // don't take this out -- see warning, above
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: dll->GetDllSpec() on %s FAILED.",
+ displayPath.get()));
+#endif
+ }
+ mobj = NULL; // Force a release of the Module object before unload()
+ }
+
+ // Update the timestamp and size of the dll in registry
+ // Don't enter deferred modules in the registry, because it might only be
+ // able to register on some later autoreg, after another component has been
+ // installed.
+ if (res != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ PRInt64 modTime;
+ if (!fs)
+ return res;
+
+ fs->GetLastModifiedTime(&modTime);
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ if (!manager)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> fs;
+ res = dll->GetDllSpec(getter_AddRefs(fs));
+ if (NS_FAILED(res)) return res;
+
+ manager->SaveFileInfo(fs, registryLocation, modTime);
+ }
+
+ return res;
+}
+
+//
+// MOZ_DEMANGLE_SYMBOLS is only a linux + MOZ_DEBUG thing.
+//
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+#include "nsTraceRefcntImpl.h" // for nsTraceRefcntImpl::DemangleSymbol()
+#endif
+
+nsresult
+nsNativeComponentLoader::DumpLoadError(nsDll *dll,
+ const char *aCallerName,
+ const char *aNsprErrorMsg)
+{
+ PR_ASSERT(aCallerName != NULL);
+
+ if (nsnull == dll || nsnull == aNsprErrorMsg)
+ return NS_OK;
+
+ nsCAutoString errorMsg(aNsprErrorMsg);
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+ // Demangle undefined symbols
+ nsCAutoString undefinedMagicString("undefined symbol:");
+
+ PRInt32 offset = errorMsg.Find(undefinedMagicString, PR_TRUE);
+
+ if (offset != kNotFound)
+ {
+ nsCAutoString symbol(errorMsg);
+ nsCAutoString demangledSymbol;
+
+ symbol.Cut(0,offset);
+
+ symbol.Cut(0,undefinedMagicString.Length());
+
+ symbol.StripWhitespace();
+
+ char demangled[4096] = "\0";
+
+ nsTraceRefcntImpl::DemangleSymbol(symbol.get(),demangled,sizeof(demangled));
+
+ if (demangled && *demangled != '\0')
+ demangledSymbol = demangled;
+
+ if (!demangledSymbol.IsEmpty())
+ {
+ nsCAutoString tmp(errorMsg);
+
+
+ tmp.Cut(offset + undefinedMagicString.Length(),
+ tmp.Length() - offset - undefinedMagicString.Length());
+
+ tmp += " \n";
+
+ tmp += demangledSymbol;
+
+ errorMsg = tmp;
+ }
+ }
+#endif // MOZ_DEMANGLE_SYMBOLS
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+#ifdef DEBUG
+ fprintf(stderr,
+ "nsNativeComponentLoader: %s(%s) Load FAILED with error: %s\n",
+ aCallerName,
+ displayPath.get(),
+ errorMsg.get());
+#endif
+
+ // Do NSPR log
+#ifdef PR_LOGGING
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsNativeComponentLoader: %s(%s) Load FAILED with error: %s",
+ aCallerName,
+ displayPath.get(),
+ errorMsg.get()));
+#endif
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::SelfUnregisterDll(nsDll *dll)
+{
+ nsresult res;
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(res)) return res;
+
+ if (dll->Load() == PR_FALSE)
+ {
+ // Cannot load. Probably not a dll.
+ return(NS_ERROR_FAILURE);
+ }
+
+ // Tell the module to self register
+ nsCOMPtr<nsIModule> mobj;
+ res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(res))
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: %s using nsIModule to unregister self.", displayPath.get()));
+#endif
+ nsCOMPtr<nsIFile> fs;
+ res = dll->GetDllSpec(getter_AddRefs(fs));
+ if (NS_FAILED(res)) return res;
+ // Get registry location for spec
+ nsXPIDLCString registryName;
+
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &res);
+ if (obsoleteManager)
+ res = obsoleteManager->RegistryLocationForSpec(fs, getter_Copies(registryName));
+
+ if (NS_FAILED(res)) return res;
+ mobj->UnregisterSelf(mCompMgr, fs, registryName);
+ }
+ return res;
+}
+
+nsresult
+nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *unregistered)
+{
+
+ nsresult rv = NS_ERROR_FAILURE;
+
+ *unregistered = PR_FALSE;
+
+ nsXPIDLCString persistentDescriptor;
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->RegistryLocationForSpec(component,
+ getter_Copies(persistentDescriptor));
+ if (NS_FAILED(rv)) return rv;
+
+ // Notify observers, if any, of autoregistration work
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ (void) observerService->NotifyObservers(mgr,
+ NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ NS_LITERAL_STRING("Unregistering native component").get());
+ }
+ }
+
+ nsDll *dll = NULL;
+ rv = CreateDll(component, persistentDescriptor, &dll);
+ if (NS_FAILED(rv) || dll == NULL) return rv;
+
+ rv = SelfUnregisterDll(dll);
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, NS_SUCCEEDED(rv) ? PR_LOG_DEBUG : PR_LOG_ERROR,
+ ("nsNativeComponentLoader: AutoUnregistration for %s %s.",
+ (NS_FAILED(rv) ? "FAILED" : "succeeded"), displayPath.get()));
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Remove any autoreg info about this dll
+ nsCStringKey key(persistentDescriptor);
+ mDllStore.RemoveAndDelete(&key);
+
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ NS_ASSERTION(manager, "Something is terribly wrong");
+
+ manager->RemoveFileInfo(component, nsnull);
+
+ *unregistered = PR_TRUE;
+ return rv;
+}
+
+nsresult
+nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *registered)
+{
+ nsresult rv;
+ if (!registered)
+ return NS_ERROR_NULL_POINTER;
+
+ *registered = PR_FALSE;
+
+#ifndef VBOX
+ /* this should be a pref or registry entry, or something */
+ static const char *ValidDllExtensions[] = {
+ ".dll", /* Windows */
+ ".so", /* Unix */
+ ".shlb", /* Mac ? */
+ ".dso", /* Unix ? */
+ ".dylib", /* Unix: Mach */
+ ".so.1.0", /* Unix: BSD */
+ ".sl", /* Unix: HP-UX */
+#if defined(VMS)
+ ".exe", /* Open VMS */
+#endif
+ ".dlm", /* new for all platforms */
+ NULL
+ };
+
+ *registered = PR_FALSE;
+
+#if 0
+ // This is a performance hit on mac. Since we have already checked
+ // this; plus is we dont, load will fail anyway later on, this
+ // is being commented out.
+
+ // Ensure we are dealing with a file as opposed to a dir
+ PRBool b = PR_FALSE;
+
+ rv = component->IsFile(&b);
+ if (NS_FAILED(rv) || !b)
+ return rv;
+#endif /* 0 */
+
+ // deal only with files that have a valid extension
+ PRBool validExtension = PR_FALSE;
+
+#if defined(XP_MAC) // sdagley dougt fix
+ // rjc - on Mac, check the file's type code (skip checking the creator code)
+
+ nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(component);
+ if (localFileMac)
+ {
+ OSType type;
+ rv = localFileMac->GetFileType(&type);
+ if (NS_SUCCEEDED(rv))
+ {
+ // on Mac, Mozilla shared libraries are of type 'shlb'
+ // Note: we don't check the creator (which for Mozilla is 'MOZZ')
+ // so that 3rd party shared libraries will be noticed!
+ validExtension = ((type == 'shlb') || (type == 'NSPL'));
+ }
+ }
+
+#else
+ nsCAutoString leafName;
+ rv = component->GetNativeLeafName(leafName);
+ if (NS_FAILED(rv)) return rv;
+ int flen = leafName.Length();
+ for (int i=0; ValidDllExtensions[i] != NULL; i++)
+ {
+ int extlen = PL_strlen(ValidDllExtensions[i]);
+
+ // Does fullname end with this extension
+ if (flen >= extlen &&
+ !PL_strcasecmp(leafName.get() + (flen - extlen), ValidDllExtensions[i])
+ )
+ {
+ validExtension = PR_TRUE;
+ break;
+ }
+ }
+#endif
+
+ if (validExtension == PR_FALSE)
+ // Skip invalid extensions
+ return NS_OK;
+
+#else /* VBOX */
+ /* VBox: Only one valid suffix exist, so dispense with the the list. */
+# ifdef RT_OS_DARWIN
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.dylib";
+# else
+ static const char s_szSuff[] = ".dylib";
+ static const char s_szSuffInvalid[] = "-x86.dylib";
+# endif
+# elif defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.dll";
+#else
+ static const char s_szSuff[] = ".dll";
+ static const char s_szSuffInvalid[] = "-x86.dll";
+# endif
+# else
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.so";
+#else
+ static const char s_szSuff[] = ".so";
+ static const char s_szSuffInvalid[] = "-x86.so";
+# endif
+# endif
+
+ nsCAutoString strLeafName;
+ rv = component->GetNativeLeafName(strLeafName);
+ if (NS_FAILED(rv))
+ return rv;
+ size_t cchLeafName = strLeafName.Length();
+ if ( cchLeafName <= sizeof(s_szSuff)
+ || PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuff) + 1, s_szSuff))
+ {
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("Skipping '%s'...", strLeafName.get()));
+ return NS_OK; /* skip */
+ }
+# ifndef VBOX_IN_32_ON_64_MAIN_API
+ if ( cchLeafName >= sizeof(s_szSuffInvalid)
+ && !PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuffInvalid) + 1, s_szSuffInvalid))
+ {
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("Skipping '%s' (#2)...", strLeafName.get()));
+ return NS_OK; /* skip */
+ }
+# endif
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("... '%s'", strLeafName.get()));
+#endif /* VBOX */
+
+ nsXPIDLCString persistentDescriptor;
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->RegistryLocationForSpec(component,
+ getter_Copies(persistentDescriptor));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(persistentDescriptor);
+
+ // Get the registry representation of the dll, if any
+ nsDll *dll;
+ rv = CreateDll(component, persistentDescriptor, &dll);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (dll != NULL)
+ {
+ // We already have seen this dll. Check if this dll changed
+ if (!dll->HasChanged())
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ // Dll hasn't changed. Skip.
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + nsDll not changed \"%s\". Skipping...",
+ displayPath.get()));
+#endif
+ *registered = PR_TRUE;
+ return NS_OK;
+ }
+
+ // Aagh! the dll has changed since the last time we saw it.
+ // re-register dll
+
+
+ // Notify observers, if any, of autoregistration work
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ // this string can't come from a string bundle, because we
+ // don't have string bundles yet.
+ NS_ConvertASCIItoUCS2 fileName("(no name)");
+
+ // get the file name
+ nsCOMPtr<nsIFile> dllSpec;
+ if (NS_SUCCEEDED(dll->GetDllSpec(getter_AddRefs(dllSpec))) && dllSpec)
+ {
+ dllSpec->GetLeafName(fileName);
+ }
+
+ // this string can't come from a string bundle, because we
+ // don't have string bundles yet.
+ (void) observerService->
+ NotifyObservers(mgr,
+ NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ PromiseFlatString(NS_LITERAL_STRING("Registering native component ") +
+ fileName).get());
+ }
+ }
+
+ if (dll->IsLoaded())
+ {
+ // We loaded the old version of the dll and now we find that the
+ // on-disk copy if newer. Try to unload the dll.
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+
+ rv = nsFreeLibrary(dll, serviceMgr, when);
+ if (NS_FAILED(rv))
+ {
+ // THIS IS THE WORST SITUATION TO BE IN.
+ // Dll doesn't want to be unloaded. Cannot re-register
+ // this dll.
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: *** Dll already loaded. "
+ "Cannot unload either. Hence cannot re-register "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return rv;
+ }
+ else {
+ // dll doesn't have a CanUnload proc. Guess it is
+ // ok to unload it.
+ dll->Unload();
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + Unloading \"%s\". (no CanUnloadProc).",
+ displayPath.get()));
+#endif
+ }
+
+ } // dll isloaded
+
+ // Sanity.
+ if (dll->IsLoaded())
+ {
+ // We went through all the above to make sure the dll
+ // is unloaded. And here we are with the dll still
+ // loaded. Whoever taught dp programming...
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: Dll still loaded. Cannot re-register "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return NS_ERROR_FAILURE;
+ }
+ } // dll != NULL
+ else
+ {
+ // Create and add the dll to the mDllStore
+ // It is ok to do this even if the creation of nsDll
+ // didnt succeed. That way we wont do this again
+ // when we encounter the same dll.
+ dll = new nsDll(component, this);
+ if (dll == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mDllStore.Put(&key, (void *) dll);
+ } // dll == NULL
+
+ // Either we are seeing the dll for the first time or the dll has
+ // changed since we last saw it and it is unloaded successfully.
+ //
+ // Now we can try register the dll for sure.
+ nsresult res = SelfRegisterDll(dll, persistentDescriptor, PR_FALSE);
+ if (NS_FAILED(res))
+ {
+ if (res == NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ /* defer for later loading */
+ mDeferredComponents.AppendElement(dll);
+ *registered = PR_TRUE;
+ return NS_OK;
+ } else {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: Autoregistration FAILED for "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: Autoregistration Passed for "
+ "\"%s\".", displayPath.get()));
+#endif
+ // Marking dll along with modified time and size in the
+ // registry happens at PlatformRegister(). No need to do it
+ // here again.
+ *registered = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::RegisterDeferredComponents(PRInt32 aWhen,
+ PRBool *aRegistered)
+{
+#ifdef DEBUG
+ fprintf(stderr, "nNCL: registering deferred (%d)\n",
+ mDeferredComponents.Count());
+#endif
+ *aRegistered = PR_FALSE;
+ if (!mDeferredComponents.Count())
+ return NS_OK;
+
+ for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
+ nsDll *dll = NS_STATIC_CAST(nsDll *, mDeferredComponents[i]);
+ nsresult rv = SelfRegisterDll(dll,
+ nsnull,
+ PR_TRUE);
+ if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ if (NS_SUCCEEDED(rv))
+ *aRegistered = PR_TRUE;
+ mDeferredComponents.RemoveElementAt(i);
+ }
+ }
+#ifdef DEBUG
+ if (*aRegistered)
+ fprintf(stderr, "nNCL: registered deferred, %d left\n",
+ mDeferredComponents.Count());
+ else
+ fprintf(stderr, "nNCL: didn't register any components, %d left\n",
+ mDeferredComponents.Count());
+#endif
+ /* are there any fatal errors? */
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::OnRegister(const nsIID &aCID, const char *aType,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLocation,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsNativeComponentLoader: Unloading...."));
+
+ struct freeLibrariesClosure callData;
+ callData.serviceMgr = NULL; // XXX need to get this as a parameter
+ callData.when = aWhen;
+
+ // Cycle through the dlls checking to see if they want to be unloaded
+ mDllStore.Enumerate(nsFreeLibraryEnum, &callData);
+ return NS_OK;
+}
+
+//
+// CreateDll
+// The only way to create a dll or get it from the dll cache. This will
+// be called in multiple situations:
+//
+// 1. Autoregister will create one for each dll it is trying to register. This
+// call will be passing a spec in.
+// {spec, NULL, 0, 0}
+//
+// 2. GetFactory() This will call CreateDll() with a null spec but will give
+// the registry represented name of the dll. If modtime and size are zero,
+// we will go the registry to find the right modtime and size.
+// {NULL, rel:libpref.so, 0, 0}
+//
+// 3. Prepopulation of dllCache A dll object created off a registry entry.
+// Specifically dll name is stored in rel: or abs: or lib: formats in the
+// registry along with its lastModTime and fileSize.
+// {NULL, rel:libpref.so, 8985659, 20987}
+nsresult
+nsNativeComponentLoader::CreateDll(nsIFile *aSpec,
+ const char *aLocation,
+ nsDll **aDll)
+{
+ nsDll *dll;
+ nsCOMPtr<nsIFile> dllSpec;
+ nsCOMPtr<nsIFile> spec;
+ nsresult rv;
+
+ nsCStringKey key(aLocation);
+ dll = (nsDll *)mDllStore.Get(&key);
+ if (dll)
+ {
+ *aDll = dll;
+ return NS_OK;
+ }
+
+ if (!aSpec)
+ {
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->SpecForRegistryLocation(aLocation,
+ getter_AddRefs(spec));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ spec = aSpec;
+ }
+
+ if (!dll)
+ {
+ dll = new nsDll(spec, this);
+ if (!dll)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ *aDll = dll;
+ mDllStore.Put(&key, dll);
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
+ nsIFactory **aFactory)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIModule> module;
+ rv = aDll->GetModule(mCompMgr, getter_AddRefs(module));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return module->GetClassObject(mCompMgr, aCID, NS_GET_IID(nsIFactory),
+ (void **)aFactory);
+}
+
+
+NS_IMETHODIMP
+nsNativeComponentLoader::AddDependentLibrary(nsIFile* aFile, const char* libName)
+{
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ if (!manager)
+ {
+ NS_WARNING("Something is terribly wrong");
+ return NS_ERROR_FAILURE;
+ }
+
+ // the native component loader uses the optional data
+ // to store a space delimited list of dependent library
+ // names
+
+ if (!libName)
+ {
+ manager->SetOptionalData(aFile, nsnull, nsnull);
+ return NS_OK;
+ }
+
+ nsXPIDLCString data;
+ manager->GetOptionalData(aFile, nsnull, getter_Copies(data));
+
+ if (!data.IsEmpty())
+ data.AppendLiteral(" ");
+
+ data.Append(nsDependentCString(libName));
+
+ manager->SetOptionalData(aFile, nsnull, data);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h
new file mode 100644
index 00000000..818596ec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.h"
+#include "nsIComponentLoader.h"
+#include "nsIComponentManager.h"
+#include "nsDirectoryService.h"
+#include "nsCOMPtr.h"
+#include "nsHashtable.h"
+#include "nsVoidArray.h"
+#include "xcDll.h"
+#include "nsINativeComponentLoader.h"
+
+#ifndef nsNativeComponentLoader_h__
+#define nsNativeComponentLoader_h__
+
+class nsNativeComponentLoader : public nsIComponentLoader, public nsINativeComponentLoader {
+
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOMPONENTLOADER
+ NS_DECL_NSINATIVECOMPONENTLOADER
+
+ nsNativeComponentLoader();
+
+ nsIComponentManager* mCompMgr; // weak reference -- backpointer
+ nsHashtable mLoadedDependentLibs;
+
+ private:
+ nsObjectHashtable mDllStore;
+ nsVoidArray mDeferredComponents;
+
+ ~nsNativeComponentLoader() {}
+
+ NS_IMETHOD RegisterComponentsInDir(PRInt32 when, nsIFile *dir);
+
+ nsresult CreateDll(nsIFile *aSpec, const char *aLocation, nsDll **aDll);
+ nsresult SelfRegisterDll(nsDll *dll, const char *registryLocation,
+ PRBool deferred);
+ nsresult SelfUnregisterDll(nsDll *dll);
+ nsresult GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
+ nsIFactory **aFactory);
+
+ nsresult DumpLoadError(nsDll *dll,
+ const char *aCallerName,
+ const char *aNsprErrorMsg);
+};
+
+#endif /* nsNativeComponentLoader_h__ */
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h b/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h
new file mode 100644
index 00000000..da3e7a43
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h
@@ -0,0 +1,27 @@
+
+#ifndef OBSOLETE_MODULE_LOADING
+/*
+ * Prototypes for dynamic library export functions. Your DLL/DSO needs to export
+ * these methods to play in the component world.
+ *
+ * THIS IS OBSOLETE. Look at nsIModule.idl
+ */
+
+extern "C" NS_EXPORT nsresult NSGetFactory(nsISupports* aServMgr,
+ const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory **aFactory);
+extern "C" NS_EXPORT PRBool NSCanUnload(nsISupports* aServMgr);
+extern "C" NS_EXPORT nsresult NSRegisterSelf(nsISupports* aServMgr, const char *fullpath);
+extern "C" NS_EXPORT nsresult NSUnregisterSelf(nsISupports* aServMgr, const char *fullpath);
+
+typedef nsresult (*nsFactoryProc)(nsISupports* aServMgr,
+ const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory **aFactory);
+typedef PRBool (*nsCanUnloadProc)(nsISupports* aServMgr);
+typedef nsresult (*nsRegisterProc)(nsISupports* aServMgr, const char *path);
+typedef nsresult (*nsUnregisterProc)(nsISupports* aServMgr, const char *path);
+#endif /* OBSOLETE_MODULE_LOADING */
diff --git a/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp b/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp
new file mode 100644
index 00000000..dd6856d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp
@@ -0,0 +1,155 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsComponentManager.h"
+
+extern PRBool gXPCOMShuttingDown;
+
+// Global service manager interface (see nsIServiceManagerObsolete.h)
+
+nsresult
+nsServiceManager::GetGlobalServiceManager(nsIServiceManager* *result)
+{
+ if (gXPCOMShuttingDown)
+ return NS_ERROR_UNEXPECTED;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ // this method does not addref for historical reasons.
+ // we return the nsIServiceManagerObsolete interface via a cast.
+ *result = (nsIServiceManager*) NS_STATIC_CAST(nsIServiceManagerObsolete*,
+ nsComponentManagerImpl::gComponentManager);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::ShutdownGlobalServiceManager(nsIServiceManager* *result)
+{
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->GetService(aClass, aIID, (void**)result);
+}
+
+nsresult
+nsServiceManager::ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::RegisterService(const nsCID& aClass, nsISupports* aService)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->RegisterService(aClass, aService);
+}
+
+nsresult
+nsServiceManager::UnregisterService(const nsCID& aClass)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->UnregisterService(aClass);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// let's do it again, this time with ContractIDs...
+
+nsresult
+nsServiceManager::GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->GetServiceByContractID(aContractID, aIID, (void**)result);
+}
+
+nsresult
+nsServiceManager::ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_RELEASE(service);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::RegisterService(const char* aContractID, nsISupports* aService)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->RegisterService(aContractID, aService);
+}
+
+nsresult
+nsServiceManager::UnregisterService(const char* aContractID)
+{
+ // Don't create the global service manager here because we might
+ // be shutting down, and releasing all the services in its
+ // destructor
+ if (gXPCOMShuttingDown)
+ return NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->UnregisterService(aContractID);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h b/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h
new file mode 100644
index 00000000..c770afdc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIModule.h"
+#include "nsModule.h"
+
+struct nsStaticModuleInfo {
+ const char *name;
+ nsGetModuleProc getModule;
+};
+
+// Must be implemented by some part of the app, if we're building the
+// static component loader.
+extern "C" {
+typedef nsresult (PR_CALLBACK *NSGetStaticModuleInfoFunc)(nsStaticModuleInfo **info, PRUint32 *count);
+extern NS_COM NSGetStaticModuleInfoFunc NSGetStaticModuleInfo;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp b/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp
new file mode 100644
index 00000000..b17b74bb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsStaticComponent.h"
+#include "nsIComponentLoader.h"
+#include "nsVoidArray.h"
+#include "pldhash.h"
+#include NEW_H
+#include <stdio.h>
+
+struct StaticModuleInfo : public PLDHashEntryHdr {
+ nsStaticModuleInfo info;
+ nsCOMPtr<nsIModule> module;
+};
+
+class nsStaticComponentLoader : public nsIComponentLoader
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOMPONENTLOADER
+
+ nsStaticComponentLoader() :
+ mAutoRegistered(PR_FALSE), mLoadedInfo(PR_FALSE) {
+ }
+
+ static NS_HIDDEN_(PLDHashOperator) PR_CALLBACK
+ info_RegisterSelf(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg);
+
+private:
+ ~nsStaticComponentLoader() {
+ if (mInfoHash.ops)
+ PL_DHashTableFinish(&mInfoHash);
+ }
+
+protected:
+ nsresult GetModuleInfo();
+ nsresult GetInfoFor(const char *aLocation, StaticModuleInfo **retval);
+
+ PRBool mAutoRegistered;
+ PRBool mLoadedInfo;
+ nsCOMPtr<nsIComponentManager> mComponentMgr;
+ PLDHashTable mInfoHash;
+ static PLDHashTableOps sInfoHashOps;
+ nsVoidArray mDeferredComponents;
+};
+
+PR_STATIC_CALLBACK(void)
+info_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *, entry);
+ info->module = 0;
+ info->~StaticModuleInfo();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+info_InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
+{
+ // Construct so that our nsCOMPtr is zeroed, etc.
+ new (NS_STATIC_CAST(void *, entry)) StaticModuleInfo();
+ return PR_TRUE;
+}
+
+/* static */ PLDHashTableOps nsStaticComponentLoader::sInfoHashOps = {
+ PL_DHashAllocTable, PL_DHashFreeTable,
+ PL_DHashGetKeyStub, PL_DHashStringKey, PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub, info_ClearEntry,
+ PL_DHashFinalizeStub, info_InitEntry
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsStaticComponentLoader, nsIComponentLoader)
+
+NS_COM NSGetStaticModuleInfoFunc NSGetStaticModuleInfo;
+
+nsresult
+nsStaticComponentLoader::GetModuleInfo()
+{
+ if (mLoadedInfo)
+ return NS_OK;
+
+ if (!mInfoHash.ops) { // creation failed in init, why are we here?
+ NS_WARNING("operating on uninitialized static component loader");
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ if (! NSGetStaticModuleInfo) {
+ // We're a static build with no static modules to
+ // register. This can happen in shared uses (such as the GRE)
+ return NS_OK;
+ }
+
+ nsStaticModuleInfo *infoList;
+ PRUint32 count;
+ nsresult rv;
+ if (NS_FAILED(rv = (*NSGetStaticModuleInfo)(&infoList, &count)))
+ return rv;
+ for (PRUint32 i = 0; i < count; i++) {
+ StaticModuleInfo *info =
+ NS_STATIC_CAST(StaticModuleInfo *,
+ PL_DHashTableOperate(&mInfoHash, infoList[i].name,
+ PL_DHASH_ADD));
+ if (!info)
+ return NS_ERROR_OUT_OF_MEMORY;
+ info->info = infoList[i];
+ }
+
+ mLoadedInfo = PR_TRUE;
+ return NS_OK;
+}
+
+nsresult
+nsStaticComponentLoader::GetInfoFor(const char *aLocation,
+ StaticModuleInfo **retval)
+{
+ nsresult rv;
+ if (NS_FAILED(rv = GetModuleInfo()))
+ return rv;
+
+ StaticModuleInfo *info =
+ NS_STATIC_CAST(StaticModuleInfo *,
+ PL_DHashTableOperate(&mInfoHash, aLocation,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(info))
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ if (!info->module) {
+ rv = info->info.getModule(mComponentMgr, nsnull,
+ getter_AddRefs(info->module));
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: GetInfoFor(\"%s\"): %x\n", aLocation, rv);
+#endif
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ *retval = info;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::Init(nsIComponentManager *mgr, nsISupports *aReg)
+{
+ mComponentMgr = mgr;
+ if (!PL_DHashTableInit(&mInfoHash, &sInfoHashOps, nsnull,
+ sizeof(StaticModuleInfo), 1024)) {
+ mInfoHash.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+PLDHashOperator PR_CALLBACK
+nsStaticComponentLoader::info_RegisterSelf(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ nsStaticComponentLoader *loader = NS_STATIC_CAST(nsStaticComponentLoader *,
+ arg);
+ nsIComponentManager *mgr = loader->mComponentMgr;
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *, hdr);
+
+ nsresult rv;
+ if (!info->module) {
+ rv = info->info.getModule(mgr, nsnull, getter_AddRefs(info->module));
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: getModule(\"%s\"): %x\n", info->info.name, rv);
+#endif
+ if (NS_FAILED(rv))
+ return PL_DHASH_NEXT; // oh well.
+ }
+
+ rv = info->module->RegisterSelf(mgr, nsnull, info->info.name,
+ staticComponentType);
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: autoreg of \"%s\": %x\n", info->info.name, rv);
+#endif
+
+ if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN)
+ loader->mDeferredComponents.AppendElement(info);
+
+ return PL_DHASH_NEXT;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoRegisterComponents(PRInt32 when, nsIFile *dir)
+{
+ if (mAutoRegistered)
+ return NS_OK;
+
+ // if a directory has been explicitly specified, then return early. we
+ // don't load static components from disk ;)
+ if (dir)
+ return NS_OK;
+
+ nsresult rv;
+ if (NS_FAILED(rv = GetModuleInfo()))
+ return rv;
+
+ PL_DHashTableEnumerate(&mInfoHash, info_RegisterSelf, this);
+
+ mAutoRegistered = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *retval)
+{
+ *retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoRegisterComponent(PRInt32 when, nsIFile *component,
+ PRBool *retval)
+{
+ *retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::RegisterDeferredComponents(PRInt32 when,
+ PRBool *aRegistered)
+{
+ *aRegistered = PR_FALSE;
+ if (!mDeferredComponents.Count())
+ return NS_OK;
+
+ for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *,
+ mDeferredComponents[i]);
+ nsresult rv = info->module->RegisterSelf(mComponentMgr, nsnull,
+ info->info.name,
+ staticComponentType);
+ if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ if (NS_SUCCEEDED(rv))
+ *aRegistered = PR_TRUE;
+ mDeferredComponents.RemoveElementAt(i);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::OnRegister(const nsCID &aCID, const char *aType,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLocation,
+ PRBool aReplace, PRBool aPersist)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::GetFactory(const nsCID &aCID, const char *aLocation,
+ const char *aType, nsIFactory **_retval)
+{
+ StaticModuleInfo *info;
+ nsresult rv;
+
+ if (NS_FAILED(rv = GetInfoFor(aLocation, &info)))
+ return rv;
+
+ return info->module->GetClassObject(mComponentMgr, aCID,
+ NS_GET_IID(nsIFactory),
+ (void **)_retval);
+}
+
+nsresult
+NS_NewStaticComponentLoader(nsIComponentLoader **retval)
+{
+ NS_IF_ADDREF(*retval = NS_STATIC_CAST(nsIComponentLoader *,
+ new nsStaticComponentLoader));
+ return *retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/xcDll.cpp b/src/libs/xpcom18a4/xpcom/components/xcDll.cpp
new file mode 100644
index 00000000..494cf174
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/xcDll.cpp
@@ -0,0 +1,457 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsDll
+ *
+ * Abstraction of a Dll. Stores modifiedTime and size for easy detection of
+ * change in dll.
+ *
+ * dp Suresh <dp@netscape.com>
+ */
+
+#include "xcDll.h"
+#include "nsDebug.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentLoaderManager.h"
+#include "nsIModule.h"
+#include "nsILocalFile.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "nsITimelineService.h"
+#include "nsModule.h"
+#ifdef DEBUG
+#if defined(VMS)
+#include <lib$routines.h>
+#include <ssdef.h>
+#elif defined(XP_MACOSX)
+#include <signal.h>
+#endif
+#endif /* defined(DEBUG) */
+
+#include "nsTraceRefcntImpl.h"
+
+#define UNLOAD_DEPENDENT_LIBS
+#ifdef HPUX
+#undef UNLOAD_DEPENDENT_LIBS
+#endif
+
+#include "nsNativeComponentLoader.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include "nsMemory.h"
+#endif
+
+nsDll::nsDll(nsIFile *dllSpec, nsNativeComponentLoader *loader)
+ : m_dllSpec(do_QueryInterface(dllSpec)),
+ m_instance(NULL),
+ m_moduleObject(NULL),
+ m_loader(loader),
+ m_markForUnload(PR_FALSE)
+{
+ NS_ASSERTION(loader, "Null loader when creating a nsDLL");
+}
+
+nsDll::~nsDll(void)
+{
+ //#if DEBUG_dougt
+ // The dll gets deleted when the dllStore is destroyed. This happens on
+ // app shutdown. At that point, unloading dlls can cause crashes if we have
+ // - dll dependencies
+ // - callbacks
+ // - static dtors
+ // Hence turn it back on after all the above have been removed.
+ //Unload();
+ //#endif
+}
+
+void
+nsDll::GetDisplayPath(nsACString& aLeafName)
+{
+ m_dllSpec->GetNativeLeafName(aLeafName);
+
+ if (aLeafName.IsEmpty())
+ aLeafName.AssignLiteral("unknown!");
+}
+
+PRBool
+nsDll::HasChanged()
+{
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
+ if (!manager)
+ return PR_TRUE;
+
+ // If mod date has changed, then dll has changed
+ PRInt64 currentDate;
+ nsresult rv = m_dllSpec->GetLastModifiedTime(&currentDate);
+ if (NS_FAILED(rv))
+ return PR_TRUE;
+ PRBool changed = PR_TRUE;
+ manager->HasFileChanged(m_dllSpec, nsnull, currentDate, &changed);
+ return changed;
+}
+
+PRBool nsDll::Load(void)
+{
+ if (m_instance != NULL)
+ {
+ // Already loaded
+ return (PR_TRUE);
+ }
+
+ if (m_dllSpec)
+ {
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+
+ // Load any library dependencies
+ // The Component Loader Manager may hold onto some extra data
+ // set by either the native component loader or the native
+ // component. We assume that this data is a space delimited
+ // listing of dependent libraries which are required to be
+ // loaded prior to us loading the given component. Once, the
+ // component is loaded into memory, we can release our hold
+ // on the dependent libraries with the assumption that the
+ // component library holds a reference via the OS so loader.
+
+#if defined(XP_UNIX)
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
+ if (!manager)
+ return PR_TRUE;
+
+ nsXPIDLCString extraData;
+ manager->GetOptionalData(m_dllSpec, nsnull, getter_Copies(extraData));
+
+#ifdef UNLOAD_DEPENDENT_LIBS
+ nsVoidArray dependentLibArray;
+#endif
+
+ // if there was any extra data, treat it as a listing of dependent libs
+ if (extraData != nsnull)
+ {
+ // all dependent libraries are suppose to be in the "gre" directory.
+ // note that the gre directory is the same as the "bin" directory,
+ // when there isn't a real "gre" found.
+
+ nsXPIDLCString path;
+ nsCOMPtr<nsIFile> file;
+ NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
+
+ if (!file)
+ return NS_ERROR_FAILURE;
+
+ // we are talking about a file in the GRE dir. Lets append something
+ // stupid right now, so that later we can just set the leaf name.
+ file->AppendNative(NS_LITERAL_CSTRING("dummy"));
+
+# ifdef VBOX_USE_IPRT_IN_XPCOM
+ char *buffer = (char *)nsMemory::Clone(extraData, strlen(extraData) + 1);
+# else
+ char *buffer = strdup(extraData);
+# endif
+ if (!buffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ char* newStr;
+ char *token = nsCRT::strtok(buffer, " ", &newStr);
+ while (token!=nsnull)
+ {
+ nsCStringKey key(token);
+ if (m_loader->mLoadedDependentLibs.Get(&key)) {
+ token = nsCRT::strtok(newStr, " ", &newStr);
+ continue;
+ }
+
+ m_loader->mLoadedDependentLibs.Put(&key, (void*)1);
+
+ nsXPIDLCString libpath;
+ file->SetNativeLeafName(nsDependentCString(token));
+ file->GetNativePath(path);
+ if (!path)
+ return NS_ERROR_FAILURE;
+
+ // Load this dependent library with the global flag and stash
+ // the result for later so that we can unload it.
+ PRLibSpec libSpec;
+ libSpec.type = PR_LibSpec_Pathname;
+
+ // if the depend library path starts with a / we are
+ // going to assume that it is a full path and should
+ // be loaded without prepending the gre diretory
+ // location. We could have short circuited the
+ // SetNativeLeafName above, but this is clearer and
+ // the common case is a relative path.
+
+ if (token[0] == '/')
+ libSpec.value.pathname = token;
+ else
+ libSpec.value.pathname = path;
+
+ PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
+ // if we couldn't load the dependent library. We did the best we
+ // can. Now just let us fail later if this really was a required
+ // dependency.
+#ifdef UNLOAD_DEPENDENT_LIBS
+ if (lib)
+ dependentLibArray.AppendElement((void*)lib);
+#endif
+
+ token = nsCRT::strtok(newStr, " ", &newStr);
+ }
+# ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(buffer);
+# else
+ free(buffer);
+# endif
+ }
+#endif
+
+ // load the component
+ nsCOMPtr<nsILocalFile> lf(do_QueryInterface(m_dllSpec));
+ NS_ASSERTION(lf, "nsIFile here must implement a nsILocalFile");
+ lf->Load(&m_instance);
+
+#if defined(XP_UNIX)
+ // Unload any of library dependencies we loaded earlier. The assumption
+ // here is that the component will have a "internal" reference count to
+ // the dependency library we just loaded.
+ // XXX should we unload later - or even at all?
+
+#ifdef UNLOAD_DEPENDENT_LIBS
+ if (extraData != nsnull)
+ {
+ PRInt32 arrayCount = dependentLibArray.Count();
+ for (PRInt32 index = 0; index < arrayCount; index++)
+ PR_UnloadLibrary((PRLibrary*)dependentLibArray.ElementAt(index));
+ }
+#endif
+#endif
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+ if (m_instance) {
+ // Inform refcnt tracer of new library so that calls through the
+ // new library can be traced.
+ nsXPIDLCString displayPath;
+ GetDisplayPath(displayPath);
+ nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_instance);
+ }
+#endif
+ }
+
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ // Debugging help for components. Component dlls need to have their
+ // symbols loaded before we can put a breakpoint in the debugger.
+ // This will help figureing out the point when the dll was loaded.
+ nsXPIDLCString displayPath;
+ GetDisplayPath(displayPath);
+ BreakAfterLoad(displayPath.get());
+#endif
+
+ return ((m_instance == NULL) ? PR_FALSE : PR_TRUE);
+}
+
+PRBool nsDll::Unload(void)
+{
+ if (m_instance == NULL)
+ return (PR_FALSE);
+
+ // Shutdown the dll
+ Shutdown();
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+ PRStatus ret = PR_UnloadLibrary(m_instance);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+#endif
+
+ if (ret == PR_SUCCESS)
+ {
+ m_instance = NULL;
+ return (PR_TRUE);
+ }
+ else
+ return (PR_FALSE);
+}
+
+void * nsDll::FindSymbol(const char *symbol)
+{
+ if (symbol == NULL)
+ return (NULL);
+
+ // If not already loaded, load it now.
+ if (Load() != PR_TRUE)
+ return (NULL);
+
+ return(PR_FindSymbol(m_instance, symbol));
+}
+
+
+// Component dll specific functions
+nsresult nsDll::GetDllSpec(nsIFile **fsobj)
+{
+ NS_ASSERTION(m_dllSpec, "m_dllSpec NULL");
+ NS_ASSERTION(fsobj, "xcDll::GetModule : Null argument" );
+
+ *fsobj = m_dllSpec;
+ NS_ADDREF(*fsobj);
+ return NS_OK;
+}
+
+nsresult nsDll::GetModule(nsISupports *servMgr, nsIModule **cobj)
+{
+ // using the backpointer of the loader.
+ nsIComponentManager* compMgr = m_loader->mCompMgr;
+ NS_ASSERTION(compMgr, "Global Component Manager is null" );
+ if (!compMgr) return NS_ERROR_UNEXPECTED;
+
+ NS_ASSERTION(cobj, "xcDll::GetModule : Null argument" );
+
+ if (m_moduleObject)
+ {
+ NS_ADDREF(m_moduleObject);
+ *cobj = m_moduleObject;
+ return NS_OK;
+ }
+
+ // If not already loaded, load it now.
+ if (Load() != PR_TRUE) return NS_ERROR_FAILURE;
+
+ // We need a nsIFile for location
+ if (!m_dllSpec)
+ {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsGetModuleProc proc =
+ (nsGetModuleProc) FindSymbol(NS_GET_MODULE_SYMBOL);
+
+ if (proc == NULL)
+ return NS_ERROR_FACTORY_NOT_LOADED;
+
+ nsresult rv = (*proc) (compMgr, m_dllSpec, &m_moduleObject);
+ if (NS_SUCCEEDED(rv))
+ {
+ NS_ADDREF(m_moduleObject);
+ *cobj = m_moduleObject;
+ }
+ return rv;
+}
+
+
+// These are used by BreakAfterLoad, below.
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+static nsCString *sBreakList[16];
+static int sBreakListCount = 0;
+#endif
+
+nsresult nsDll::Shutdown(void)
+{
+ // Release the module object if we got one
+ nsrefcnt refcnt;
+ if (m_moduleObject)
+ {
+ NS_RELEASE2(m_moduleObject, refcnt);
+ NS_ASSERTION(refcnt == 0, "Dll moduleObject refcount non zero");
+ }
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ for (int i = 0; i < sBreakListCount; i++)
+ {
+ delete sBreakList[i];
+ sBreakList[i] = nsnull;
+ }
+ sBreakListCount = 0;
+#endif
+ return NS_OK;
+
+}
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+void nsDll::BreakAfterLoad(const char *nsprPath)
+{
+ static PRBool firstTime = PR_TRUE;
+
+ // return if invalid input
+ if (!nsprPath || !*nsprPath) return;
+
+ // return if nothing to break on
+ if (!firstTime && sBreakListCount == 0) return;
+
+ if (firstTime)
+ {
+ firstTime = PR_FALSE;
+ // Form the list of dlls to break on load
+ nsCAutoString envList(getenv("XPCOM_BREAK_ON_LOAD"));
+ if (envList.IsEmpty()) return;
+ PRInt32 ofset = 0;
+ PRInt32 start = 0;
+ do
+ {
+ ofset = envList.FindChar(':', start);
+ sBreakList[sBreakListCount] = new nsCString();
+ envList.Mid(*(sBreakList[sBreakListCount]), start, ofset);
+ sBreakListCount++;
+ start = ofset + 1;
+ }
+ while (ofset != -1 && 16 > sBreakListCount); // avoiding vc6.0 compiler issue. count < thinks it is starting a template
+ }
+
+ // Find the dllname part of the string
+ nsCString currentPath(nsprPath);
+ PRInt32 lastSep = currentPath.RFindCharInSet(":\\/");
+
+ for (int i=0; i<sBreakListCount; i++)
+ if (currentPath.Find(*(sBreakList[i]), PR_TRUE, lastSep) > 0)
+ {
+ // Loading a dll that we want to break on
+ // Put your breakpoint here
+ fprintf(stderr, "...Loading module %s\n", nsprPath);
+ // Break in the debugger here.
+#if defined(__i386) && defined(__GNUC__)
+ asm("int $3");
+#elif defined(VMS)
+ lib$signal(SS$_DEBUG);
+#elif defined(XP_MACOSX)
+ raise(SIGTRAP);
+#endif
+ }
+ return;
+}
+#endif /* SHOULD_IMPLEMENT_BREAKAFTERLOAD */
diff --git a/src/libs/xpcom18a4/xpcom/components/xcDll.h b/src/libs/xpcom18a4/xpcom/components/xcDll.h
new file mode 100644
index 00000000..5de5b0eb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/xcDll.h
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Dll
+ *
+ * Programmatic representation of a dll. Stores modifiedTime and size for
+ * easy detection of change in dll.
+ *
+ * dp Suresh <dp@netscape.com>
+ */
+
+#ifndef xcDll_h__
+#define xcDll_h__
+
+#include "prio.h"
+#include "prlink.h"
+#include "nsISupports.h"
+#include "nsILocalFile.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+class nsNativeComponentLoader;
+
+#if defined(DEBUG) && !defined(XP_BEOS)
+#define SHOULD_IMPLEMENT_BREAKAFTERLOAD
+#endif
+
+class nsIModule;
+class nsIServiceManager;
+
+typedef enum nsDllStatus
+{
+ DLL_OK = 0,
+ DLL_NO_MEM = 1,
+ DLL_STAT_ERROR = 2,
+ DLL_NOT_FILE = 3,
+ DLL_INVALID_PARAM = 4
+} nsDllStatus;
+
+class nsDll
+{
+private:
+ nsCOMPtr<nsIFile> m_dllSpec;
+ PRLibrary *m_instance;
+ nsIModule *m_moduleObject;
+ nsNativeComponentLoader *m_loader;
+ PRBool m_markForUnload;
+
+ void Init(nsIFile *dllSpec);
+
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ void BreakAfterLoad(const char *nsprPath);
+#endif
+
+public:
+
+ nsDll(nsIFile *dllSpec, nsNativeComponentLoader* loader);
+ ~nsDll(void);
+
+ // Dll Loading
+ PRBool Load(void);
+ PRBool Unload(void);
+ PRBool IsLoaded(void)
+ {
+ return ((m_instance != 0) ? PR_TRUE : PR_FALSE);
+ }
+ void MarkForUnload(PRBool mark) { m_markForUnload = mark; }
+ PRBool IsMarkedForUnload(void) { return m_markForUnload; }
+
+ // Shutdown the dll. This will call any on unload hook for the dll.
+ // This wont unload the dll. Unload() implicitly calls Shutdown().
+ nsresult Shutdown(void);
+
+ void *FindSymbol(const char *symbol);
+
+ PRBool HasChanged(void);
+
+ void GetDisplayPath(nsACString& string);
+
+ PRLibrary *GetInstance(void) { return (m_instance); }
+
+ // NS_RELEASE() is required to be done on objects returned
+ nsresult GetDllSpec(nsIFile **dllSpec);
+ nsresult GetModule(nsISupports *servMgr, nsIModule **mobj);
+};
+
+#endif /* xcDll_h__ */