Bug 298044 - Dynamically load XPCOM dependent libs as part of the XPCOM standalone glue bootstrap process, r=darin a=asa

This commit is contained in:
bsmedberg%covad.net 2005-07-14 18:42:59 +00:00
parent dd4ba30607
commit b9720ffcb9
17 changed files with 612 additions and 289 deletions

View File

@ -649,34 +649,6 @@ endif # IS_COMPONENT
endif # EXPORT_LIBRARY
endif # LIBRARY_NAME
# Dependent libs
ifdef USE_DEPENDENT_LIBS
ifdef IS_COMPONENT
ifeq (,$(filter-out OS2 WINNT,$(OS_ARCH))$(GNU_CXX))
DEPENDENT_LIBS = $(filter-out %_s$(DLL_SUFFIX), $(patsubst %.$(IMPORT_LIB_SUFFIX),$(LIB_PREFIX)%$(DLL_SUFFIX),$(notdir $(filter %.$(IMPORT_LIB_SUFFIX), $(EXTRA_DSO_LDOPTS)))))
else
DEPENDENT_LIBS = $(filter-out %_s$(DLL_SUFFIX), $(patsubst -l%,$(DLL_PREFIX)%$(DLL_SUFFIX),$(filter -l%, $(EXTRA_DSO_LDOPTS))))
endif
ifneq (,$(strip $(DEPENDENT_LIBS)))
DEFINES += -DHAVE_DEPENDENT_LIBS
INCLUDES += -I.
# This must match value in nsIGenericFactory.h
DEPENDENT_LIBS_H = dependentLibs.h
GARBAGE += $(DEPENDENT_LIBS_H)
export:: $(DEPENDENT_LIBS_H)
$(DEPENDENT_LIBS_H): Makefile Makefile.in
@rm -f $@
echo "#define DEPENDENT_LIBS $(foreach f,$(DEPENDENT_LIBS),\"${f}\",) " > $@
endif
endif
endif
# Create dependencies on static libraries
LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(LIBS))
HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(HOST_LIBS))

View File

@ -77,7 +77,6 @@ XPIDLSRCS = \
nsIComponentLoader.idl \
nsIComponentLoaderManager.idl \
nsIComponentManagerObsolete.idl \
nsINativeComponentLoader.idl \
$(NULL)
SDK_XPIDLSRCS = \

View File

@ -952,14 +952,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS8(nsComponentManagerImpl,
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()

View File

@ -79,15 +79,13 @@ DLLStore_Destroy(nsHashKey *aKey, void *aData, void* closure)
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_IMPL_THREADSAFE_ISUPPORTS1(nsNativeComponentLoader,
nsIComponentLoader)
NS_IMETHODIMP
nsNativeComponentLoader::GetFactory(const nsIID & aCID,
@ -419,10 +417,6 @@ nsNativeComponentLoader::SelfRegisterDll(nsDll *dll,
*************************************************************/
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);
}
@ -1063,36 +1057,3 @@ nsNativeComponentLoader::GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
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;
}

View File

@ -43,22 +43,20 @@
#include "nsHashtable.h"
#include "nsVoidArray.h"
#include "xcDll.h"
#include "nsINativeComponentLoader.h"
#ifndef nsNativeComponentLoader_h__
#define nsNativeComponentLoader_h__
class nsNativeComponentLoader : public nsIComponentLoader, public nsINativeComponentLoader {
class nsNativeComponentLoader : public nsIComponentLoader
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICOMPONENTLOADER
NS_DECL_NSINATIVECOMPONENTLOADER
nsNativeComponentLoader();
nsIComponentManager* mCompMgr; // weak reference -- backpointer
nsHashtable mLoadedDependentLibs;
private:
nsObjectHashtable mDllStore;

View File

@ -137,121 +137,11 @@ PRBool nsDll::Load(void)
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"));
char *buffer = strdup(extraData);
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);
}
free(buffer);
}
#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) {

View File

@ -48,9 +48,6 @@
#ifdef XPCOM_GLUE
#include "nsXPCOMGlue.h"
#include "nsXPCOMPrivate.h"
#else
#include "nsIInterfaceRequestorUtils.h"
#include "nsINativeComponentLoader.h"
#endif
nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo *info)
@ -223,16 +220,14 @@ NS_NewGenericFactory(nsIGenericFactory* *result,
nsGenericModule::nsGenericModule(const char* moduleName, PRUint32 componentCount,
const nsModuleComponentInfo* components,
nsModuleConstructorProc ctor,
nsModuleDestructorProc dtor,
const char** aLibDepends)
nsModuleDestructorProc dtor)
: mInitialized(PR_FALSE),
mModuleName(moduleName),
mComponentCount(componentCount),
mComponents(components),
mFactoriesNotToBeRegistered(nsnull),
mCtor(ctor),
mDtor(dtor),
mLibraryDependencies(aLibDepends)
mDtor(dtor)
{
}
@ -433,25 +428,6 @@ nsGenericModule::RegisterSelf(nsIComponentManager *aCompMgr,
cp++;
}
#ifndef XPCOM_GLUE
// We want to tell the component loader of any dependencies
// we have so that the loader can resolve them for us.
nsCOMPtr<nsINativeComponentLoader> loader = do_GetInterface(aCompMgr);
if (loader && mLibraryDependencies)
{
for(int i=0; mLibraryDependencies[i] != nsnull &&
mLibraryDependencies[i][0] != '\0'; i++)
{
loader->AddDependentLibrary(aPath,
mLibraryDependencies[i]);
}
loader = nsnull;
}
#endif
return rv;
}
@ -506,7 +482,7 @@ NS_NewGenericModule2(nsModuleInfo* info, nsIModule* *result)
// Create and initialize the module instance
nsGenericModule *m =
new nsGenericModule(info->mModuleName, info->mCount, info->mComponents,
info->mCtor, info->mDtor, info->mLibraryDependencies);
info->mCtor, info->mDtor);
if (!m)
return NS_ERROR_OUT_OF_MEMORY;
@ -531,7 +507,6 @@ NS_NewGenericModule(const char* moduleName,
info.mComponents = components;
info.mCount = componentCount;
info.mDtor = dtor;
info.mLibraryDependencies = nsnull;
return NS_NewGenericModule2(&info, result);
}

View File

@ -82,8 +82,7 @@ public:
PRUint32 componentCount,
const nsModuleComponentInfo* components,
nsModuleConstructorProc ctor,
nsModuleDestructorProc dtor,
const char** alibDepends);
nsModuleDestructorProc dtor);
private:
~nsGenericModule();
@ -122,7 +121,6 @@ protected:
FactoryNode* mFactoriesNotToBeRegistered;
nsModuleConstructorProc mCtor;
nsModuleDestructorProc mDtor;
const char** mLibraryDependencies;
};
#endif /* nsGenericFactory_h___ */

View File

@ -41,9 +41,6 @@
#include "nsIFactory.h"
#include "nsIModule.h"
#include "nsIClassInfo.h"
#ifdef HAVE_DEPENDENT_LIBS
#include "dependentLibs.h"
#endif
// {3bc97f01-ccdf-11d2-bab8-b548654461fc}
#define NS_GENERICFACTORY_CID \
@ -280,8 +277,6 @@ typedef void (PR_CALLBACK *nsModuleDestructorProc) (nsIModule *self);
* @param mCount : Count of mComponents
* @param mCtor : Module user defined constructor
* @param mDtor : Module user defined destructor
* @param mLibraryDependencies : array of library which this module is
* dependent on.
*
**/
@ -292,7 +287,6 @@ struct nsModuleInfo {
PRUint32 mCount;
nsModuleConstructorProc mCtor;
nsModuleDestructorProc mDtor;
const char** mLibraryDependencies;
};
/**
@ -323,13 +317,9 @@ NS_NewGenericModule(const char* moduleName,
# define NS_MODULEINFO nsModuleInfo
# define NSMODULEINFO(_name) _name##_gModuleInfo
# define NSGETMODULE_ENTRY_POINT(_info)
# define NSDEPENDENT_LIBS(_name) const char* _name##_gDependlibs[]={DEPENDENT_LIBS "\0"};
# define NSDEPENDENT_LIBS_NAME(_name) _name##_gDependlibs
#else
# define NS_MODULEINFO static nsModuleInfo
# define NSMODULEINFO(_name) gModuleInfo
# define NSDEPENDENT_LIBS(_name) static const char* gDependlibs[]={DEPENDENT_LIBS "\0"};
# define NSDEPENDENT_LIBS_NAME(_name) gDependlibs
# define NSGETMODULE_ENTRY_POINT(_info) \
extern "C" NS_EXPORT nsresult \
NSGetModule(nsIComponentManager *servMgr, \
@ -355,8 +345,6 @@ NSGetModule(nsIComponentManager *servMgr, \
#define NS_IMPL_NSGETMODULE_WITH_DTOR(_name, _components, _dtor) \
NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, nsnull, _dtor)
#ifndef DEPENDENT_LIBS
#define NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, _dtor) \
NS_MODULEINFO NSMODULEINFO(_name) = { \
NS_MODULEINFO_VERSION, \
@ -364,28 +352,10 @@ NS_MODULEINFO NSMODULEINFO(_name) = { \
(_components), \
(sizeof(_components) / sizeof(_components[0])), \
(_ctor), \
(_dtor), \
(nsnull) \
(_dtor) \
}; \
NSGETMODULE_ENTRY_POINT(NSMODULEINFO(_name))
#else // DEPENDENT_LIBS
#define NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, _dtor) \
NSDEPENDENT_LIBS(_name) \
NS_MODULEINFO NSMODULEINFO(_name) = { \
NS_MODULEINFO_VERSION, \
(#_name), \
(_components), \
(sizeof(_components) / sizeof(_components[0])), \
(_ctor), \
(_dtor), \
(NSDEPENDENT_LIBS_NAME(_name)) \
}; \
NSGETMODULE_ENTRY_POINT(NSMODULEINFO(_name))
#endif
////////////////////////////////////////////////////////////////////////////////
#define NS_GENERIC_FACTORY_CONSTRUCTOR(_InstanceClass) \

View File

@ -53,10 +53,29 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../build \
$(NULL)
ifeq (Darwin,$(OS_ARCH))
LINKSRC = nsGlueLinkingOSX.cpp
endif
ifeq (WINNT,$(OS_ARCH))
LINKSRC = nsGlueLinkingWin.cpp
endif
ifneq (,$(filter Linux,$(OS_ARCH)))
LINKSRC = nsGlueLinkingDlopen.cpp
endif
ifeq (OS2,$(OS_ARCH))
LINKSRC = nsGlueLinkingOS2.cpp
endif
ifndef LINKSRC
LINKSRC = nsGlueLinkingNull.cpp
$(warning TinderboxPrint:<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=298044">Error: XPCOM Glue</a>)
endif
CPPSRCS = \
$(XPCOM_GLUE_SRC_LCSRCS) \
nsXPCOMGlue.cpp \
nsGREDirServiceProvider.cpp \
$(LINKSRC) \
$(NULL)
SDK_HEADERS = \

View File

@ -0,0 +1,56 @@
/* ***** 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 XPCOM.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef nsGlueLinking_h__
#define nsGlueLinking_h__
#include "nsXPCOMPrivate.h"
#define XPCOM_DEPENDENT_LIBS_LIST "dependentlibs.list"
NS_HIDDEN_(GetFrozenFunctionsFunc)
XPCOMGlueLoad(const char *xpcomFile);
NS_HIDDEN_(void)
XPCOMGlueUnload();
typedef void (*DependentLibsCallback)(const char *aDependentLib);
NS_HIDDEN_(void)
XPCOMGlueLoadDependentLibs(const char *xpcomDir, DependentLibsCallback cb);
#endif // nsGlueLinking_h__

View File

@ -0,0 +1,129 @@
/* -*- Mode: C++; tab-width: 6; 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 XPCOM.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsGlueLinking.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#if defined(SUNOS4) || defined(NEXTSTEP) || \
(defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__)
#define LEADING_UNDERSCORE "_"
#else
#define LEADING_UNDERSCORE
#endif
struct DependentLib
{
void *libHandle;
DependentLib *next;
};
static DependentLib *sTop;
static void
AppendDependentLib(void *libHandle)
{
DependentLib *d = new DependentLib;
if (!d)
return;
d->next = sTop;
d->libHandle = libHandle;
sTop = d;
}
static void
ReadDependentCB(const char *aDependentLib)
{
void *libHandle = dlopen(aDependentLib, RTLD_GLOBAL | RTLD_LAZY);
if (!libHandle)
return;
AppendDependentLib(libHandle);
}
GetFrozenFunctionsFunc
XPCOMGlueLoad(const char *xpcomFile)
{
char xpcomDir[MAXPATHLEN];
if (realpath(xpcomFile, xpcomDir)) {
char *lastSlash = strrchr(xpcomDir, '/');
if (lastSlash) {
*lastSlash = '\0';
XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
}
}
void *libHandle = RTLD_DEFAULT;
if (xpcomFile[0] != '.' || xpcomFile[1] != '\0') {
libHandle = dlopen(xpcomFile, RTLD_GLOBAL | RTLD_LAZY);
if (libHandle) {
AppendDependentLib(libHandle);
}
else {
libHandle = RTLD_DEFAULT;
}
}
GetFrozenFunctionsFunc sym =
(GetFrozenFunctionsFunc) dlsym(libHandle,
LEADING_UNDERSCORE "NS_GetFrozenFunctions");
if (!sym)
XPCOMGlueUnload();
return sym;
}
void
XPCOMGlueUnload()
{
while (sTop) {
dlclose(sTop->libHandle);
DependentLib *temp = sTop;
sTop = sTop->next;
delete temp;
}
}

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 6; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -12,18 +12,19 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
* The Original Code is Mozilla XPCOM.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* 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"),
* 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
@ -35,36 +36,18 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsGlueLinking.h"
interface nsIFile;
#include <stdio.h>
[uuid(10d1a2a2-d816-458d-a4c3-0805ff0f7b31)]
interface nsINativeComponentLoader : nsISupports
GetFrozenFunctionsFunc
XPCOMGlueLoad(const char *xpcomFile)
{
fprintf(stderr, "XPCOM glue dynamic linking is not implemented on this platform!");
return nsnull;
}
/**
* 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);
};
void
XPCOMGlueUnload()
{
}

View File

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 6; 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 XPCOM.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsGlueLinking.h"
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <stdlib.h>
struct DependentLib
{
HMODULE libHandle;
DependentLib *next;
};
static DependentLib *sTop;
static void
AppendDependentLib(HMODULE libHandle)
{
DependentLib *d = new DependentLib;
if (!d)
return;
d->next = sTop;
d->libHandle = libHandle;
sTop = d;
}
static void
ReadDependentCB(const char *aDependentLib)
{
CHAR pszError[_MAX_PATH];
ULONG ulRc = NO_ERROR;
HMODULE h;
ulRc = DosLoadModule(pszError, _MAX_PATH, aDependentLib, &h);
if (ulRc != NO_ERROR)
return;
AppendDependentLib(h);
}
// like strpbrk but finds the *last* char, not the first
static char*
ns_strrpbrk(char *string, const char *strCharSet)
{
char *found = NULL;
for (; *string; ++string) {
for(const char *search = strCharSet; *search; ++search) {
if (*search == *string) {
found = string;
}
}
}
return found;
}
GetFrozenFunctionsFunc
XPCOMGlueLoad(const char *xpcomFile)
{
if (xpcomFile[0] == '.' && xpcomFile[1] == '\0') {
xpcomFile = XPCOM_DLL;
}
else {
char xpcomDir[MAXPATHLEN];
_fullpath(xpcomDir, xpcomFile, sizeof(xpcomDir));
char *lastSlash = ns_strrpbrk(xpcomDir, "/\\");
if (lastSlash) {
*lastSlash = '\0';
XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
}
}
CHAR pszError[_MAX_PATH];
ULONG ulRc = NO_ERROR;
HMODULE h;
ulRc = DosLoadModule(pszError, _MAX_PATH, xpcomFile, &h);
if (ulRc != NO_ERROR)
return nsnull;
AppendDependentLib(h);
ULONG ulrc = NO_ERROR;
GetFrozenFunctionsFunc sym;
ulrc = DosQueryProcAddr(h, 0, "NS_GetFrozenFunctions", &sym);
if (ulrc != NO_ERROR)
XPCOMGlueUnload();
return sym;
}
void
XPCOMGlueUnload()
{
while (sTop) {
DosFreeModule(sTop->libHandle);
DependentLib *temp = sTop;
sTop = sTop->next;
delete temp;
}
}

View File

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 6; 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 XPCOM.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsGlueLinking.h"
#include <mach-o/dyld.h>
#include <sys/param.h>
#include <stdlib.h>
#include <string.h>
static void
ReadDependentCB(const char *aDependentLib)
{
(void) NSAddImage(aDependentLib,
NSADDIMAGE_OPTION_RETURN_ON_ERROR |
NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
}
GetFrozenFunctionsFunc
XPCOMGlueLoad(const char *xpcomFile)
{
if (xpcomFile[0] != '.' || xpcomFile[1] != '\0') {
char xpcomDir[PATH_MAX];
if (realpath(xpcomFile, xpcomDir)) {
char *lastSlash = strrchr(xpcomDir, '/');
if (lastSlash) {
*lastSlash = '\0';
XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
}
}
(void) NSAddImage(xpcomFile,
NSADDIMAGE_OPTION_RETURN_ON_ERROR |
NSADDIMAGE_OPTION_WITH_SEARCHING |
NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
// We don't really care if this fails, as long as we can get
// NS_GetFrozenFunctions below.
}
if (!NSIsSymbolNameDefined("_NS_GetFrozenFunctions"))
return nsnull;
NSSymbol sym = NSLookupAndBindSymbol("_NS_GetFrozenFunctions");
return (GetFrozenFunctionsFunc) NSAddressOfSymbol(sym);
}
void
XPCOMGlueUnload()
{
// nothing to do, since we cannot unload dylibs on OS X
}

View File

@ -0,0 +1,140 @@
/* -*- Mode: C++; tab-width: 6; 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 XPCOM.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsGlueLinking.h"
#include <windows.h>
#include <stdlib.h>
struct DependentLib
{
HINSTANCE libHandle;
DependentLib *next;
};
static DependentLib *sTop;
static void
AppendDependentLib(HINSTANCE libHandle)
{
DependentLib *d = new DependentLib;
if (!d)
return;
d->next = sTop;
d->libHandle = libHandle;
sTop = d;
}
static void
ReadDependentCB(const char *aDependentLib)
{
HINSTANCE h =
LoadLibraryEx(aDependentLib, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!h)
return;
AppendDependentLib(h);
}
// like strpbrk but finds the *last* char, not the first
static char*
ns_strrpbrk(char *string, const char *strCharSet)
{
char *found = NULL;
for (; *string; ++string) {
for (const char *search = strCharSet; *search; ++search) {
if (*search == *string) {
found = string;
// Since we're looking for the last char, we save "found"
// until we're at the end of the string.
}
}
}
return found;
}
GetFrozenFunctionsFunc
XPCOMGlueLoad(const char *xpcomFile)
{
if (xpcomFile[0] == '.' && xpcomFile[1] == '\0') {
xpcomFile = XPCOM_DLL;
}
else {
char xpcomDir[MAXPATHLEN];
_fullpath(xpcomDir, xpcomFile, sizeof(xpcomDir));
char *lastSlash = ns_strrpbrk(xpcomDir, "/\\");
if (lastSlash) {
*lastSlash = '\0';
XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
}
}
HINSTANCE h =
LoadLibraryEx(xpcomFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!h)
return nsnull;
AppendDependentLib(h);
GetFrozenFunctionsFunc sym =
(GetFrozenFunctionsFunc) GetProcAddress(h, "NS_GetFrozenFunctions");
if (!sym)
XPCOMGlueUnload();
return sym;
}
void
XPCOMGlueUnload()
{
while (sTop) {
FreeLibrary(sTop->libHandle);
DependentLib *temp = sTop;
sTop = sTop->next;
delete temp;
}
}

View File

@ -45,6 +45,10 @@ include $(DEPTH)/config/autoconf.mk
MODULE = xpcom
LIBRARY_NAME = xpcom
# The XPCOM glue uses realpath() on libxpcom.so to resolve any symlinks. We
# want it to find dist/bin and not xpcom/stub so we copy instead of symlinking.
NSDISTMODE = copy
PACKAGE_FILE = xpcom.pkg
PACKAGE_VARS += USE_SHORT_LIBNAME