diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/libs/xpcom18a4/xpcom/glue | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/glue')
29 files changed, 7605 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/glue/.cvsignore b/src/libs/xpcom18a4/xpcom/glue/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/glue/Makefile.in b/src/libs/xpcom18a4/xpcom/glue/Makefile.in new file mode 100644 index 00000000..a3b1f24d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/Makefile.in @@ -0,0 +1,86 @@ +# ***** 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) 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 ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk +include $(srcdir)/objs.mk + +DIRS = standalone + +MODULE = xpcom +LIBRARY_NAME = xpcomglue_s + +REQUIRES = $(NULL) + +LOCAL_INCLUDES = \ + -I$(srcdir)/../build \ + $(NULL) + +CPPSRCS = \ + $(XPCOM_GLUE_SRC_LCSRCS) \ + $(NULL) + +SDK_HEADERS = \ + nsIGenericFactory.h \ + nsIInterfaceRequestorUtils.h \ + nsISupportsImpl.h \ + nsISupportsUtils.h \ + nsIWeakReferenceUtils.h \ + $(XPCOM_GLUE_SRC_LEXPORTS) \ + $(NULL) + +SDK_LIBRARY = \ + $(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \ + $(NULL) + +# 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 + +# hack to work around objdir bustage +export:: + rm -f $(XPCOM_GLUE_SRC_CSRCS:.cpp=.$(OBJ_SUFFIX)) + +DEFINES += \ + -D_IMPL_NS_COM diff --git a/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp new file mode 100644 index 00000000..cac3c6d4 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp @@ -0,0 +1,124 @@ +/* -*- 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): + * 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 ***** */ + +#include "nsCOMPtr.h" + +nsresult +nsQueryInterface::operator()( const nsIID& aIID, void** answer ) const + { + nsresult status; + if ( mRawPtr ) + { + status = mRawPtr->QueryInterface(aIID, answer); +#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS + NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?"); +#endif + } + else + status = NS_ERROR_NULL_POINTER; + + return status; + } + +nsresult +nsQueryInterfaceWithError::operator()( const nsIID& aIID, void** answer ) const + { + nsresult status; + if ( mRawPtr ) + { + status = mRawPtr->QueryInterface(aIID, answer); +#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS + NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?"); +#endif + } + else + status = NS_ERROR_NULL_POINTER; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; + } + +nsCOMPtr_base::~nsCOMPtr_base() + { + NSCAP_LOG_RELEASE(this, mRawPtr); + if ( mRawPtr ) + NSCAP_RELEASE(this, mRawPtr); + } + +void +nsCOMPtr_base::assign_with_AddRef( nsISupports* rawPtr ) + { + if ( rawPtr ) + NSCAP_ADDREF(this, rawPtr); + assign_assuming_AddRef(rawPtr); + } + +void +nsCOMPtr_base::assign_from_qi( const nsQueryInterface qi, const nsIID& iid ) + { + nsISupports* newRawPtr; + if ( NS_FAILED( qi(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) + newRawPtr = 0; + assign_assuming_AddRef(newRawPtr); + } + +void +nsCOMPtr_base::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& iid ) + { + nsISupports* newRawPtr; + if ( NS_FAILED( qi(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) + newRawPtr = 0; + assign_assuming_AddRef(newRawPtr); + } + +void +nsCOMPtr_base::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& iid ) + { + nsISupports* newRawPtr; + if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) + newRawPtr = 0; + assign_assuming_AddRef(newRawPtr); + } + +void** +nsCOMPtr_base::begin_assignment() + { + assign_assuming_AddRef(0); + return NS_REINTERPRET_CAST(void**, &mRawPtr); + } diff --git a/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h new file mode 100644 index 00000000..b5a0fd78 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h @@ -0,0 +1,1405 @@ +/* -*- 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): + * Scott Collins <scc@mozilla.org> (original author) + * L. David Baron <dbaron@dbaron.org> + * + * 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 nsCOMPtr_h___ +#define nsCOMPtr_h___ + +/* + Having problems? + + See the User Manual at: + http://www.mozilla.org/projects/xpcom/nsCOMPtr.html + + + nsCOMPtr + better than a raw pointer + for owning objects + -- scc +*/ + + + // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design") +#ifndef nsDebug_h___ +#include "nsDebug.h" + // for |NS_PRECONDITION| +#endif + +#ifndef nsISupportsUtils_h__ +#include "nsISupportsUtils.h" + // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al +#endif + +#ifndef nscore_h___ +#include "nscore.h" + // for |NS_..._CAST|, |NS_COM| +#endif + + +/* + WARNING: + This file defines several macros for internal use only. These macros begin with the + prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use + only for cross-platform compatibility, and are subject to change without notice. +*/ + + +#ifdef _MSC_VER + #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT + // under VC++, we win by inlining StartAssignment + + // Also under VC++, at the highest warning level, we are overwhelmed with warnings + // about (unused) inline functions being removed. This is to be expected with + // templates, so we disable the warning. + #pragma warning( disable: 4514 ) +#endif + +#define NSCAP_FEATURE_USE_BASE + +#ifdef NS_DEBUG + #define NSCAP_FEATURE_TEST_DONTQUERY_CASES + #undef NSCAP_FEATURE_USE_BASE +//#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS +#endif + + /* + |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is + problematic on a select few of our platforms, e.g., QNX. Therefore, I'm providing + a mechanism by which these features can be explicitly disabled from the command-line. + */ + +#ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES + #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) + // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing + // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher + // don't reorder instructions based on aliasing assumptions for + // this variable. Fortunately, gcc versions < 3.3 do not do any + // optimizations that break nsCOMPtr. + + #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__)) +#else + #define NS_MAY_ALIAS_PTR(t) t* +#endif + +#if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES) + #define NSCAP_FEATURE_USE_BASE +#endif + + +#ifdef HAVE_CPP_BOOL + typedef bool NSCAP_BOOL; +#else + typedef PRBool NSCAP_BOOL; +#endif + + + + + /* + The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|) + allow external clients the ability to add logging or other interesting debug facilities. + In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you + provide (e.g., in "nsTraceRefcnt.h") suitable definitions + + #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr) + #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr) + */ + +#ifndef NSCAP_ADDREF + #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef() +#endif + +#ifndef NSCAP_RELEASE + #define NSCAP_RELEASE(this, ptr) (ptr)->Release() +#endif + + // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging. +#ifdef NSCAP_LOG_ASSIGNMENT + // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know + // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into + // the |nsCOMPtr|. + #define NSCAP_LOG_EXTERNAL_ASSIGNMENT +#else + // ...otherwise, just strip it out of the code + #define NSCAP_LOG_ASSIGNMENT(this, ptr) +#endif + +#ifndef NSCAP_LOG_RELEASE + #define NSCAP_LOG_RELEASE(this, ptr) +#endif + + + + + /* + WARNING: + VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined + in an order that satisfies: + + nsDerivedSafe < nsCOMPtr + already_AddRefed < nsCOMPtr + nsCOMPtr < nsGetterAddRefs + + The other compilers probably won't complain, so please don't reorder these + classes, on pain of breaking 4.2 compatibility. + */ + + +template <class T> +class nsDerivedSafe : public T + /* + No client should ever see or have to type the name of this class. It is the + artifact that makes it a compile-time error to call |AddRef| and |Release| + on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. + + See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al. + + This type should be a nested class inside |nsCOMPtr<T>|. + */ + { + private: +#ifdef HAVE_CPP_ACCESS_CHANGING_USING + using T::AddRef; + using T::Release; +#else + nsrefcnt AddRef(void); + nsrefcnt Release(void); +#endif + +#if !defined(AIX) && !defined(IRIX) + void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED + // declaring |operator delete| private makes calling delete on an interface pointer a compile error +#endif + + nsDerivedSafe<T>& operator=( const T& ); // NOT TO BE IMPLEMENTED + // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one + + /* + Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=(). + If you see that, that means somebody checked in a [XP]COM interface class that declares an + |operator=()|, and that's _bad_. So bad, in fact, that this declaration exists explicitly + to stop people from doing it. + */ + + protected: + nsDerivedSafe(); // NOT TO BE IMPLEMENTED + /* + This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the + default ctor but inheriting classes without an empty ctor. See bug 209667. + */ + }; + +#if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS) +template <class T> +nsrefcnt +nsDerivedSafe<T>::AddRef() + { + return 0; + } + +template <class T> +nsrefcnt +nsDerivedSafe<T>::Release() + { + return 0; + } + +#endif + + + +template <class T> +struct already_AddRefed + /* + ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_ + |AddRef|ing it. You might want to use this as a return type from a function + that produces an already |AddRef|ed pointer as a result. + + See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|. + + This type should be a nested class inside |nsCOMPtr<T>|. + + Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to + avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest + case, and perhaps worth the savings in time and space that its specific + implementation affords over the more general solution offered by + |nsCOMPtr_helper|. + */ + { + already_AddRefed( T* aRawPtr ) + : mRawPtr(aRawPtr) + { + // nothing else to do here + } + + T* get() const { return mRawPtr; } + + T* mRawPtr; + }; + +template <class T> +inline +const already_AddRefed<T> +getter_AddRefs( T* aRawPtr ) + /* + ...makes typing easier, because it deduces the template type, e.g., + you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|. + */ + { + return already_AddRefed<T>(aRawPtr); + } + +template <class T> +inline +const already_AddRefed<T> +getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr ) + { + return aAlreadyAddRefedPtr; + } + +template <class T> +inline +const already_AddRefed<T> +dont_AddRef( T* aRawPtr ) + { + return already_AddRefed<T>(aRawPtr); + } + +template <class T> +inline +const already_AddRefed<T> +dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr ) + { + return aAlreadyAddRefedPtr; + } + + + +class nsCOMPtr_helper + /* + An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms + that are more convenient to call, and more efficient to use with |nsCOMPtr|s. + Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc. + + Here are the rules for a helper: + - it implements |operator()| to produce an interface pointer + - (except for its name) |operator()| is a valid [XP]COM `getter' + - the interface pointer that it returns is already |AddRef()|ed (as from any good getter) + - it matches the type requested with the supplied |nsIID| argument + - its constructor provides an optional |nsresult*| that |operator()| can fill + in with an error when it is executed + + See |class nsGetInterface| for an example. + */ + { + public: + virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0; + }; + +/* + |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to + avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface| + is called often enough that the codesize savings are big enough to + warrant the specialcasing. +*/ + +class NS_COM nsQueryInterface + { + public: + nsQueryInterface( nsISupports* aRawPtr ) + : mRawPtr(aRawPtr) + { + // nothing else to do here + } + + nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const; + + private: + nsISupports* mRawPtr; + }; + +class NS_COM nsQueryInterfaceWithError + { + public: + nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error ) + : mRawPtr(aRawPtr), + mErrorPtr(error) + { + // nothing else to do here + } + + nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const; + + private: + nsISupports* mRawPtr; + nsresult* mErrorPtr; + }; + +inline +nsQueryInterface +do_QueryInterface( nsISupports* aRawPtr ) + { + return nsQueryInterface(aRawPtr); + } + +inline +nsQueryInterfaceWithError +do_QueryInterface( nsISupports* aRawPtr, nsresult* error ) + { + return nsQueryInterfaceWithError(aRawPtr, error); + } + +template <class T> +inline +void +do_QueryInterface( already_AddRefed<T>& ) + { + // This signature exists soley to _stop_ you from doing the bad thing. + // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by + // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>. + } + +template <class T> +inline +void +do_QueryInterface( already_AddRefed<T>&, nsresult* ) + { + // This signature exists soley to _stop_ you from doing the bad thing. + // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by + // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>. + } + + + +class nsCOMPtr_base + /* + ...factors implementation for all template versions of |nsCOMPtr|. + + This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work + because unlike the + + Here's the way people normally do things like this + + template <class T> class Foo { ... }; + template <> class Foo<void*> { ... }; + template <class T> class Foo<T*> : private Foo<void*> { ... }; + */ + { + public: + + nsCOMPtr_base( nsISupports* rawPtr = 0 ) + : mRawPtr(rawPtr) + { + // nothing else to do here + } + + NS_COM NS_FASTCALL ~nsCOMPtr_base(); + + NS_COM void NS_FASTCALL assign_with_AddRef( nsISupports* ); + NS_COM void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& ); + NS_COM void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& ); + NS_COM void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& ); + NS_COM void** NS_FASTCALL begin_assignment(); + + protected: + NS_MAY_ALIAS_PTR(nsISupports) mRawPtr; + + void + assign_assuming_AddRef( nsISupports* newPtr ) + { + /* + |AddRef()|ing the new value (before entering this function) before + |Release()|ing the old lets us safely ignore the self-assignment case. + We must, however, be careful only to |Release()| _after_ doing the + assignment, in case the |Release()| leads to our _own_ destruction, + which would, in turn, cause an incorrect second |Release()| of our old + pointer. Thank <waterson@netscape.com> for discovering this. + */ + nsISupports* oldPtr = mRawPtr; + mRawPtr = newPtr; + NSCAP_LOG_ASSIGNMENT(this, newPtr); + NSCAP_LOG_RELEASE(this, oldPtr); + if ( oldPtr ) + NSCAP_RELEASE(this, oldPtr); + } + }; + +// template <class T> class nsGetterAddRefs; + +template <class T> +class nsCOMPtr +#ifdef NSCAP_FEATURE_USE_BASE + : private nsCOMPtr_base +#endif + { + +#ifdef NSCAP_FEATURE_USE_BASE + #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x) +#else + #define NSCAP_CTOR_BASE(x) mRawPtr(x) + + private: + void assign_with_AddRef( nsISupports* ); + void assign_from_qi( const nsQueryInterface, const nsIID& ); + void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& ); + void assign_from_helper( const nsCOMPtr_helper&, const nsIID& ); + void** begin_assignment(); + + void + assign_assuming_AddRef( T* newPtr ) + { + T* oldPtr = mRawPtr; + mRawPtr = newPtr; + NSCAP_LOG_ASSIGNMENT(this, newPtr); + NSCAP_LOG_RELEASE(this, oldPtr); + if ( oldPtr ) + NSCAP_RELEASE(this, oldPtr); + } + + private: + T* mRawPtr; +#endif + + public: + typedef T element_type; + +#ifndef NSCAP_FEATURE_USE_BASE + ~nsCOMPtr() + { + NSCAP_LOG_RELEASE(this, mRawPtr); + if ( mRawPtr ) + NSCAP_RELEASE(this, mRawPtr); + } +#endif + +#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES + void + Assert_NoQueryNeeded() + { + if ( mRawPtr ) + { + nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) ); + NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed"); + } + } + + #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded(); +#else + #define NSCAP_ASSERT_NO_QUERY_NEEDED() +#endif + + + // Constructors + + nsCOMPtr() + : NSCAP_CTOR_BASE(0) + // default constructor + { + NSCAP_LOG_ASSIGNMENT(this, 0); + } + + nsCOMPtr( const nsCOMPtr<T>& aSmartPtr ) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) + // copy-constructor + { + if ( mRawPtr ) + NSCAP_ADDREF(this, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); + } + + nsCOMPtr( T* aRawPtr ) + : NSCAP_CTOR_BASE(aRawPtr) + // construct from a raw pointer (of the right type) + { + if ( mRawPtr ) + NSCAP_ADDREF(this, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, aRawPtr); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + nsCOMPtr( const already_AddRefed<T>& aSmartPtr ) + : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr) + // construct from |dont_AddRef(expr)| + { + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + nsCOMPtr( const nsQueryInterface qi ) + : NSCAP_CTOR_BASE(0) + // construct from |do_QueryInterface(expr)| + { + NSCAP_LOG_ASSIGNMENT(this, 0); + assign_from_qi(qi, NS_GET_IID(T)); + } + + nsCOMPtr( const nsQueryInterfaceWithError& qi ) + : NSCAP_CTOR_BASE(0) + // construct from |do_QueryInterface(expr, &rv)| + { + NSCAP_LOG_ASSIGNMENT(this, 0); + assign_from_qi_with_error(qi, NS_GET_IID(T)); + } + + nsCOMPtr( const nsCOMPtr_helper& helper ) + : NSCAP_CTOR_BASE(0) + // ...and finally, anything else we might need to construct from + // can exploit the |nsCOMPtr_helper| facility + { + NSCAP_LOG_ASSIGNMENT(this, 0); + assign_from_helper(helper, NS_GET_IID(T)); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + + // Assignment operators + + nsCOMPtr<T>& + operator=( const nsCOMPtr<T>& rhs ) + // copy assignment operator + { + assign_with_AddRef(rhs.mRawPtr); + return *this; + } + + nsCOMPtr<T>& + operator=( T* rhs ) + // assign from a raw pointer (of the right type) + { + assign_with_AddRef(rhs); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + return *this; + } + + nsCOMPtr<T>& + operator=( const already_AddRefed<T>& rhs ) + // assign from |dont_AddRef(expr)| + { + assign_assuming_AddRef(rhs.mRawPtr); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + return *this; + } + + nsCOMPtr<T>& + operator=( const nsQueryInterface rhs ) + // assign from |do_QueryInterface(expr)| + { + assign_from_qi(rhs, NS_GET_IID(T)); + return *this; + } + + nsCOMPtr<T>& + operator=( const nsQueryInterfaceWithError& rhs ) + // assign from |do_QueryInterface(expr, &rv)| + { + assign_from_qi_with_error(rhs, NS_GET_IID(T)); + return *this; + } + + nsCOMPtr<T>& + operator=( const nsCOMPtr_helper& rhs ) + // ...and finally, anything else we might need to assign from + // can exploit the |nsCOMPtr_helper| facility. + { + assign_from_helper(rhs, NS_GET_IID(T)); + NSCAP_ASSERT_NO_QUERY_NEEDED(); + return *this; + } + + void + swap( nsCOMPtr<T>& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { +#ifdef NSCAP_FEATURE_USE_BASE + nsISupports* temp = rhs.mRawPtr; +#else + T* temp = rhs.mRawPtr; +#endif + NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + NSCAP_LOG_RELEASE(&rhs, temp); + rhs.mRawPtr = mRawPtr; + mRawPtr = temp; + // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED| + } + + void + swap( T*& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { +#ifdef NSCAP_FEATURE_USE_BASE + nsISupports* temp = rhs; +#else + T* temp = rhs; +#endif + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + rhs = NS_REINTERPRET_CAST(T*, mRawPtr); + mRawPtr = temp; + NSCAP_ASSERT_NO_QUERY_NEEDED(); + } + + + // Other pointer operators + + nsDerivedSafe<T>* + get() const + /* + Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|. + Use |get()| _only_ to resolve ambiguity. + + Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|. + */ + { + return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr); + } + + operator nsDerivedSafe<T>*() const + /* + ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|, + and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator + that makes an |nsCOMPtr| substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity. + */ + { + return get(); + } + + nsDerivedSafe<T>* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->()."); + return get(); + } + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + // broken version for IRIX + + nsCOMPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return NS_CONST_CAST(nsCOMPtr<T>*, this); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + nsCOMPtr<T>* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsCOMPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + public: + nsDerivedSafe<T>& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*()."); + return *get(); + } + +#if 0 + private: + friend class nsGetterAddRefs<T>; +#endif + + T** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return NS_REINTERPRET_CAST(T**, begin_assignment()); +#else + assign_assuming_AddRef(0); + return NS_REINTERPRET_CAST(T**, &mRawPtr); +#endif + } + }; + + + + /* + Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the + same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing + to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able + to point to the single [XP]COM-correct |nsISupports| instance within an object; extra + querying ensues. Clients need to be able to pass around arbitrary interface pointers, + without hassles, through intermediary code that doesn't know the exact type. + */ + +NS_SPECIALIZE_TEMPLATE +class nsCOMPtr<nsISupports> + : private nsCOMPtr_base + { + public: + typedef nsISupports element_type; + + // Constructors + + nsCOMPtr() + : nsCOMPtr_base(0) + // default constructor + { + NSCAP_LOG_ASSIGNMENT(this, 0); + } + + nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr ) + : nsCOMPtr_base(aSmartPtr.mRawPtr) + // copy constructor + { + if ( mRawPtr ) + NSCAP_ADDREF(this, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); + } + + nsCOMPtr( nsISupports* aRawPtr ) + : nsCOMPtr_base(aRawPtr) + // construct from a raw pointer (of the right type) + { + if ( mRawPtr ) + NSCAP_ADDREF(this, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, aRawPtr); + } + + nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr ) + : nsCOMPtr_base(aSmartPtr.mRawPtr) + // construct from |dont_AddRef(expr)| + { + NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr); + } + + nsCOMPtr( const nsQueryInterface qi ) + : nsCOMPtr_base(0) + // assign from |do_QueryInterface(expr)| + { + NSCAP_LOG_ASSIGNMENT(this, 0); + assign_from_qi(qi, NS_GET_IID(nsISupports)); + } + + nsCOMPtr( const nsQueryInterfaceWithError& qi ) + : nsCOMPtr_base(0) + // assign from |do_QueryInterface(expr, &rv)| + { + NSCAP_LOG_ASSIGNMENT(this, 0); + assign_from_qi_with_error(qi, NS_GET_IID(nsISupports)); + } + + nsCOMPtr( const nsCOMPtr_helper& helper ) + : nsCOMPtr_base(0) + // ...and finally, anything else we might need to construct from + // can exploit the |nsCOMPtr_helper| facility + { + NSCAP_LOG_ASSIGNMENT(this, 0); + assign_from_helper(helper, NS_GET_IID(nsISupports)); + } + + + // Assignment operators + + nsCOMPtr<nsISupports>& + operator=( const nsCOMPtr<nsISupports>& rhs ) + // copy assignment operator + { + assign_with_AddRef(rhs.mRawPtr); + return *this; + } + + nsCOMPtr<nsISupports>& + operator=( nsISupports* rhs ) + // assign from a raw pointer (of the right type) + { + assign_with_AddRef(rhs); + return *this; + } + + nsCOMPtr<nsISupports>& + operator=( const already_AddRefed<nsISupports>& rhs ) + // assign from |dont_AddRef(expr)| + { + assign_assuming_AddRef(rhs.mRawPtr); + return *this; + } + + nsCOMPtr<nsISupports>& + operator=( const nsQueryInterface rhs ) + // assign from |do_QueryInterface(expr)| + { + assign_from_qi(rhs, NS_GET_IID(nsISupports)); + return *this; + } + + nsCOMPtr<nsISupports>& + operator=( const nsQueryInterfaceWithError& rhs ) + // assign from |do_QueryInterface(expr, &rv)| + { + assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports)); + return *this; + } + + nsCOMPtr<nsISupports>& + operator=( const nsCOMPtr_helper& rhs ) + // ...and finally, anything else we might need to assign from + // can exploit the |nsCOMPtr_helper| facility. + { + assign_from_helper(rhs, NS_GET_IID(nsISupports)); + return *this; + } + + void + swap( nsCOMPtr<nsISupports>& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + nsISupports* temp = rhs.mRawPtr; + NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr); + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + NSCAP_LOG_RELEASE(&rhs, temp); + rhs.mRawPtr = mRawPtr; + mRawPtr = temp; + } + + void + swap( nsISupports*& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + nsISupports* temp = rhs; + NSCAP_LOG_ASSIGNMENT(this, temp); + NSCAP_LOG_RELEASE(this, mRawPtr); + rhs = mRawPtr; + mRawPtr = temp; + } + + + // Other pointer operators + + nsDerivedSafe<nsISupports>* + get() const + /* + Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|. + Use |get()| _only_ to resolve ambiguity. + + Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|. + */ + { + return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr); + } + + operator nsDerivedSafe<nsISupports>*() const + /* + ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|, + and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator + that makes an |nsCOMPtr| substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity. + */ + { + return get(); + } + + nsDerivedSafe<nsISupports>* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->()."); + return get(); + } + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + // broken version for IRIX + + nsCOMPtr<nsISupports>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + nsCOMPtr<nsISupports>* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsCOMPtr<nsISupports>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + public: + + nsDerivedSafe<nsISupports>& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*()."); + return *get(); + } + +#if 0 + private: + friend class nsGetterAddRefs<nsISupports>; +#endif + + nsISupports** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return NS_REINTERPRET_CAST(nsISupports**, begin_assignment()); +#else + assign_assuming_AddRef(0); + return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr); +#endif + } + }; + +#ifndef NSCAP_FEATURE_USE_BASE +template <class T> +void +nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr ) + { + if ( rawPtr ) + NSCAP_ADDREF(this, rawPtr); + assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr)); + } + +template <class T> +void +nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID ) + { + T* newRawPtr; + if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) + newRawPtr = 0; + assign_assuming_AddRef(newRawPtr); + } + +template <class T> +void +nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID ) + { + T* newRawPtr; + if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) + newRawPtr = 0; + assign_assuming_AddRef(newRawPtr); + } + +template <class T> +void +nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID ) + { + T* newRawPtr; + if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) + newRawPtr = 0; + assign_assuming_AddRef(newRawPtr); + } + +template <class T> +void** +nsCOMPtr<T>::begin_assignment() + { + assign_assuming_AddRef(0); + return NS_REINTERPRET_CAST(void**, &mRawPtr); + } +#endif + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + +// This is the broken version for IRIX, which can't handle the version below. + +template <class T> +inline +nsCOMPtr<T>* +address_of( const nsCOMPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +inline +nsCOMPtr<T>* +address_of( nsCOMPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +template <class T> +inline +const nsCOMPtr<T>* +address_of( const nsCOMPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +class nsGetterAddRefs + /* + ... + + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + + nsCOMPtr<IFoo> fooP; + ...->QueryInterface(iid, getter_AddRefs(fooP)) + + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. + + When initialized with a |nsCOMPtr|, as in the example above, it returns + a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this + case) can fill in. + + This type should be a nested class inside |nsCOMPtr<T>|. + */ + { + public: + explicit + nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + +#if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT) + ~nsGetterAddRefs() + { +#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT + NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get()); +#endif + +#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES + mTargetSmartPtr.Assert_NoQueryNeeded(); +#endif + } +#endif + + operator void**() + { + return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment()); + } + + operator nsISupports**() + { + return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment()); + } + + operator T**() + { + return mTargetSmartPtr.StartAssignment(); + } + + T*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsCOMPtr<T>& mTargetSmartPtr; + }; + + +NS_SPECIALIZE_TEMPLATE +class nsGetterAddRefs<nsISupports> + { + public: + explicit + nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + +#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT + ~nsGetterAddRefs() + { + NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get()); + } +#endif + + operator void**() + { + return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment()); + } + + operator nsISupports**() + { + return mTargetSmartPtr.StartAssignment(); + } + + nsISupports*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsCOMPtr<nsISupports>& mTargetSmartPtr; + }; + + +template <class T> +inline +nsGetterAddRefs<T> +getter_AddRefs( nsCOMPtr<T>& aSmartPtr ) + /* + Used around a |nsCOMPtr| when + ...makes the class |nsGetterAddRefs<T>| invisible. + */ + { + return nsGetterAddRefs<T>(aSmartPtr); + } + + + + // Comparing two |nsCOMPtr|s + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get()); + } + + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get()); + } + + + // Comparing an |nsCOMPtr| to a raw pointer + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsCOMPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == rhs; + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const U* lhs, const nsCOMPtr<T>& rhs ) + { + return lhs == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsCOMPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != rhs; + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const U* lhs, const nsCOMPtr<T>& rhs ) + { + return lhs != NS_STATIC_CAST(const T*, rhs.get()); + } + + // To avoid ambiguities caused by the presence of builtin |operator==|s + // creating a situation where one of the |operator==| defined above + // has a better conversion for one argument and the builtin has a + // better conversion for the other argument, define additional + // |operator==| without the |const| on the raw pointer. + // See bug 65664 for details. + +// This is defined by an autoconf test, but VC++ also has a bug that +// prevents us from using these. (It also, fortunately, has the bug +// that we don't need them either.) +#if defined(_MSC_VER) && (_MSC_VER < 1310) +#define NSCAP_DONT_PROVIDE_NONCONST_OPEQ +#endif + +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsCOMPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( U* lhs, const nsCOMPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsCOMPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( U* lhs, const nsCOMPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get()); + } +#endif + + + + // Comparing an |nsCOMPtr| to |0| + +class NSCAP_Zero; + +template <class T> +inline +NSCAP_BOOL +operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr != 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs ) + // specifically to allow |0 != smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get()); + } + + +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO + + // We need to explicitly define comparison operators for `int' + // because the compiler is lame. + +template <class T> +inline +NSCAP_BOOL +operator==( const nsCOMPtr<T>& lhs, int rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( int lhs, const nsCOMPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) + + // Comparing any two [XP]COM objects for identity + +inline +NSCAP_BOOL +SameCOMIdentity( nsISupports* lhs, nsISupports* rhs ) + { + return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) ); + } + + + +template <class SourceType, class DestinationType> +inline +nsresult +CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr ) + { + return CallQueryInterface(aSourcePtr.get(), aDestPtr); + } + +#endif // !defined(nsCOMPtr_h___) diff --git a/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp b/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp new file mode 100644 index 00000000..5733fc36 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp @@ -0,0 +1,133 @@ +/* -*- 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 nsXPCOM_h__ +#include "nsXPCOM.h" +#endif + +#ifndef nsCOMPtr_h__ +#include "nsCOMPtr.h" +#endif + +#include "nsComponentManagerUtils.h" +#include "nsIServiceManagerUtils.h" + +nsresult +nsCreateInstanceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const +{ + nsCOMPtr<nsIComponentManager> compMgr; + nsresult status = NS_GetComponentManager(getter_AddRefs(compMgr)); + if (compMgr) + status = compMgr->CreateInstance(mCID, mOuter, aIID, aInstancePtr); + else if (NS_SUCCEEDED(status)) + status = NS_ERROR_UNEXPECTED; + + if ( NS_FAILED(status) ) + *aInstancePtr = 0; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; +} + +nsresult +nsCreateInstanceByContractID::operator()( const nsIID& aIID, void** aInstancePtr ) const +{ + nsresult status; + if ( mContractID ) { + nsCOMPtr<nsIComponentManager> compMgr; + status = NS_GetComponentManager(getter_AddRefs(compMgr)); + if (compMgr) + status = compMgr->CreateInstanceByContractID(mContractID, mOuter, + aIID, aInstancePtr); + else if (NS_SUCCEEDED(status)) + status = NS_ERROR_UNEXPECTED; + } + else + status = NS_ERROR_NULL_POINTER; + + if (NS_FAILED(status)) + *aInstancePtr = 0; + if ( mErrorPtr ) + *mErrorPtr = status; + return status; +} + + +nsresult +nsGetServiceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const +{ + nsresult status = NS_ERROR_FAILURE; + if ( mServiceManager ) { + status = mServiceManager->GetService(mCID, aIID, (void**)aInstancePtr); + } else { + nsCOMPtr<nsIServiceManager> mgr; + NS_GetServiceManager(getter_AddRefs(mgr)); + if (mgr) + status = mgr->GetService(mCID, aIID, (void**)aInstancePtr); + } + if ( NS_FAILED(status) ) + *aInstancePtr = 0; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; +} + +nsresult +nsGetServiceByContractID::operator()( const nsIID& aIID, void** aInstancePtr ) const +{ + nsresult status = NS_ERROR_FAILURE; + if ( mServiceManager ) { + status = mServiceManager->GetServiceByContractID(mContractID, aIID, (void**)aInstancePtr); + } else { + nsCOMPtr<nsIServiceManager> mgr; + NS_GetServiceManager(getter_AddRefs(mgr)); + if (mgr) + status = mgr->GetServiceByContractID(mContractID, aIID, (void**)aInstancePtr); + } + + if ( NS_FAILED(status) ) + *aInstancePtr = 0; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; +} + + + diff --git a/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp b/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp new file mode 100644 index 00000000..9e947f30 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp @@ -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 Doug Turner <dougt@meer.net> + * + * 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 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 "nsXPCOM.h" +#include "nsXPCOMPrivate.h" +#include "nsCOMPtr.h" +#include "nsIServiceManager.h" +#include "nsDebug.h" +#include "nsDebugImpl.h" + +static nsIDebug* gDebugObject = nsnull; + +// Note: Although the machinery here is similar to nsMemory.cpp, we cannot use +// NS_ASSERTION macros below because they end up in nsDebug::Assertion and +// therefore may produce endless recursion. + +static NS_METHOD FreeDebugObject(void) +{ + NS_IF_RELEASE(gDebugObject); + return NS_OK; +} + +#define ENSURE_DEBUGOBJECT \ + (gDebugObject ? PR_TRUE : (PRBool)(SetupDebugObject() != nsnull)) + +static nsIDebug* SetupDebugObject() +{ + if (!gDebugObject) + { + NS_GetDebug(&gDebugObject); + if (gDebugObject) + NS_RegisterXPCOMExitRoutine(FreeDebugObject, 0); + } + return gDebugObject; +} + +#ifdef XPCOM_GLUE +nsresult GlueStartupDebug() +{ + if (!gDebugObject) + { + NS_GetDebug(&gDebugObject); + if (!gDebugObject) + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +void GlueShutdownDebug() +{ + NS_IF_RELEASE(gDebugObject); +} +#endif + +NS_COM void nsDebug::Abort(const char* aFile, PRIntn aLine) +{ + if (!ENSURE_DEBUGOBJECT) + return; + + gDebugObject->Abort(aFile, aLine); +} + +NS_COM void nsDebug::Break(const char* aFile, PRIntn aLine) +{ + if (!ENSURE_DEBUGOBJECT) + return; + + gDebugObject->Break(aFile, aLine); +} + +NS_COM void nsDebug::Warning(const char* aStr, + const char* aFile, + PRIntn aLine) +{ + if (!ENSURE_DEBUGOBJECT) + return; + gDebugObject->Warning(aStr, aFile, aLine); +} + +NS_COM void nsDebug::Assertion(const char* aStr, const char* aExpr, + const char* aFile, PRIntn aLine) +{ + if (!ENSURE_DEBUGOBJECT) + return; + gDebugObject->Assertion(aStr, aExpr, aFile, aLine); +} diff --git a/src/libs/xpcom18a4/xpcom/glue/nsDebug.h b/src/libs/xpcom18a4/xpcom/glue/nsDebug.h new file mode 100644 index 00000000..f2ed4c56 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsDebug.h @@ -0,0 +1,276 @@ +/* -*- 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 ***** */ + +#ifndef nsDebug_h___ +#define nsDebug_h___ + +#ifndef nscore_h___ +#include "nscore.h" +#endif + +#ifndef nsError_h__ +#include "nsError.h" +#endif + +#ifdef DEBUG +#define NS_DEBUG +#endif + +/** + * Namespace for debugging methods. Note that your code must use the + * macros defined later in this file so that the debug code can be + * conditionally compiled out. + */ + +/* in case this is included by a C file */ +#ifdef __cplusplus + +class nsDebug { +public: + + /** + * Log a warning message to the debug log. + */ + static NS_COM void Warning(const char* aMessage, + const char* aFile, PRIntn aLine); + + /** + * Abort the executing program. This works on all architectures. + */ + static NS_COM void Abort(const char* aFile, PRIntn aLine); + + /** + * Break the executing program into the debugger. + */ + static NS_COM void Break(const char* aFile, PRIntn aLine); + + /** + * Log an assertion message to the debug log + */ + static NS_COM void Assertion(const char* aStr, const char* aExpr, + const char* aFile, PRIntn aLine); +}; + +#ifdef DEBUG + +/** + * Abort the execution of the program if the expression evaluates to + * false. + * + * There is no status value returned from the macro. + * + * Note that the non-debug version of this macro does <b>not</b> + * evaluate the expression argument. Hence side effect statements + * as arguments to the macro will yield improper execution in a + * non-debug build. For example: + * + * NS_ABORT_IF_FALSE(0 == foo++, "yikes foo should be zero"); + * + * Note also that the non-debug version of this macro does <b>not</b> + * evaluate the message argument. + */ +#define NS_ABORT_IF_FALSE(_expr, _msg) \ + PR_BEGIN_MACRO \ + if (!(_expr)) { \ + nsDebug::Assertion(_msg, #_expr, __FILE__, __LINE__); \ + } \ + PR_END_MACRO + +/** + * Warn if a given condition is false. + * + * Program execution continues past the usage of this macro. + * + * Note also that the non-debug version of this macro does <b>not</b> + * evaluate the message argument. + */ +#define NS_WARN_IF_FALSE(_expr,_msg) \ + PR_BEGIN_MACRO \ + if (!(_expr)) { \ + nsDebug::Assertion(_msg, #_expr, __FILE__, __LINE__); \ + } \ + PR_END_MACRO + +/** + * Test a precondition for truth. If the expression is not true then + * trigger a program failure. + */ +#define NS_PRECONDITION(expr, str) \ + PR_BEGIN_MACRO \ + if (!(expr)) { \ + nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \ + } \ + PR_END_MACRO + +/** + * Test an assertion for truth. If the expression is not true then + * trigger a program failure. + */ +#define NS_ASSERTION(expr, str) \ + PR_BEGIN_MACRO \ + if (!(expr)) { \ + nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \ + } \ + PR_END_MACRO + +/** + * Test a post-condition for truth. If the expression is not true then + * trigger a program failure. + */ +#define NS_POSTCONDITION(expr, str) \ + PR_BEGIN_MACRO \ + if (!(expr)) { \ + nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \ + } \ + PR_END_MACRO + +/** + * This macros triggers a program failure if executed. It indicates that + * an attempt was made to execute some unimplimented functionality. + */ +#define NS_NOTYETIMPLEMENTED(str) \ + nsDebug::Assertion(str, "NotYetImplemented", __FILE__, __LINE__) + +/** + * This macros triggers a program failure if executed. It indicates that + * an attempt was made to execute some unimplimented functionality. + */ +#define NS_NOTREACHED(str) \ + nsDebug::Assertion(str, "Not Reached", __FILE__, __LINE__) + +/** + * Log an error message. + */ +#define NS_ERROR(str) \ + nsDebug::Assertion(str, "Error", __FILE__, __LINE__) + +/** + * Log a warning message. + */ +#define NS_WARNING(str) \ + nsDebug::Warning(str, __FILE__, __LINE__) + +/** + * Trigger an abort + */ +#define NS_ABORT() \ + nsDebug::Abort(__FILE__, __LINE__) + +/** + * Cause a break + */ +#define NS_BREAK() \ + nsDebug::Break(__FILE__, __LINE__) + +#else /* NS_DEBUG */ + +/** + * The non-debug version of these macros do not evaluate the + * expression or the message arguments to the macro. + */ +#define NS_ABORT_IF_FALSE(_expr, _msg) /* nothing */ +#define NS_WARN_IF_FALSE(_expr, _msg) /* nothing */ +#define NS_PRECONDITION(expr, str) /* nothing */ +#define NS_ASSERTION(expr, str) /* nothing */ +#define NS_POSTCONDITION(expr, str) /* nothing */ +#define NS_NOTYETIMPLEMENTED(str) /* nothing */ +#define NS_NOTREACHED(str) /* nothing */ +#define NS_ERROR(str) /* nothing */ +#define NS_WARNING(str) /* nothing */ +#define NS_ABORT() /* nothing */ +#define NS_BREAK() /* nothing */ + +#endif /* ! NS_DEBUG */ +#endif /* __cplusplus */ + +// Macros for checking the trueness of an expression passed in within an +// interface implementation. These need to be compiled regardless of the +// NS_DEBUG flag +/////////////////////////////////////////////////////////////////////////////// + +#define NS_ENSURE_TRUE(x, ret) \ + PR_BEGIN_MACRO \ + if (NS_UNLIKELY(!(x))) { \ + NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \ + return ret; \ + } \ + PR_END_MACRO + +#define NS_ENSURE_FALSE(x, ret) \ + NS_ENSURE_TRUE(!(x), ret) + +/////////////////////////////////////////////////////////////////////////////// +// Macros for checking results +/////////////////////////////////////////////////////////////////////////////// + +#define NS_ENSURE_SUCCESS(res, ret) \ + NS_ENSURE_TRUE(NS_SUCCEEDED(res), ret) + +/////////////////////////////////////////////////////////////////////////////// +// Macros for checking state and arguments upon entering interface boundaries +/////////////////////////////////////////////////////////////////////////////// + +#define NS_ENSURE_ARG(arg) \ + NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_ARG) + +#define NS_ENSURE_ARG_POINTER(arg) \ + NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_POINTER) + +#define NS_ENSURE_ARG_MIN(arg, min) \ + NS_ENSURE_TRUE((arg) >= min, NS_ERROR_INVALID_ARG) + +#define NS_ENSURE_ARG_MAX(arg, max) \ + NS_ENSURE_TRUE((arg) <= max, NS_ERROR_INVALID_ARG) + +#define NS_ENSURE_ARG_RANGE(arg, min, max) \ + NS_ENSURE_TRUE(((arg) >= min) && ((arg) <= max), NS_ERROR_INVALID_ARG) + +#define NS_ENSURE_STATE(state) \ + NS_ENSURE_TRUE(state, NS_ERROR_UNEXPECTED) + +#define NS_ENSURE_NO_AGGREGATION(outer) \ + NS_ENSURE_FALSE(outer, NS_ERROR_NO_AGGREGATION) + +#define NS_ENSURE_PROPER_AGGREGATION(outer, iid) \ + NS_ENSURE_FALSE(outer && !iid.Equals(NS_GET_IID(nsISupports)), NS_ERROR_INVALID_ARG) + +/////////////////////////////////////////////////////////////////////////////// + +#define NS_CheckThreadSafe(owningThread, msg) \ + NS_ASSERTION(owningThread == PR_GetCurrentThread(), msg) + +#endif /* nsDebug_h___ */ diff --git a/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp new file mode 100644 index 00000000..2d791943 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp @@ -0,0 +1,547 @@ +/* -*- 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): + * Pierre Phaneuf <pp@ludusdesign.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 ***** */ + + +// DO NOT COPY THIS CODE INTO YOUR SOURCE! USE NS_IMPL_NSGETMODULE() + +#include "nsGenericFactory.h" +#include "nsMemory.h" +#include "nsCOMPtr.h" +#include "nsIComponentManager.h" +#include "nsIComponentRegistrar.h" + +#ifdef XPCOM_GLUE +#include "nsXPCOMGlue.h" +#include "nsXPCOMPrivate.h" +#else +#include "nsIInterfaceRequestorUtils.h" +#include "nsINativeComponentLoader.h" +#endif + +nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo *info) + : mInfo(info) +{ + if (mInfo && mInfo->mClassInfoGlobal) + *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this); +} + +nsGenericFactory::~nsGenericFactory() +{ + if (mInfo) { + if (mInfo->mFactoryDestructor) + mInfo->mFactoryDestructor(); + if (mInfo->mClassInfoGlobal) + *mInfo->mClassInfoGlobal = 0; + } +} + +NS_IMPL_THREADSAFE_ISUPPORTS3(nsGenericFactory, + nsIGenericFactory, + nsIFactory, + nsIClassInfo) + +NS_IMETHODIMP nsGenericFactory::CreateInstance(nsISupports *aOuter, + REFNSIID aIID, void **aResult) +{ + if (mInfo->mConstructor) { + return mInfo->mConstructor(aOuter, aIID, aResult); + } + + return NS_ERROR_FACTORY_NOT_REGISTERED; +} + +NS_IMETHODIMP nsGenericFactory::LockFactory(PRBool aLock) +{ + // XXX do we care if (mInfo->mFlags & THREADSAFE)? + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetInterfaces(PRUint32 *countp, + nsIID* **array) +{ + if (!mInfo->mGetInterfacesProc) { + *countp = 0; + *array = nsnull; + return NS_OK; + } + return mInfo->mGetInterfacesProc(countp, array); +} + +NS_IMETHODIMP nsGenericFactory::GetHelperForLanguage(PRUint32 language, + nsISupports **helper) +{ + if (mInfo->mGetLanguageHelperProc) + return mInfo->mGetLanguageHelperProc(language, helper); + *helper = nsnull; + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetContractID(char **aContractID) +{ + if (mInfo->mContractID) { + *aContractID = (char *)nsMemory::Alloc(strlen(mInfo->mContractID) + 1); + if (!*aContractID) + return NS_ERROR_OUT_OF_MEMORY; + strcpy(*aContractID, mInfo->mContractID); + } else { + *aContractID = nsnull; + } + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetClassDescription(char * *aClassDescription) +{ + if (mInfo->mDescription) { + *aClassDescription = (char *) + nsMemory::Alloc(strlen(mInfo->mDescription) + 1); + if (!*aClassDescription) + return NS_ERROR_OUT_OF_MEMORY; + strcpy(*aClassDescription, mInfo->mDescription); + } else { + *aClassDescription = nsnull; + } + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetClassID(nsCID * *aClassID) +{ + *aClassID = + NS_REINTERPRET_CAST(nsCID*, + nsMemory::Clone(&mInfo->mCID, sizeof mInfo->mCID)); + if (! *aClassID) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetClassIDNoAlloc(nsCID *aClassID) +{ + *aClassID = mInfo->mCID; + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetImplementationLanguage(PRUint32 *langp) +{ + *langp = nsIProgrammingLanguage::CPLUSPLUS; + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetFlags(PRUint32 *flagsp) +{ + *flagsp = mInfo->mFlags; + return NS_OK; +} + +// nsIGenericFactory: component-info accessors +NS_IMETHODIMP nsGenericFactory::SetComponentInfo(const nsModuleComponentInfo *info) +{ + if (mInfo && mInfo->mClassInfoGlobal) + *mInfo->mClassInfoGlobal = 0; + mInfo = info; + if (mInfo && mInfo->mClassInfoGlobal) + *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this); + return NS_OK; +} + +NS_IMETHODIMP nsGenericFactory::GetComponentInfo(const nsModuleComponentInfo **infop) +{ + *infop = mInfo; + return NS_OK; +} + +NS_METHOD nsGenericFactory::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + // sorry, aggregation not spoken here. + nsresult res = NS_ERROR_NO_AGGREGATION; + if (outer == NULL) { + nsGenericFactory* factory = new nsGenericFactory; + if (factory != NULL) { + res = factory->QueryInterface(aIID, aInstancePtr); + if (res != NS_OK) + delete factory; + } else { + res = NS_ERROR_OUT_OF_MEMORY; + } + } + return res; +} + +NS_COM nsresult +NS_NewGenericFactory(nsIGenericFactory* *result, + const nsModuleComponentInfo *info) +{ + nsresult rv; + nsIGenericFactory* fact; + rv = nsGenericFactory::Create(NULL, NS_GET_IID(nsIGenericFactory), (void**)&fact); + if (NS_FAILED(rv)) return rv; + rv = fact->SetComponentInfo(info); + if (NS_FAILED(rv)) goto error; + *result = fact; + return rv; + + error: + NS_RELEASE(fact); + return rv; +} + +//////////////////////////////////////////////////////////////////////////////// + +nsGenericModule::nsGenericModule(const char* moduleName, PRUint32 componentCount, + const nsModuleComponentInfo* components, + nsModuleConstructorProc ctor, + nsModuleDestructorProc dtor, + const char** aLibDepends) + : mInitialized(PR_FALSE), + mModuleName(moduleName), + mComponentCount(componentCount), + mComponents(components), + mFactoriesNotToBeRegistered(nsnull), + mCtor(ctor), + mDtor(dtor), + mLibraryDependencies(aLibDepends) +{ +} + +nsGenericModule::~nsGenericModule() +{ + Shutdown(); + +#ifdef XPCOM_GLUE + XPCOMGlueShutdown(); +#endif + +} + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsGenericModule, nsIModule) + +nsresult +nsGenericModule::AddFactoryNode(nsIGenericFactory* fact) +{ + if (!fact) + return NS_ERROR_FAILURE; + + FactoryNode *node = new FactoryNode(fact, mFactoriesNotToBeRegistered); + if (!node) + return NS_ERROR_OUT_OF_MEMORY; + + mFactoriesNotToBeRegistered = node; + return NS_OK; +} + + +// Perform our one-time intialization for this module +nsresult +nsGenericModule::Initialize(nsIComponentManager *compMgr) +{ + nsresult rv; + + if (mInitialized) { + return NS_OK; + } + + if (mCtor) { + rv = mCtor(this); + if (NS_FAILED(rv)) + return rv; + } + + +#ifdef XPCOM_GLUE + rv = XPCOMGlueStartup("."); + if (NS_FAILED(rv)) + return rv; +#endif + + nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(compMgr, &rv); + if (NS_FAILED(rv)) + return rv; + + // Eagerly populate factory/class object hash for entries + // without constructors. If we didn't, the class object would + // never get created. Also create the factory, which doubles + // as the class object, if the EAGER_CLASSINFO flag was given. + // This allows objects to be created (within their modules) + // via operator new rather than CreateInstance, yet still be + // QI'able to nsIClassInfo. + const nsModuleComponentInfo* desc = mComponents; + for (PRUint32 i = 0; i < mComponentCount; i++) { + if (!desc->mConstructor || + (desc->mFlags & nsIClassInfo::EAGER_CLASSINFO)) { + nsCOMPtr<nsIGenericFactory> fact; + nsresult rv = NS_NewGenericFactory(getter_AddRefs(fact), desc); + if (NS_FAILED(rv)) return rv; + + // if we don't have a mConstructor, then we should not populate + // the component manager. + if (!desc->mConstructor) { + rv = AddFactoryNode(fact); + } else { + rv = registrar->RegisterFactory(desc->mCID, + desc->mDescription, + desc->mContractID, + fact); + } + if (NS_FAILED(rv)) return rv; + } + desc++; + } + + mInitialized = PR_TRUE; + return NS_OK; +} + +// Shutdown this module, releasing all of the module resources +void +nsGenericModule::Shutdown() +{ + // Free cached factories that were not registered. + FactoryNode* node; + while (mFactoriesNotToBeRegistered) + { + node = mFactoriesNotToBeRegistered->mNext; + delete mFactoriesNotToBeRegistered; + mFactoriesNotToBeRegistered = node; + } + + if (mInitialized) { + mInitialized = PR_FALSE; + + if (mDtor) + mDtor(this); + } +} + +// Create a factory object for creating instances of aClass. +NS_IMETHODIMP +nsGenericModule::GetClassObject(nsIComponentManager *aCompMgr, + const nsCID& aClass, + const nsIID& aIID, + void** r_classObj) +{ + nsresult rv; + + // Defensive programming: Initialize *r_classObj in case of error below + if (!r_classObj) { + return NS_ERROR_INVALID_POINTER; + } + *r_classObj = NULL; + + // Do one-time-only initialization if necessary + if (!mInitialized) { + rv = Initialize(aCompMgr); + if (NS_FAILED(rv)) { + // Initialization failed! yikes! + return rv; + } + } + + // Choose the appropriate factory, based on the desired instance + // class type (aClass). + const nsModuleComponentInfo* desc = mComponents; + for (PRUint32 i = 0; i < mComponentCount; i++) { + if (desc->mCID.Equals(aClass)) { + nsCOMPtr<nsIGenericFactory> fact; + rv = NS_NewGenericFactory(getter_AddRefs(fact), desc); + if (NS_FAILED(rv)) return rv; + return fact->QueryInterface(aIID, r_classObj); + } + desc++; + } + // not found in descriptions +#ifndef XPCOM_GLUE +#ifdef DEBUG + char* cs = aClass.ToString(); + fprintf(stderr, "+++ nsGenericModule %s: unable to create factory for %s\n", mModuleName, cs); + // leak until we resolve the nsID Allocator. + // nsCRT::free(cs); +#endif // XXX put in stop-gap so that we don't search for this one again +#endif + return NS_ERROR_FACTORY_NOT_REGISTERED; +} + +NS_IMETHODIMP +nsGenericModule::RegisterSelf(nsIComponentManager *aCompMgr, + nsIFile* aPath, + const char* registryLocation, + const char* componentType) +{ + nsresult rv = NS_OK; + +#ifdef DEBUG + fprintf(stderr, "*** Registering %s components (all right -- a generic module!)\n", mModuleName); +#endif + + const nsModuleComponentInfo* cp = mComponents; + for (PRUint32 i = 0; i < mComponentCount; i++) { + // Register the component only if it has a constructor + if (cp->mConstructor) { + nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv); + if (registrar) + rv = registrar->RegisterFactoryLocation(cp->mCID, + cp->mDescription, + cp->mContractID, + aPath, + registryLocation, + componentType); + if (NS_FAILED(rv)) { +#ifdef DEBUG + fprintf(stderr, "nsGenericModule %s: unable to register %s component => %x\n", + mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv); +#endif + break; + } + } + // Call the registration hook of the component, if any + if (cp->mRegisterSelfProc) + { + rv = cp->mRegisterSelfProc(aCompMgr, aPath, registryLocation, + componentType, cp); + if (NS_FAILED(rv)) { +#ifdef DEBUG + fprintf(stderr, "nsGenericModule %s: Register hook for %s component returned error => %x\n", + mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv); +#endif + break; + } + } + 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; +} + +NS_IMETHODIMP +nsGenericModule::UnregisterSelf(nsIComponentManager* aCompMgr, + nsIFile* aPath, + const char* registryLocation) +{ +#ifdef DEBUG + fprintf(stderr, "*** Unregistering %s components (all right -- a generic module!)\n", mModuleName); +#endif + const nsModuleComponentInfo* cp = mComponents; + for (PRUint32 i = 0; i < mComponentCount; i++) { + // Call the unregistration hook of the component, if any + if (cp->mUnregisterSelfProc) + { + cp->mUnregisterSelfProc(aCompMgr, aPath, registryLocation, cp); + } + + // Unregister the component + nsresult rv; + nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv); + if (registrar) + rv = registrar->UnregisterFactoryLocation(cp->mCID, aPath); + if (NS_FAILED(rv)) { +#ifdef DEBUG + fprintf(stderr, "nsGenericModule %s: unable to unregister %s component => %x\n", + mModuleName, cp->mDescription, rv); +#endif + } + cp++; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsGenericModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload) +{ + if (!okToUnload) { + return NS_ERROR_INVALID_POINTER; + } + *okToUnload = PR_FALSE; + return NS_ERROR_FAILURE; +} + +NS_COM nsresult +NS_NewGenericModule2(nsModuleInfo* info, nsIModule* *result) +{ + nsresult rv = NS_OK; + + // Create and initialize the module instance + nsGenericModule *m = + new nsGenericModule(info->mModuleName, info->mCount, info->mComponents, + info->mCtor, info->mDtor, info->mLibraryDependencies); + + if (!m) + return NS_ERROR_OUT_OF_MEMORY; + + // Increase refcnt and store away nsIModule interface to m in result + NS_ADDREF(*result = m); + return rv; +} + +NS_COM nsresult +NS_NewGenericModule(const char* moduleName, + PRUint32 componentCount, + nsModuleComponentInfo* components, + nsModuleDestructorProc dtor, + nsIModule* *result) +{ + nsModuleInfo info; + memset(&info, 0, sizeof(info)); + + info.mVersion = NS_MODULEINFO_VERSION; + info.mModuleName = moduleName; + info.mComponents = components; + info.mCount = componentCount; + info.mDtor = dtor; + info.mLibraryDependencies = nsnull; + + return NS_NewGenericModule2(&info, result); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h new file mode 100644 index 00000000..64afd0de --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h @@ -0,0 +1,129 @@ +/* -*- 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 nsGenericFactory_h___ +#define nsGenericFactory_h___ + +#include "nsCOMPtr.h" +#include "nsIGenericFactory.h" +#include "nsIClassInfo.h" + +/** + * Most factories follow this simple pattern, so why not just use a function + * pointer for most creation operations? + */ +class nsGenericFactory : public nsIGenericFactory, public nsIClassInfo { +public: + NS_DEFINE_STATIC_CID_ACCESSOR(NS_GENERICFACTORY_CID); + + nsGenericFactory(const nsModuleComponentInfo *info = NULL); + + NS_DECL_ISUPPORTS + NS_DECL_NSICLASSINFO + + /* nsIGenericFactory methods */ + NS_IMETHOD SetComponentInfo(const nsModuleComponentInfo *info); + NS_IMETHOD GetComponentInfo(const nsModuleComponentInfo **infop); + + NS_IMETHOD CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); +private: + ~nsGenericFactory(); + + const nsModuleComponentInfo *mInfo; +}; + +//////////////////////////////////////////////////////////////////////////////// + +#include "nsIModule.h" +#include "plhash.h" + +class nsGenericModule : public nsIModule +{ +public: + nsGenericModule(const char* moduleName, + PRUint32 componentCount, + const nsModuleComponentInfo* components, + nsModuleConstructorProc ctor, + nsModuleDestructorProc dtor, + const char** alibDepends); + +private: + ~nsGenericModule(); + +public: + NS_DECL_ISUPPORTS + + NS_DECL_NSIMODULE + + struct FactoryNode + { + FactoryNode(nsIGenericFactory* fact, FactoryNode* next) + { + mFactory = fact; + mNext = next; + } + ~FactoryNode(){} + + nsCOMPtr<nsIGenericFactory> mFactory; + FactoryNode* mNext; + }; + + + + +protected: + nsresult Initialize(nsIComponentManager* compMgr); + + void Shutdown(); + nsresult AddFactoryNode(nsIGenericFactory* fact); + + PRBool mInitialized; + const char* mModuleName; + PRUint32 mComponentCount; + const nsModuleComponentInfo* mComponents; + FactoryNode* mFactoriesNotToBeRegistered; + nsModuleConstructorProc mCtor; + nsModuleDestructorProc mDtor; + const char** mLibraryDependencies; +}; + +#endif /* nsGenericFactory_h___ */ + diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h b/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h new file mode 100644 index 00000000..82506e8e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h @@ -0,0 +1,480 @@ +/* -*- 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 nsIGenericFactory_h___ +#define nsIGenericFactory_h___ + +#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 \ + { 0x3bc97f01, 0xccdf, 0x11d2, \ + { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } } + +// {3bc97f00-ccdf-11d2-bab8-b548654461fc} +#define NS_IGENERICFACTORY_IID \ + { 0x3bc97f00, 0xccdf, 0x11d2, \ + { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } } + +#define NS_GENERICFACTORY_CONTRACTID "@mozilla.org/generic-factory;1" +#define NS_GENERICFACTORY_CLASSNAME "Generic Factory" + +struct nsModuleComponentInfo; // forward declaration + +/** + * Provides a Generic nsIFactory implementation that can be used by + * DLLs with very simple factory needs. + */ +class nsIGenericFactory : public nsIFactory { +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IGENERICFACTORY_IID) + + NS_IMETHOD SetComponentInfo(const nsModuleComponentInfo *info) = 0; + NS_IMETHOD GetComponentInfo(const nsModuleComponentInfo **infop) = 0; +}; + +NS_COM nsresult +NS_NewGenericFactory(nsIGenericFactory **result, + const nsModuleComponentInfo *info); + + +/** Component Callbacks **/ + + /** + * NSConstructorProcPtr + * + * This function will be used by the generic factory to create an + * instance of the given CID. + * + * @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. + **/ +typedef NS_CALLBACK(NSConstructorProcPtr)(nsISupports *aOuter, + REFNSIID aIID, + void **aResult); + +/** + * NSRegisterSelfProcPtr + * + * One time registration call back. Allows you to perform registration + * specific activity like adding yourself to a category. + * + * @param aCompMgr : The global component manager + * @param aFile : Component File. This file must have an associated + * loader and export the required symbols which this + * loader defines. + * @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. + * @param aInfo : Pointer to array of nsModuleComponentInfo + * + * @param aInfo + * @return NS_OK Registration was successful. + * NS_ERROR* Method failure. + **/ +typedef NS_CALLBACK(NSRegisterSelfProcPtr)(nsIComponentManager *aCompMgr, + nsIFile *aPath, + const char *aLoaderStr, + const char *aType, + const nsModuleComponentInfo *aInfo); + +/** + * NSUnregisterSelfProcPtr + * + * One time unregistration call back. Allows you to perform unregistration + * specific activity like removing yourself from a category. + * + * @param aCompMgr : The global component manager + * @param aFile : Component File. This file must have an associated + * loader and export the required symbols which this + * loader defines. + * @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 aInfo : Pointer to array of nsModuleComponentInfo + * + * @param aInfo + * @return NS_OK Registration was successful. + * NS_ERROR* Method failure. + + **/ +typedef NS_CALLBACK(NSUnregisterSelfProcPtr)(nsIComponentManager *aCompMgr, + nsIFile *aPath, + const char *aLoaderStr, + const nsModuleComponentInfo *aInfo); + +/** + * NSFactoryDestructorProcPtr + * + * This function will be called when the factory is being destroyed. + * + **/ +typedef NS_CALLBACK(NSFactoryDestructorProcPtr)(void); + + +/** + * NSGetInterfacesProcPtr + * + * This function is used to implement class info. + * + * 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. + * + * @see nsIClassInfo.idl + **/ +typedef NS_CALLBACK(NSGetInterfacesProcPtr)(PRUint32 *countp, + nsIID* **array); + +/** + * NSGetLanguageHelperProcPtr + * + * This function is used to implement class info. + * + * 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: nsIClassInfo.idl, nsIProgrammingLanguage.idl + * + * Should return null if no helper available for given language. + **/ +typedef NS_CALLBACK(NSGetLanguageHelperProcPtr)(PRUint32 language, + nsISupports **helper); + +/** + * nsModuleComponentInfo + * + * Use this type to define a list of module component info to pass to + * NS_NewGenericModule. + * + * @param mDescription : Class Name of given object + * @param mCID : CID of given object + * @param mContractID : Contract ID of given object + * @param mConstructor : Constructor of given object + * @param mRegisterSelfProc : (optional) Registration Callback + * @param mUnregisterSelfProc : (optional) Unregistration Callback + * @param mFactoryDestructor : (optional) Destruction Callback + * @param mGetInterfacesProc : (optional) Interfaces Callback + * @param mGetLanguageHelperProc : (optional) Language Helper Callback + * @param mClassInfoGlobal : (optional) Global Class Info of given object + * @param mFlags : (optional) Class Info Flags @see nsIClassInfo + * + * E.g.: + * static nsModuleComponentInfo components[] = { ... }; + * + * See xpcom/sample/nsSampleModule.cpp for more info. + */ +struct nsModuleComponentInfo { + const char* mDescription; + nsCID mCID; + const char* mContractID; + NSConstructorProcPtr mConstructor; + NSRegisterSelfProcPtr mRegisterSelfProc; + NSUnregisterSelfProcPtr mUnregisterSelfProc; + NSFactoryDestructorProcPtr mFactoryDestructor; + NSGetInterfacesProcPtr mGetInterfacesProc; + NSGetLanguageHelperProcPtr mGetLanguageHelperProc; + nsIClassInfo ** mClassInfoGlobal; + PRUint32 mFlags; +}; + + +/** Module Callbacks **/ + + +/** + * nsModuleConstructorProc + * + * This function is called when the module is first being constructed. + * @param self module which is being constructed. + * + * @return NS_OK Construction successful. + * NS_ERROR* Method failure which will result in module not being + * loaded. + **/ +typedef nsresult (PR_CALLBACK *nsModuleConstructorProc) (nsIModule *self); + + +/** + * nsModuleDestructorProc + * + * This function is called when the module is being destroyed. + * @param self module which is being destroyed. + * + **/ +typedef void (PR_CALLBACK *nsModuleDestructorProc) (nsIModule *self); + +/** + * nsModuleInfo + * + * Use this structure to define meta-information about the module + * itself, including the name, its components, and an optional + * module-level initialization or shutdown routine. + * + * @param mVersion : Module Info Version + * @param mModuleName : Module Name + * @param mComponents : Array of Components + * @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. + * + **/ + +struct nsModuleInfo { + PRUint32 mVersion; + const char* mModuleName; + const nsModuleComponentInfo* mComponents; + PRUint32 mCount; + nsModuleConstructorProc mCtor; + nsModuleDestructorProc mDtor; + const char** mLibraryDependencies; +}; + +/** + * Rev this if you change the nsModuleInfo, and are worried about + * binary compatibility. (Ostensibly fix NS_NewGenericModule2() to deal + * with older rev's at the same time.) + */ +#define NS_MODULEINFO_VERSION 0x00015000UL // 1.5 + +/** + * Create a new generic module. Use the NS_IMPL_NSGETMODULE macro, or + * one of its relatives, rather than using this directly. + */ +NS_COM nsresult +NS_NewGenericModule2(nsModuleInfo *info, nsIModule* *result); + +/** + * Obsolete. Use NS_NewGenericModule2() instead. + */ +NS_COM nsresult +NS_NewGenericModule(const char* moduleName, + PRUint32 componentCount, + nsModuleComponentInfo* components, + nsModuleDestructorProc dtor, + nsIModule* *result); + +#if defined(XPCOM_TRANSLATE_NSGM_ENTRY_POINT) +# 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, \ + nsIFile* location, \ + nsIModule** result) \ +{ \ + (void)servMgr; \ + (void)location; \ + return NS_NewGenericModule2(&(_info), result); \ +} +#endif + +/** + * Ease of use Macros which define NSGetModule for your component. + * See xpcom/sample/nsSampleModule.cpp for more info. + * + **/ + +#define NS_IMPL_NSGETMODULE(_name, _components) \ + NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, nsnull, nsnull) + +#define NS_IMPL_NSGETMODULE_WITH_CTOR(_name, _components, _ctor) \ + NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, nsnull) + +#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, \ + (#_name), \ + (_components), \ + (sizeof(_components) / sizeof(_components[0])), \ + (_ctor), \ + (_dtor), \ + (nsnull) \ +}; \ +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) \ +static NS_IMETHODIMP \ +_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ + void **aResult) \ +{ \ + nsresult rv; \ + \ + _InstanceClass * inst; \ + \ + *aResult = NULL; \ + if (NULL != aOuter) { \ + rv = NS_ERROR_NO_AGGREGATION; \ + return rv; \ + } \ + \ + NS_NEWXPCOM(inst, _InstanceClass); \ + if (NULL == inst) { \ + rv = NS_ERROR_OUT_OF_MEMORY; \ + return rv; \ + } \ + NS_ADDREF(inst); \ + rv = inst->QueryInterface(aIID, aResult); \ + NS_RELEASE(inst); \ + \ + return rv; \ +} \ + + +#define NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(_InstanceClass, _InitMethod) \ +static NS_IMETHODIMP \ +_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ + void **aResult) \ +{ \ + nsresult rv; \ + \ + _InstanceClass * inst; \ + \ + *aResult = NULL; \ + if (NULL != aOuter) { \ + rv = NS_ERROR_NO_AGGREGATION; \ + return rv; \ + } \ + \ + NS_NEWXPCOM(inst, _InstanceClass); \ + if (NULL == inst) { \ + rv = NS_ERROR_OUT_OF_MEMORY; \ + return rv; \ + } \ + NS_ADDREF(inst); \ + rv = inst->_InitMethod(); \ + if(NS_SUCCEEDED(rv)) { \ + rv = inst->QueryInterface(aIID, aResult); \ + } \ + NS_RELEASE(inst); \ + \ + return rv; \ +} \ + +// 'Constructor' that uses an existing getter function that gets a singleton. +// NOTE: assumes that getter does an AddRef - so additional AddRef is not done. +#define NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(_InstanceClass, _GetterProc) \ +static NS_IMETHODIMP \ +_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ + void **aResult) \ +{ \ + nsresult rv; \ + \ + _InstanceClass * inst; \ + \ + *aResult = NULL; \ + if (NULL != aOuter) { \ + rv = NS_ERROR_NO_AGGREGATION; \ + return rv; \ + } \ + \ + inst = _GetterProc(); \ + if (NULL == inst) { \ + rv = NS_ERROR_OUT_OF_MEMORY; \ + return rv; \ + } \ + /* NS_ADDREF(inst); */ \ + rv = inst->QueryInterface(aIID, aResult); \ + NS_RELEASE(inst); \ + \ + return rv; \ +} \ + +#endif /* nsIGenericFactory_h___ */ diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp new file mode 100644 index 00000000..b440c342 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp @@ -0,0 +1,64 @@ +/* -*- 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): + * 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 ***** */ + +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" + +nsresult +nsGetInterface::operator()( const nsIID& aIID, void** aInstancePtr ) const +{ + nsresult status; + + if ( mSource ) + { + nsCOMPtr<nsIInterfaceRequestor> factoryPtr = do_QueryInterface(mSource, &status); + NS_ASSERTION(factoryPtr, "Did you know you were calling |do_GetInterface()| on an object that doesn't support the |nsIInterfaceRequestor| interface?"); + + if ( factoryPtr ) + status = factoryPtr->GetInterface(aIID, aInstancePtr); + + if ( NS_FAILED(status) ) + *aInstancePtr = 0; + } + else + status = NS_ERROR_NULL_POINTER; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; +} diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h new file mode 100644 index 00000000..e971dd4b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h @@ -0,0 +1,83 @@ +/* -*- Mode: IDL; 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 the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * 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 ***** */ + +#ifndef __nsInterfaceRequestorUtils_h +#define __nsInterfaceRequestorUtils_h + +#include "nsCOMPtr.h" + +// a type-safe shortcut for calling the |GetInterface()| member function +// T must inherit from nsIInterfaceRequestor, but the cast may be ambiguous. +template <class T, class DestinationType> +inline +nsresult +CallGetInterface( T* aSource, DestinationType** aDestination ) + { + NS_PRECONDITION(aSource, "null parameter"); + NS_PRECONDITION(aDestination, "null parameter"); + + return aSource->GetInterface(NS_GET_IID(DestinationType), + NS_REINTERPRET_CAST(void**, aDestination)); + } + +class NS_COM nsGetInterface : public nsCOMPtr_helper + { + public: + nsGetInterface( nsISupports* aSource, nsresult* error ) + : mSource(aSource), + mErrorPtr(error) + { + // nothing else to do here + } + + virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const; + + private: + nsCOMPtr<nsISupports> mSource; + nsresult* mErrorPtr; + }; + +inline +const nsGetInterface +do_GetInterface( nsISupports* aSource, nsresult* error = 0 ) + { + return nsGetInterface(aSource, error); + } + +#endif // __nsInterfaceRequestorUtils_h + diff --git a/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h b/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h new file mode 100644 index 00000000..588a2c73 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h @@ -0,0 +1,1246 @@ +/* ***** 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 Corp. + * 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 ***** */ + + +#ifndef nsISupportsImpl_h__ +#define nsISupportsImpl_h__ + +#ifndef nscore_h___ +#include "nscore.h" +#endif + +#ifndef nsISupportsBase_h__ +#include "nsISupportsBase.h" +#endif + +#include "prthread.h" /* needed for thread-safety checks */ +#include "pratom.h" /* needed for PR_AtomicIncrement and PR_AtomicDecrement */ + +#include "nsDebug.h" +#include "nsTraceRefcnt.h" +#ifdef VBOX +# include "iprt/asm.h" +# include "iprt/assert.h" +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Macros to help detect thread-safety: + +#if defined(NS_DEBUG) + +class nsAutoOwningThread { +public: + nsAutoOwningThread() { mThread = PR_GetCurrentThread(); } + void *GetThread() const { return mThread; } + +private: + void *mThread; +}; + +#define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread; +#define NS_ASSERT_OWNINGTHREAD(_class) \ + NS_CheckThreadSafe(_mOwningThread.GetThread(), #_class " not thread-safe") + +#else // !(defined(NS_DEBUG)) + +#define NS_DECL_OWNINGTHREAD /* nothing */ +#define NS_ASSERT_OWNINGTHREAD(_class) ((void)0) + +#endif // !(defined(NS_DEBUG)) + +class nsAutoRefCnt { + + public: + nsAutoRefCnt() : mValue(0) +#ifdef VBOX + , mState(0) +#endif + {} + nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {} + + // only support prefix increment/decrement + nsrefcnt operator++() { return ++mValue; } + nsrefcnt operator--() { return --mValue; } + + nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); } + operator nsrefcnt() const { return mValue; } + nsrefcnt get() const { return mValue; } +#ifdef VBOX + nsrefcnt *ref() { return &mValue; } + PRUint32 getState() const { return mState; } + PRUint32 *refState() { return &mState; } +#endif + private: + // do not define these to enforce the faster prefix notation + nsrefcnt operator++(int); + nsrefcnt operator--(int); + nsrefcnt mValue; +#ifdef VBOX + PRUint32 mState; +#endif +}; + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Declare the reference count variable and the implementations of the + * AddRef and QueryInterface methods. + */ + +#define NS_DECL_ISUPPORTS \ +public: \ + NS_IMETHOD QueryInterface(REFNSIID aIID, \ + void** aInstancePtr); \ + NS_IMETHOD_(nsrefcnt) AddRef(void); \ + NS_IMETHOD_(nsrefcnt) Release(void); \ +protected: \ + nsAutoRefCnt mRefCnt; \ + NS_DECL_OWNINGTHREAD \ +public: + + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Previously used to initialize the reference count, but no longer needed. + * + * DEPRECATED. + */ +#define NS_INIT_ISUPPORTS() ((void)0) + +/** + * Use this macro to implement the AddRef method for a given <i>_class</i> + * @param _class The name of the class implementing the method + */ +#define NS_IMPL_ADDREF(_class) \ +NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \ +{ \ + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ + ++mRefCnt; \ + NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ + return mRefCnt; \ +} + +/** + * Use this macro to implement the AddRef method for a given <i>_class</i> + * implemented as a wholly owned aggregated object intended to implement + * interface(s) for its owner + * @param _class The name of the class implementing the method + * @param _aggregator the owning/containing object + */ +#define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator) \ +NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \ +{ \ + NS_PRECONDITION(_aggregator, "null aggregator"); \ + return (_aggregator)->AddRef(); \ +} + +/** + * Use this macro to implement the Release method for a given + * <i>_class</i>. + * @param _class The name of the class implementing the method + * @param _destroy A statement that is executed when the object's + * refcount drops to zero. + * + * For example, + * + * NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this)) + * + * will cause + * + * Destroy(this); + * + * to be invoked when the object's refcount drops to zero. This + * allows for arbitrary teardown activity to occur (e.g., deallocation + * of object allocated with placement new). + */ +#define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \ +NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \ +{ \ + NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ + --mRefCnt; \ + NS_LOG_RELEASE(this, mRefCnt, #_class); \ + if (mRefCnt == 0) { \ + mRefCnt = 1; /* stabilize */ \ + _destroy; \ + return 0; \ + } \ + return mRefCnt; \ +} + +/** + * Use this macro to implement the Release method for a given <i>_class</i> + * @param _class The name of the class implementing the method + * + * A note on the 'stabilization' of the refcnt to one. At that point, + * the object's refcount will have gone to zero. The object's + * destructor may trigger code that attempts to QueryInterface() and + * Release() 'this' again. Doing so will temporarily increment and + * decrement the refcount. (Only a logic error would make one try to + * keep a permanent hold on 'this'.) To prevent re-entering the + * destructor, we make sure that no balanced refcounting can return + * the refcount to |0|. + */ +#define NS_IMPL_RELEASE(_class) \ + NS_IMPL_RELEASE_WITH_DESTROY(_class, NS_DELETEXPCOM(this)) + +/** + * Use this macro to implement the Release method for a given <i>_class</i> + * implemented as a wholly owned aggregated object intended to implement + * interface(s) for its owner + * @param _class The name of the class implementing the method + * @param _aggregator the owning/containing object + */ +#define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator) \ +NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \ +{ \ + NS_PRECONDITION(_aggregator, "null aggregator"); \ + return (_aggregator)->Release(); \ +} + + + +/////////////////////////////////////////////////////////////////////////////// + +/* + * Some convenience macros for implementing QueryInterface + */ + +/** + * This implements query interface with two assumptions: First, the + * class in question implements nsISupports and its own interface and + * nothing else. Second, the implementation of the class's primary + * inheritance chain leads to its own interface. + * + * @param _class The name of the class implementing the method + * @param _classiiddef The name of the #define symbol that defines the IID + * for the class (e.g. NS_ISUPPORTS_IID) + */ + +#define NS_IMPL_QUERY_HEAD(_class) \ +NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \ +{ \ + NS_ASSERTION(aInstancePtr, \ + "QueryInterface requires a non-NULL destination!"); \ + nsISupports* foundInterface; + +#define NS_IMPL_QUERY_BODY(_interface) \ + if ( aIID.Equals(NS_GET_IID(_interface)) ) \ + foundInterface = NS_STATIC_CAST(_interface*, this); \ + else + +#define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) \ + if ( (condition) && aIID.Equals(NS_GET_IID(_interface))) \ + foundInterface = NS_STATIC_CAST(_interface*, this); \ + else + +#define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) \ + if ( aIID.Equals(NS_GET_IID(_interface)) ) \ + foundInterface = NS_STATIC_CAST(_interface*, \ + NS_STATIC_CAST(_implClass*, this)); \ + else + +#define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate) \ + if ( aIID.Equals(NS_GET_IID(_interface)) ) \ + foundInterface = NS_STATIC_CAST(_interface*, _aggregate); \ + else + +#define NS_IMPL_QUERY_TAIL_GUTS \ + foundInterface = 0; \ + nsresult status; \ + if ( !foundInterface ) \ + status = NS_NOINTERFACE; \ + else \ + { \ + NS_ADDREF(foundInterface); \ + status = NS_OK; \ + } \ + *aInstancePtr = foundInterface; \ + return status; \ +} + +#define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass) \ + foundInterface = 0; \ + nsresult status; \ + if ( !foundInterface ) \ + status = _baseclass::QueryInterface(aIID, (void**)&foundInterface); \ + else \ + { \ + NS_ADDREF(foundInterface); \ + status = NS_OK; \ + } \ + *aInstancePtr = foundInterface; \ + return status; \ +} + +#define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) \ + foundInterface = 0; \ + nsresult status; \ + if ( !foundInterface ) { \ + NS_ASSERTION(_aggregator, "null aggregator"); \ + status = _aggregator->QueryInterface(aIID, (void**)&foundInterface); \ + } else \ + { \ + NS_ADDREF(foundInterface); \ + status = NS_OK; \ + } \ + *aInstancePtr = foundInterface; \ + return status; \ +} + +#define NS_IMPL_QUERY_TAIL(_supports_interface) \ + NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface) \ + NS_IMPL_QUERY_TAIL_GUTS + + + /* + This is the new scheme. Using this notation now will allow us to switch to + a table driven mechanism when it's ready. Note the difference between this + and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism. You must + explicitly mention |nsISupports| when using the interface maps. + */ +#define NS_INTERFACE_MAP_BEGIN(_implClass) NS_IMPL_QUERY_HEAD(_implClass) +#define NS_INTERFACE_MAP_ENTRY(_interface) NS_IMPL_QUERY_BODY(_interface) +#define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition) \ + NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) +#define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate) \ + NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate) + +#define NS_INTERFACE_MAP_END NS_IMPL_QUERY_TAIL_GUTS +#define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass) \ + NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) +#define NS_INTERFACE_MAP_END_INHERITING(_baseClass) \ + NS_IMPL_QUERY_TAIL_INHERITING(_baseClass) +#define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator) \ + NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) + +#define NS_IMPL_QUERY_INTERFACE0(_class) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(nsISupports) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE1(_class, _i1) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY(_i9) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY(_i9) \ + NS_INTERFACE_MAP_ENTRY(_i10) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10, _i11) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY(_i9) \ + NS_INTERFACE_MAP_ENTRY(_i10) \ + NS_INTERFACE_MAP_ENTRY(_i11) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_INTERFACE_MAP_END + + +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE0 NS_IMPL_QUERY_INTERFACE0 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE1 NS_IMPL_QUERY_INTERFACE1 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE2 NS_IMPL_QUERY_INTERFACE2 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE3 NS_IMPL_QUERY_INTERFACE3 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE4 NS_IMPL_QUERY_INTERFACE4 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE5 NS_IMPL_QUERY_INTERFACE5 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE6 NS_IMPL_QUERY_INTERFACE6 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE7 NS_IMPL_QUERY_INTERFACE7 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE8 NS_IMPL_QUERY_INTERFACE8 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE9 NS_IMPL_QUERY_INTERFACE9 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE10 NS_IMPL_QUERY_INTERFACE10 +#define NS_IMPL_THREADSAFE_QUERY_INTERFACE11 NS_IMPL_QUERY_INTERFACE11 + +/** + * Declare that you're going to inherit from something that already + * implements nsISupports, but also implements an additional interface, thus + * causing an ambiguity. In this case you don't need another mRefCnt, you + * just need to forward the definitions to the appropriate superclass. E.g. + * + * class Bar : public Foo, public nsIBar { // both provide nsISupports + * public: + * NS_DECL_ISUPPORTS_INHERITED + * ...other nsIBar and Bar methods... + * }; + */ +#define NS_DECL_ISUPPORTS_INHERITED \ +public: \ + NS_IMETHOD QueryInterface(REFNSIID aIID, \ + void** aInstancePtr); \ + NS_IMETHOD_(nsrefcnt) AddRef(void); \ + NS_IMETHOD_(nsrefcnt) Release(void); \ + +/** + * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED + * to implement the nsISupports methods, forwarding the invocations to a + * superclass that already implements nsISupports. + * + * Note that I didn't make these inlined because they're virtual methods. + */ + +#define NS_IMPL_ADDREF_INHERITED(Class, Super) \ +NS_IMETHODIMP_(nsrefcnt) Class::AddRef(void) \ +{ \ + return Super::AddRef(); \ +} \ + +#define NS_IMPL_RELEASE_INHERITED(Class, Super) \ +NS_IMETHODIMP_(nsrefcnt) Class::Release(void) \ +{ \ + return Super::Release(); \ +} \ + +#define NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \ + NS_IMPL_QUERY_HEAD(Class) \ + NS_IMPL_QUERY_TAIL_INHERITING(Super) \ + +#define NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \ + NS_IMPL_QUERY_HEAD(Class) \ + NS_IMPL_QUERY_BODY(i1) \ + NS_IMPL_QUERY_TAIL_INHERITING(Super) \ + +#define NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \ + NS_IMPL_QUERY_HEAD(Class) \ + NS_IMPL_QUERY_BODY(i1) \ + NS_IMPL_QUERY_BODY(i2) \ + NS_IMPL_QUERY_TAIL_INHERITING(Super) \ + +#define NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \ + NS_IMPL_QUERY_HEAD(Class) \ + NS_IMPL_QUERY_BODY(i1) \ + NS_IMPL_QUERY_BODY(i2) \ + NS_IMPL_QUERY_BODY(i3) \ + NS_IMPL_QUERY_TAIL_INHERITING(Super) \ + +#define NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \ + NS_IMPL_QUERY_HEAD(Class) \ + NS_IMPL_QUERY_BODY(i1) \ + NS_IMPL_QUERY_BODY(i2) \ + NS_IMPL_QUERY_BODY(i3) \ + NS_IMPL_QUERY_BODY(i4) \ + NS_IMPL_QUERY_TAIL_INHERITING(Super) \ + +#define NS_IMPL_QUERY_INTERFACE_INHERITED5(Class,Super,i1,i2,i3,i4,i5) \ + NS_IMPL_QUERY_HEAD(Class) \ + NS_IMPL_QUERY_BODY(i1) \ + NS_IMPL_QUERY_BODY(i2) \ + NS_IMPL_QUERY_BODY(i3) \ + NS_IMPL_QUERY_BODY(i4) \ + NS_IMPL_QUERY_BODY(i5) \ + NS_IMPL_QUERY_TAIL_INHERITING(Super) \ + +#define NS_IMPL_QUERY_INTERFACE_INHERITED6(Class,Super,i1,i2,i3,i4,i5,i6) \ + NS_IMPL_QUERY_HEAD(Class) \ + NS_IMPL_QUERY_BODY(i1) \ + NS_IMPL_QUERY_BODY(i2) \ + NS_IMPL_QUERY_BODY(i3) \ + NS_IMPL_QUERY_BODY(i4) \ + NS_IMPL_QUERY_BODY(i5) \ + NS_IMPL_QUERY_BODY(i6) \ + NS_IMPL_QUERY_TAIL_INHERITING(Super) \ + +/** + * Convenience macros for implementing all nsISupports methods for + * a simple class. + * @param _class The name of the class implementing the method + * @param _classiiddef The name of the #define symbol that defines the IID + * for the class (e.g. NS_ISUPPORTS_IID) + */ + +#define NS_IMPL_ISUPPORTS0(_class) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE0(_class) + +#define NS_IMPL_ISUPPORTS1(_class, _interface) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE1(_class, _interface) + +#define NS_IMPL_ISUPPORTS2(_class, _i1, _i2) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2) + +#define NS_IMPL_ISUPPORTS3(_class, _i1, _i2, _i3) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3) + +#define NS_IMPL_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4) + +#define NS_IMPL_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5) + +#define NS_IMPL_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) + +#define NS_IMPL_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) + +#define NS_IMPL_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) + +#define NS_IMPL_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \ + _i9) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9) + +#define NS_IMPL_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \ + _i9, _i10) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \ + _i9, _i10) + +#define NS_IMPL_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \ + _i9, _i10, _i11) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \ + _i9, _i10, _i11) + +#define NS_IMPL_ISUPPORTS_INHERITED0(Class, Super) \ + NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \ + NS_IMPL_ADDREF_INHERITED(Class, Super) \ + NS_IMPL_RELEASE_INHERITED(Class, Super) \ + +#define NS_IMPL_ISUPPORTS_INHERITED1(Class, Super, i1) \ + NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \ + NS_IMPL_ADDREF_INHERITED(Class, Super) \ + NS_IMPL_RELEASE_INHERITED(Class, Super) \ + +#define NS_IMPL_ISUPPORTS_INHERITED2(Class, Super, i1, i2) \ + NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \ + NS_IMPL_ADDREF_INHERITED(Class, Super) \ + NS_IMPL_RELEASE_INHERITED(Class, Super) \ + +#define NS_IMPL_ISUPPORTS_INHERITED3(Class, Super, i1, i2, i3) \ + NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \ + NS_IMPL_ADDREF_INHERITED(Class, Super) \ + NS_IMPL_RELEASE_INHERITED(Class, Super) \ + +#define NS_IMPL_ISUPPORTS_INHERITED4(Class, Super, i1, i2, i3, i4) \ + NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \ + NS_IMPL_ADDREF_INHERITED(Class, Super) \ + NS_IMPL_RELEASE_INHERITED(Class, Super) \ + +#define NS_IMPL_ISUPPORTS_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \ + NS_IMPL_QUERY_INTERFACE_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \ + NS_IMPL_ADDREF_INHERITED(Class, Super) \ + NS_IMPL_RELEASE_INHERITED(Class, Super) \ + +#define NS_IMPL_ISUPPORTS_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \ + NS_IMPL_QUERY_INTERFACE_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \ + NS_IMPL_ADDREF_INHERITED(Class, Super) \ + NS_IMPL_RELEASE_INHERITED(Class, Super) \ + +/////////////////////////////////////////////////////////////////////////////// +/** + * + * Threadsafe implementations of the ISupports convenience macros + * + */ + +/** + * Use this macro to implement the AddRef method for a given <i>_class</i> + * @param _class The name of the class implementing the method + */ + +#ifdef VBOX +#define NS_IMPL_THREADSAFE_ADDREF(_class) \ +NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \ +{ \ + nsrefcnt count = mRefCnt.get(); \ + PRUint32 state = mRefCnt.getState(); \ + AssertReleaseMsg( state <= 1 \ + && ( (state == 0 && count == 0) \ + || (state == 1 && count < PR_UINT32_MAX/2)), \ + ("AddRef: illegal refcnt=%u state=%d\n", count, state)); \ + switch (state) \ + { \ + case 0: \ + if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 1, 0)) \ + AssertReleaseMsgFailed(("AddRef: racing for first increment\n")); \ + count = ASMAtomicIncU32(mRefCnt.ref()); \ + AssertReleaseMsg(count == 1, \ + ("AddRef: unexpected refcnt=%u\n", count)); \ + break; \ + case 1: \ + count = ASMAtomicIncU32(mRefCnt.ref()); \ + AssertReleaseMsg(count <= PR_UINT32_MAX/2, \ + ("AddRef: unexpected refcnt=%u\n", count)); \ + break; \ + case 2: \ + AssertReleaseMsgFailed(("AddRef: freed object\n")); \ + break; \ + default: \ + AssertReleaseMsgFailed(("AddRef: garbage object\n")); \ + } \ + NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \ + return count; \ +} +#else +#define NS_IMPL_THREADSAFE_ADDREF(_class) \ +NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \ +{ \ + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + nsrefcnt count; \ + count = PR_AtomicIncrement((PRInt32*)&mRefCnt); \ + NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \ + return count; \ +} +#endif + +/** + * Use this macro to implement the Release method for a given <i>_class</i> + * @param _class The name of the class implementing the method + */ + +#ifdef VBOX +#define NS_IMPL_THREADSAFE_RELEASE(_class) \ +NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \ +{ \ + nsrefcnt count = mRefCnt.get(); \ + PRUint32 state = mRefCnt.getState(); \ + AssertReleaseMsg(state == 1 && count <= PR_UINT32_MAX/2, \ + ("Release: illegal refcnt=%u state=%d\n", count, state)); \ + switch (state) \ + { \ + case 0: \ + AssertReleaseMsgFailed(("Release: new object\n")); \ + break; \ + case 1: \ + count = ASMAtomicDecU32(mRefCnt.ref()); \ + AssertReleaseMsg(count < PR_UINT32_MAX/2, \ + ("Release: unexpected refcnt=%u\n", count)); \ + if (count == 0) \ + { \ + if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 2, 1)) \ + AssertReleaseMsgFailed(("Release: racing for state free\n")); \ + /* Use better stabilization: reserve everything with top bit set. */ \ + if (!ASMAtomicCmpXchgU32(mRefCnt.ref(), PR_UINT32_MAX/4*3, 0)) \ + AssertReleaseMsgFailed(("Release: racing for refcnt stabilize\n")); \ + NS_DELETEXPCOM(this); \ + } \ + break; \ + case 2: \ + AssertReleaseMsgFailed(("Release: freed object\n")); \ + break; \ + default: \ + AssertReleaseMsgFailed(("Release: garbage object\n")); \ + } \ + NS_LOG_RELEASE(this, count, #_class); \ + return count; \ +} +#else +#define NS_IMPL_THREADSAFE_RELEASE(_class) \ +NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \ +{ \ + nsrefcnt count; \ + NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); \ + NS_LOG_RELEASE(this, count, #_class); \ + if (0 == count) { \ + mRefCnt = 1; /* stabilize */ \ + /* enable this to find non-threadsafe destructors: */ \ + /* NS_ASSERT_OWNINGTHREAD(_class); */ \ + NS_DELETEXPCOM(this); \ + return 0; \ + } \ + return count; \ +} +#endif + +#define NS_IMPL_THREADSAFE_ISUPPORTS0(_class) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE0(_class) + +#define NS_IMPL_THREADSAFE_ISUPPORTS1(_class, _interface) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE1(_class, _interface) + +#define NS_IMPL_THREADSAFE_ISUPPORTS2(_class, _i1, _i2) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE2(_class, _i1, _i2) + +#define NS_IMPL_THREADSAFE_ISUPPORTS3(_class, _i1, _i2, _i3) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE3(_class, _i1, _i2, _i3) + +#define NS_IMPL_THREADSAFE_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4) + +#define NS_IMPL_THREADSAFE_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5) + +#define NS_IMPL_THREADSAFE_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) + +#define NS_IMPL_THREADSAFE_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7) + +#define NS_IMPL_THREADSAFE_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8) + +#define NS_IMPL_THREADSAFE_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9) + +#define NS_IMPL_THREADSAFE_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10) + +#define NS_IMPL_THREADSAFE_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10, _i11) \ + NS_IMPL_THREADSAFE_ADDREF(_class) \ + NS_IMPL_THREADSAFE_RELEASE(_class) \ + NS_IMPL_THREADSAFE_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10, _i11) + +/////////////////////////////////////////////////////////////////////////////// +// Macros for implementing nsIClassInfo-related stuff. +/////////////////////////////////////////////////////////////////////////////// + +// include here instead of at the top because it requires the nsISupport decl +#include "nsIClassInfo.h" + +#define NS_CLASSINFO_NAME(_class) _class##_classInfoGlobal +#define NS_CI_INTERFACE_GETTER_NAME(_class) _class##_GetInterfacesHelper + +#define NS_DECL_CI_INTERFACE_GETTER(_class) \ + extern NS_IMETHODIMP NS_CI_INTERFACE_GETTER_NAME(_class)(PRUint32 *, \ + nsIID ***); + +#define NS_DECL_CLASSINFO(_class) \ + NS_DECL_CI_INTERFACE_GETTER(_class) \ + nsIClassInfo *NS_CLASSINFO_NAME(_class); + +#define NS_IMPL_QUERY_CLASSINFO(_class) \ + if ( aIID.Equals(NS_GET_IID(nsIClassInfo)) ) { \ + extern nsIClassInfo *NS_CLASSINFO_NAME(_class); \ + foundInterface = NS_STATIC_CAST(nsIClassInfo*, NS_CLASSINFO_NAME(_class));\ + } else + +#define NS_CLASSINFO_HELPER_BEGIN(_class, _c) \ +NS_IMETHODIMP \ +NS_CI_INTERFACE_GETTER_NAME(_class)(PRUint32 *count, nsIID ***array) \ +{ \ + *count = _c; \ + *array = (nsIID **)nsMemory::Alloc(sizeof (nsIID *) * _c); + +#define NS_CLASSINFO_HELPER_ENTRY(_i, _interface) \ + (*array)[_i] = (nsIID *)nsMemory::Clone(&NS_GET_IID(_interface), \ + sizeof(nsIID)); + +#define NS_CLASSINFO_HELPER_END \ + return NS_OK; \ +} + +#define NS_IMPL_CI_INTERFACE_GETTER1(_class, _interface) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 1) \ + NS_CLASSINFO_HELPER_ENTRY(0, _interface) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE1_CI(_class, _i1) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS1_CI(_class, _interface) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE1_CI(_class, _interface) \ + NS_IMPL_CI_INTERFACE_GETTER1(_class, _interface) + +#define NS_IMPL_CI_INTERFACE_GETTER2(_class, _i1, _i2) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 2) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE2_CI(_class, _i1, _i2) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS2_CI(_class, _i1, _i2) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE2_CI(_class, _i1, _i2) \ + NS_IMPL_CI_INTERFACE_GETTER2(_class, _i1, _i2) + +#define NS_IMPL_CI_INTERFACE_GETTER3(_class, _i1, _i2, _i3) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 3) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE3_CI(_class, _i1, _i2, _i3) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS3_CI(_class, _i1, _i2, _i3) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE3_CI(_class, _i1, _i2, _i3) \ + NS_IMPL_CI_INTERFACE_GETTER3(_class, _i1, _i2, _i3) + +#define NS_IMPL_CI_INTERFACE_GETTER4(_class, _i1, _i2, _i3, _i4) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 4) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE4_CI(_class, _i1, _i2, _i3, _i4) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS4_CI(_class, _i1, _i2, _i3, _i4) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE4_CI(_class, _i1, _i2, _i3, _i4) \ + NS_IMPL_CI_INTERFACE_GETTER4(_class, _i1, _i2, _i3, _i4) + +#define NS_IMPL_CI_INTERFACE_GETTER5(_class, _i1, _i2, _i3, _i4, _i5) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 5) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_ENTRY(4, _i5) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE5_CI(_class, _i1, _i2, _i3, _i4, _i5) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS5_CI(_class, _i1, _i2, _i3, _i4, _i5) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE5_CI(_class, _i1, _i2, _i3, _i4, _i5) \ + NS_IMPL_CI_INTERFACE_GETTER5(_class, _i1, _i2, _i3, _i4, _i5) + +#define NS_IMPL_CI_INTERFACE_GETTER6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 6) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_ENTRY(4, _i5) \ + NS_CLASSINFO_HELPER_ENTRY(5, _i6) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \ + NS_IMPL_CI_INTERFACE_GETTER6(_class, _i1, _i2, _i3, _i4, _i5, _i6) + +#define NS_IMPL_CI_INTERFACE_GETTER7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 7) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_ENTRY(4, _i5) \ + NS_CLASSINFO_HELPER_ENTRY(5, _i6) \ + NS_CLASSINFO_HELPER_ENTRY(6, _i7) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \ + NS_IMPL_CI_INTERFACE_GETTER7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) + +#define NS_IMPL_CI_INTERFACE_GETTER8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 8) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_ENTRY(4, _i5) \ + NS_CLASSINFO_HELPER_ENTRY(5, _i6) \ + NS_CLASSINFO_HELPER_ENTRY(6, _i7) \ + NS_CLASSINFO_HELPER_ENTRY(7, _i8) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \ + NS_IMPL_CI_INTERFACE_GETTER8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) + +#define NS_IMPL_CI_INTERFACE_GETTER9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 9) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_ENTRY(4, _i5) \ + NS_CLASSINFO_HELPER_ENTRY(5, _i6) \ + NS_CLASSINFO_HELPER_ENTRY(6, _i7) \ + NS_CLASSINFO_HELPER_ENTRY(7, _i8) \ + NS_CLASSINFO_HELPER_ENTRY(8, _i9) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY(_i9) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9) \ + NS_IMPL_CI_INTERFACE_GETTER9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9) + +#define NS_IMPL_CI_INTERFACE_GETTER10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 10) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_ENTRY(4, _i5) \ + NS_CLASSINFO_HELPER_ENTRY(5, _i6) \ + NS_CLASSINFO_HELPER_ENTRY(6, _i7) \ + NS_CLASSINFO_HELPER_ENTRY(7, _i8) \ + NS_CLASSINFO_HELPER_ENTRY(8, _i9) \ + NS_CLASSINFO_HELPER_ENTRY(9, _i10) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_CI_INTERFACE_GETTER11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10, _i11) \ + NS_CLASSINFO_HELPER_BEGIN(_class, 10) \ + NS_CLASSINFO_HELPER_ENTRY(0, _i1) \ + NS_CLASSINFO_HELPER_ENTRY(1, _i2) \ + NS_CLASSINFO_HELPER_ENTRY(2, _i3) \ + NS_CLASSINFO_HELPER_ENTRY(3, _i4) \ + NS_CLASSINFO_HELPER_ENTRY(4, _i5) \ + NS_CLASSINFO_HELPER_ENTRY(5, _i6) \ + NS_CLASSINFO_HELPER_ENTRY(6, _i7) \ + NS_CLASSINFO_HELPER_ENTRY(7, _i8) \ + NS_CLASSINFO_HELPER_ENTRY(8, _i9) \ + NS_CLASSINFO_HELPER_ENTRY(9, _i10) \ + NS_CLASSINFO_HELPER_ENTRY(10, _i11) \ + NS_CLASSINFO_HELPER_END + +#define NS_IMPL_QUERY_INTERFACE10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY(_i9) \ + NS_INTERFACE_MAP_ENTRY(_i10) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_QUERY_INTERFACE11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \ + _i7, _i8, _i9, _i10, _i11) \ + NS_INTERFACE_MAP_BEGIN(_class) \ + NS_INTERFACE_MAP_ENTRY(_i1) \ + NS_INTERFACE_MAP_ENTRY(_i2) \ + NS_INTERFACE_MAP_ENTRY(_i3) \ + NS_INTERFACE_MAP_ENTRY(_i4) \ + NS_INTERFACE_MAP_ENTRY(_i5) \ + NS_INTERFACE_MAP_ENTRY(_i6) \ + NS_INTERFACE_MAP_ENTRY(_i7) \ + NS_INTERFACE_MAP_ENTRY(_i8) \ + NS_INTERFACE_MAP_ENTRY(_i9) \ + NS_INTERFACE_MAP_ENTRY(_i10) \ + NS_INTERFACE_MAP_ENTRY(_i11) \ + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \ + NS_IMPL_QUERY_CLASSINFO(_class) \ + NS_INTERFACE_MAP_END + +#define NS_IMPL_ISUPPORTS10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9, _i10) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9, _i10) \ + NS_IMPL_CI_INTERFACE_GETTER10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9, _i10) + +#define NS_IMPL_ISUPPORTS11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9, _i10, _i11) \ + NS_IMPL_ADDREF(_class) \ + NS_IMPL_RELEASE(_class) \ + NS_IMPL_QUERY_INTERFACE11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9, _i10, _i11) \ + NS_IMPL_CI_INTERFACE_GETTER11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \ + _i8, _i9, _i10, _i11) + +#define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS + +#endif diff --git a/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h new file mode 100644 index 00000000..d8d002b1 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h @@ -0,0 +1,230 @@ +/* -*- 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): + * Pierre Phaneuf <pp@ludusdesign.com> + * Scott Collins <scc@ScottCollins.net> + * Dan Mosedale <dmose@mozilla.org> + * + * 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 nsISupportsUtils_h__ +#define nsISupportsUtils_h__ + +#ifndef nscore_h___ +#include "nscore.h" +#endif + +#ifndef nsISupportsBase_h__ +#include "nsISupportsBase.h" +#endif + +#ifndef nsError_h__ +#include "nsError.h" +#endif + +#ifndef nsDebug_h___ +#include "nsDebug.h" +#endif + +#ifndef nsISupportsImpl_h__ +#include "nsISupportsImpl.h" +#endif + +/** + * Macro for instantiating a new object that implements nsISupports. + * Note that you can only use this if you adhere to the no arguments + * constructor com policy (which you really should!). + * @param _result Where the new instance pointer is stored + * @param _type The type of object to call "new" with. + */ +#define NS_NEWXPCOM(_result,_type) \ + PR_BEGIN_MACRO \ + _result = new _type(); \ + PR_END_MACRO + +/** + * Macro for deleting an object that implements nsISupports. + * @param _ptr The object to delete. + */ +#define NS_DELETEXPCOM(_ptr) \ + PR_BEGIN_MACRO \ + delete (_ptr); \ + PR_END_MACRO + +/** + * Macro for adding a reference to an interface. + * @param _ptr The interface pointer. + */ +#define NS_ADDREF(_ptr) \ + (_ptr)->AddRef() + +/** + * Macro for adding a reference to this. This macro should be used + * because NS_ADDREF (when tracing) may require an ambiguous cast + * from the pointers primary type to nsISupports. This macro sidesteps + * that entire problem. + */ +#define NS_ADDREF_THIS() \ + AddRef() + + +extern "C++" { +// ...because some one is accidentally including this file inside +// an |extern "C"| + + +// Making this a |inline| |template| allows |expr| to be evaluated only once, +// yet still denies you the ability to |AddRef()| an |nsCOMPtr|. +template <class T> +inline +nsrefcnt +ns_if_addref( T expr ) +{ + return expr ? expr->AddRef() : 0; +} + +} /* extern "C++" */ + +/** + * Macro for adding a reference to an interface that checks for NULL. + * @param _expr The interface pointer. + */ +#define NS_IF_ADDREF(_expr) ns_if_addref(_expr) + +/* + * Given these declarations, it explicitly OK and efficient to end a `getter' with: + * + * NS_IF_ADDREF(*result = mThing); + * + * even if |mThing| is an |nsCOMPtr|. If |mThing| is an |nsCOMPtr|, however, it is still + * _illegal_ to say |NS_IF_ADDREF(mThing)|. + */ + +/** + * Macro for releasing a reference to an interface. + * @param _ptr The interface pointer. + */ +#define NS_RELEASE(_ptr) \ + PR_BEGIN_MACRO \ + (_ptr)->Release(); \ + (_ptr) = 0; \ + PR_END_MACRO + +/** + * Macro for releasing a reference to an interface. + * @param _ptr The interface pointer. + */ +#define NS_RELEASE_THIS() \ + Release() + +/** + * Macro for releasing a reference to an interface, except that this + * macro preserves the return value from the underlying Release call. + * The interface pointer argument will only be NULLed if the reference count + * goes to zero. + * + * @param _ptr The interface pointer. + */ +#define NS_RELEASE2(_ptr,_rv) \ + PR_BEGIN_MACRO \ + _rv = (_ptr)->Release(); \ + if (0 == (_rv)) (_ptr) = 0; \ + PR_END_MACRO + +/** + * Macro for releasing a reference to an interface that checks for NULL; + * @param _ptr The interface pointer. + */ +#define NS_IF_RELEASE(_ptr) \ + PR_BEGIN_MACRO \ + if (_ptr) { \ + (_ptr)->Release(); \ + (_ptr) = 0; \ + } \ + PR_END_MACRO + +/* + * Often you have to cast an implementation pointer, e.g., |this|, to an + * |nsISupports*|, but because you have multiple inheritance, a simple cast + * is ambiguous. One could simply say, e.g., (given a base |nsIBase|), + * |NS_STATIC_CAST(nsIBase*, this)|; but that disguises the fact that what + * you are really doing is disambiguating the |nsISupports|. You could make + * that more obvious with a double cast, e.g., |NS_STATIC_CAST(nsISupports*, + * NS_STATIC_CAST(nsIBase*, this))|, but that is bulky and harder to read... + * + * The following macro is clean, short, and obvious. In the example above, + * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|. + */ + +#define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \ + NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(__unambiguousBase, __expr)) + +extern "C++" { +// ...because some one is accidentally including this file inside +// an |extern "C"| + +class nsISupports; + +template <class T> +struct nsCOMTypeInfo +{ + static const nsIID& GetIID() { return T::GetIID(); } +}; + +NS_SPECIALIZE_TEMPLATE +struct nsCOMTypeInfo<nsISupports> +{ + static const nsIID& GetIID() { + static const nsIID iid_NS_ISUPPORTS_IID = NS_ISUPPORTS_IID; return iid_NS_ISUPPORTS_IID; + } +}; + +#define NS_GET_IID(T) nsCOMTypeInfo<T>::GetIID() + +// a type-safe shortcut for calling the |QueryInterface()| member function +template <class T, class DestinationType> +inline +nsresult +CallQueryInterface( T* aSource, DestinationType** aDestination ) +{ + NS_PRECONDITION(aSource, "null parameter"); + NS_PRECONDITION(aDestination, "null parameter"); + + return aSource->QueryInterface(NS_GET_IID(DestinationType), + NS_REINTERPRET_CAST(void**, aDestination)); +} + +} // extern "C++" + +#endif /* __nsISupportsUtils_h */ diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h new file mode 100644 index 00000000..17d1bd79 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h @@ -0,0 +1,162 @@ +/* -*- 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): + * Scott Collins <scc@mozilla.org> (Original Author) + * + * 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 nsIWeakReferenceUtils_h__ +#define nsIWeakReferenceUtils_h__ + +#ifndef nsCOMPtr_h__ +#include "nsCOMPtr.h" +#endif + +typedef nsCOMPtr<nsIWeakReference> nsWeakPtr; + +/** + * + */ + +// a type-safe shortcut for calling the |QueryReferent()| member function +// T must inherit from nsIWeakReference, but the cast may be ambiguous. +template <class T, class DestinationType> +inline +nsresult +CallQueryReferent( T* aSource, DestinationType** aDestination ) + { + NS_PRECONDITION(aSource, "null parameter"); + NS_PRECONDITION(aDestination, "null parameter"); + + return aSource->QueryReferent(NS_GET_IID(DestinationType), + NS_REINTERPRET_CAST(void**, aDestination)); + } + + +class NS_COM nsQueryReferent : public nsCOMPtr_helper + { + public: + nsQueryReferent( nsIWeakReference* aWeakPtr, nsresult* error ) + : mWeakPtr(aWeakPtr), + mErrorPtr(error) + { + // nothing else to do here + } + + virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const; + + private: + nsIWeakReference* mWeakPtr; + nsresult* mErrorPtr; + }; + +inline +const nsQueryReferent +do_QueryReferent( nsIWeakReference* aRawPtr, nsresult* error = 0 ) + { + return nsQueryReferent(aRawPtr, error); + } + + + +class NS_COM nsGetWeakReference : public nsCOMPtr_helper + { + public: + nsGetWeakReference( nsISupports* aRawPtr, nsresult* error ) + : mRawPtr(aRawPtr), + mErrorPtr(error) + { + // nothing else to do here + } + + virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const; + + private: + nsISupports* mRawPtr; + nsresult* mErrorPtr; + }; + + /** + * |do_GetWeakReference| is a convenience function that bundles up all the work needed + * to get a weak reference to an arbitrary object, i.e., the |QueryInterface|, test, and + * call through to |GetWeakReference|, and put it into your |nsCOMPtr|. + * It is specifically designed to cooperate with |nsCOMPtr| (or |nsWeakPtr|) like so: + * |nsWeakPtr myWeakPtr = do_GetWeakReference(aPtr);|. + */ +inline +const nsGetWeakReference +do_GetWeakReference( nsISupports* aRawPtr, nsresult* error = 0 ) + { + return nsGetWeakReference(aRawPtr, error); + } + +inline +void +do_GetWeakReference( nsIWeakReference* aRawPtr, nsresult* error = 0 ) + { + // This signature exists soley to _stop_ you from doing a bad thing. + // Saying |do_GetWeakReference()| on a weak reference itself, + // is very likely to be a programmer error. + } + +template <class T> +inline +void +do_GetWeakReference( already_AddRefed<T>& ) + { + // This signature exists soley to _stop_ you from doing the bad thing. + // Saying |do_GetWeakReference()| on a pointer that is not otherwise owned by + // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>. + } + +template <class T> +inline +void +do_GetWeakReference( already_AddRefed<T>&, nsresult* ) + { + // This signature exists soley to _stop_ you from doing the bad thing. + // Saying |do_GetWeakReference()| on a pointer that is not otherwise owned by + // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>. + } + + + + /** + * Deprecated, use |do_GetWeakReference| instead. + */ +extern NS_COM +nsIWeakReference* +NS_GetWeakReference( nsISupports* , nsresult* aResult=0 ); + +#endif diff --git a/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp b/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp new file mode 100644 index 00000000..2449c58e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp @@ -0,0 +1,151 @@ +/* -*- 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 "nsXPCOM.h" +#include "nsMemory.h" +#include "nsXPCOMPrivate.h" + +static nsIMemory* gMemory = nsnull; + +static NS_METHOD FreeGlobalMemory(void) +{ + NS_ASSERTION(gMemory, "must be not null after SetupGlobalMemory"); + NS_IF_RELEASE(gMemory); + return NS_OK; +} + +#define ENSURE_ALLOCATOR \ + (gMemory ? PR_TRUE : (PRBool)(SetupGlobalMemory() != nsnull)) + +static nsIMemory* +SetupGlobalMemory() +{ + NS_ASSERTION(!gMemory, "must be called once"); + if (!gMemory) + { + NS_GetMemoryManager(&gMemory); + NS_ASSERTION(gMemory, "can't get memory manager!"); + if (gMemory) + NS_RegisterXPCOMExitRoutine(FreeGlobalMemory, 0); + } + return gMemory; +} + +#ifdef XPCOM_GLUE +nsresult GlueStartupMemory() +{ + NS_ASSERTION(!gMemory, "must be called once"); + if (!gMemory) + { + NS_GetMemoryManager(&gMemory); + NS_ASSERTION(gMemory, "can't get memory manager!"); + if (!gMemory) + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +void GlueShutdownMemory() +{ + NS_IF_RELEASE(gMemory); +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +// nsMemory static helper routines + +NS_COM void* +nsMemory::Alloc(PRSize size) +{ + if (!ENSURE_ALLOCATOR) + return nsnull; + + return gMemory->Alloc(size); +} + +NS_COM void* +nsMemory::Realloc(void* ptr, PRSize size) +{ + if (!ENSURE_ALLOCATOR) + return nsnull; + + return gMemory->Realloc(ptr, size); +} + +NS_COM void +nsMemory::Free(void* ptr) +{ + if (!ENSURE_ALLOCATOR) + return; + + gMemory->Free(ptr); +} + +NS_COM nsresult +nsMemory::HeapMinimize(PRBool aImmediate) +{ + if (!ENSURE_ALLOCATOR) + return NS_ERROR_FAILURE; + + return gMemory->HeapMinimize(aImmediate); +} + +NS_COM void* +nsMemory::Clone(const void* ptr, PRSize size) +{ + if (!ENSURE_ALLOCATOR) + return nsnull; + + void* newPtr = gMemory->Alloc(size); + if (newPtr) + memcpy(newPtr, ptr, size); + return newPtr; +} + +NS_COM nsIMemory* +nsMemory::GetGlobalMemoryService() +{ + if (!ENSURE_ALLOCATOR) + return nsnull; + + nsIMemory* result = gMemory; + NS_IF_ADDREF(result); + return result; +} + +//---------------------------------------------------------------------- + diff --git a/src/libs/xpcom18a4/xpcom/glue/nsMemory.h b/src/libs/xpcom18a4/xpcom/glue/nsMemory.h new file mode 100644 index 00000000..4ee48bf0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsMemory.h @@ -0,0 +1,154 @@ +/* -*- 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 nsMemory_h__ +#define nsMemory_h__ + +#include "nsIMemory.h" + +#define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1" +#define NS_MEMORY_CLASSNAME "Global Memory Service" +#define NS_MEMORY_CID \ +{ /* 30a04e40-38e7-11d4-8cf5-0060b0fc14a3 */ \ + 0x30a04e40, \ + 0x38e7, \ + 0x11d4, \ + {0x8c, 0xf5, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \ +} + + +/** + * Static helper routines to manage memory. These routines allow easy access + * to xpcom's built-in (global) nsIMemory implementation, without needing + * to go through the service manager to get it. However this requires clients + * to link with the xpcom DLL. + * + * This class is not threadsafe and is intented for use only on the main + * thread. + */ +class nsMemory +{ +public: + static NS_COM void* Alloc(size_t size); + static NS_COM void* Realloc(void* ptr, size_t size); + static NS_COM void Free(void* ptr); + static NS_COM nsresult HeapMinimize(PRBool aImmediate); + static NS_COM void* Clone(const void* ptr, size_t size); + static NS_COM nsIMemory* GetGlobalMemoryService(); // AddRefs +}; + +/** + * Macro to free all elements of an XPCOM array of a given size using + * freeFunc, then frees the array itself using nsMemory::Free(). + * + * Note that this macro (and its wrappers) can be used to deallocate a + * partially- or completely-built array while unwinding an error + * condition inside the XPCOM routine that was going to return the + * array. For this to work on a partially-built array, your code + * needs to be building the array from index 0 upwards, and simply + * pass the number of elements that have already been built (and thus + * need to be freed) as |size|. + * + * Thanks to <alecf@netscape.com> for suggesting this form, which + * allows the macro to be used with NS_RELEASE / NS_RELEASE_IF in + * addition to nsMemory::Free. + * + * @param size Number of elements in the array. If not a constant, this + * should be a PRInt32. Note that this means this macro + * will not work if size >= 2^31. + * @param array The array to be freed. + * @param freeFunc The function or macro to be used to free it. + * For arrays of nsISupports (or any class derived + * from it), NS_IF_RELEASE (or NS_RELEASE) should be + * passed as freeFunc. For most (all?) other pointer + * types (including XPCOM strings and wstrings), + * nsMemory::Free should be used, since the + * shared-allocator (nsMemory) is what will have been + * used to allocate the memory. + */ +#define NS_FREE_XPCOM_POINTER_ARRAY(size, array, freeFunc) \ + PR_BEGIN_MACRO \ + PRInt32 iter_ = PRInt32(size); \ + while (--iter_ >= 0) \ + freeFunc((array)[iter_]); \ + nsMemory::Free((array)); \ + PR_END_MACRO + +// convenience macros for commonly used calls. mmmmm. syntactic sugar. + +/** + * Macro to free arrays of non-refcounted objects allocated by the + * shared allocator (nsMemory) such as strings and wstrings. A + * convenience wrapper around NS_FREE_XPCOM_POINTER_ARRAY. + * + * @param size Number of elements in the array. If not a constant, this + * should be a PRInt32. Note that this means this macro + * will not work if size >= 2^31. + * @param array The array to be freed. + */ +#define NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(size, array) \ + NS_FREE_XPCOM_POINTER_ARRAY((size), (array), nsMemory::Free) + +/** + * Macro to free an array of pointers to nsISupports (or classes + * derived from it). A convenience wrapper around + * NS_FREE_XPCOM_POINTER_ARRAY. + * + * Note that if you know that none of your nsISupports pointers are + * going to be 0, you can gain a bit of speed by calling + * NS_FREE_XPCOM_POINTER_ARRAY directly and using NS_RELEASE as your + * free function. + * + * @param size Number of elements in the array. If not a constant, this + * should be a PRInt32. Note that this means this macro + * will not work if size >= 2^31. + * @param array The array to be freed. + */ +#define NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(size, array) \ + NS_FREE_XPCOM_POINTER_ARRAY((size), (array), NS_IF_RELEASE) + +/** + * Helpful array length function for calculating the length of a + * statically declared array. + */ + +#define NS_ARRAY_LENGTH(array_) \ + (sizeof(array_)/sizeof(array_[0])) + + +#endif // nsMemory_h__ + diff --git a/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h new file mode 100644 index 00000000..b225b6a2 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h @@ -0,0 +1,183 @@ +/* -*- 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 + } + + 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/glue/nsTraceRefcnt.cpp b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp new file mode 100644 index 00000000..14e9469b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp @@ -0,0 +1,125 @@ +/* ***** 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 Doug Turner <dougt@meer.net> + * + * 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 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 "nsXPCOM.h" +#include "nsXPCOMPrivate.h" +#include "nsCOMPtr.h" +#include "nsIServiceManager.h" +#include "nsTraceRefcnt.h" +#include "nsTraceRefcntImpl.h" + +static nsITraceRefcnt* gTraceRefcntObject = nsnull; + +static NS_METHOD FreeTraceRefcntObject(void) +{ + NS_IF_RELEASE(gTraceRefcntObject); + return NS_OK; +} + +#define ENSURE_TRACEOBJECT \ + (gTraceRefcntObject || SetupTraceRefcntObject() != nsnull) + +static nsITraceRefcnt* SetupTraceRefcntObject() +{ + NS_GetTraceRefcnt(&gTraceRefcntObject); + if (gTraceRefcntObject) + NS_RegisterXPCOMExitRoutine(FreeTraceRefcntObject, 0); + return gTraceRefcntObject; +} + +#ifdef XPCOM_GLUE +nsresult GlueStartupTraceRefcnt() +{ + NS_GetTraceRefcnt(&gTraceRefcntObject); + if (!gTraceRefcntObject) + return NS_ERROR_FAILURE; + return NS_OK; +} + +void GlueShutdownTraceRefcnt() +{ + NS_IF_RELEASE(gTraceRefcntObject); +} +#endif + +NS_COM void +nsTraceRefcnt::LogAddRef(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName, PRUint32 aInstanceSize) +{ + if (!ENSURE_TRACEOBJECT) + return; + gTraceRefcntObject->LogAddRef(aPtr, aNewRefcnt, aTypeName, aInstanceSize); +} + +NS_COM void +nsTraceRefcnt::LogRelease(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName) +{ + if (!ENSURE_TRACEOBJECT) + return; + gTraceRefcntObject->LogRelease(aPtr, aNewRefcnt, aTypeName); +} + +NS_COM void +nsTraceRefcnt::LogCtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize) +{ + if (!ENSURE_TRACEOBJECT) + return; + gTraceRefcntObject->LogCtor(aPtr, aTypeName, aInstanceSize); +} + +NS_COM void +nsTraceRefcnt::LogDtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize) +{ + if (!ENSURE_TRACEOBJECT) + return; + gTraceRefcntObject->LogDtor(aPtr, aTypeName, aInstanceSize); +} + +NS_COM void +nsTraceRefcnt::LogAddCOMPtr(void * aPtr, nsISupports *aObject) +{ + if (!ENSURE_TRACEOBJECT) + return; + gTraceRefcntObject->LogAddCOMPtr(aPtr, aObject); +} + +NS_COM void +nsTraceRefcnt::LogReleaseCOMPtr(void * aPtr, nsISupports *aObject) +{ + if (!ENSURE_TRACEOBJECT) + return; + gTraceRefcntObject->LogReleaseCOMPtr(aPtr, aObject); +} + diff --git a/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h new file mode 100644 index 00000000..afafda4b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h @@ -0,0 +1,135 @@ +/* -*- 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 Communicator client 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): + * L. David Baron <dbaron@dbaron.org> + * + * 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 nsTraceRefcnt_h___ +#define nsTraceRefcnt_h___ + +#include "nscore.h" + +class nsISupports; + +// By default refcnt logging is not part of the build. +#undef NS_BUILD_REFCNT_LOGGING + +#if (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING)) +// Make refcnt logging part of the build. This doesn't mean that +// actual logging will occur (that requires a separate enable; see +// nsTraceRefcnt.h for more information). +#define NS_BUILD_REFCNT_LOGGING 1 +#endif + +// If NO_BUILD_REFCNT_LOGGING is defined then disable refcnt logging +// in the build. This overrides FORCE_BUILD_REFCNT_LOGGING. +#if defined(NO_BUILD_REFCNT_LOGGING) +#undef NS_BUILD_REFCNT_LOGGING +#endif + +#ifdef NS_BUILD_REFCNT_LOGGING + +#define NS_LOG_ADDREF(_p, _rc, _type, _size) \ + nsTraceRefcnt::LogAddRef((_p), (_rc), (_type), (PRUint32) (_size)) + +#define NS_LOG_RELEASE(_p, _rc, _type) \ + nsTraceRefcnt::LogRelease((_p), (_rc), (_type)) + +#define MOZ_DECL_CTOR_COUNTER(_type) + +#define MOZ_COUNT_CTOR(_type) \ +PR_BEGIN_MACRO \ + nsTraceRefcnt::LogCtor((void*)this, #_type, sizeof(*this)); \ +PR_END_MACRO + +#define MOZ_COUNT_DTOR(_type) \ +PR_BEGIN_MACRO \ + nsTraceRefcnt::LogDtor((void*)this, #_type, sizeof(*this)); \ +PR_END_MACRO + +#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR // from autoconf (XXX needs to be + // set for non-autoconf platforms) + +// nsCOMPtr.h allows these macros to be defined by clients +// These logging functions require dynamic_cast<void *>, so we don't +// define these macros if we don't have dynamic_cast. +#define NSCAP_LOG_ASSIGNMENT(_c, _p) \ + if (_p) \ + nsTraceRefcnt::LogAddCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p)) + +#define NSCAP_LOG_RELEASE(_c, _p) \ + if (_p) \ + nsTraceRefcnt::LogReleaseCOMPtr((_c), NS_STATIC_CAST(nsISupports*,_p)) + +#endif /* HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR */ + +#else /* !NS_BUILD_REFCNT_LOGGING */ + +#define NS_LOG_ADDREF(_p, _rc, _type, _size) +#define NS_LOG_RELEASE(_p, _rc, _type) +#define MOZ_DECL_CTOR_COUNTER(_type) +#define MOZ_COUNT_CTOR(_type) +#define MOZ_COUNT_DTOR(_type) + +#endif /* NS_BUILD_REFCNT_LOGGING */ + +//---------------------------------------------------------------------- + +/** + * Note: The implementations for these methods are no-ops in a build + * where NS_BUILD_REFCNT_LOGGING is disabled. + */ +class nsTraceRefcnt { +public: + static NS_COM void LogAddRef(void* aPtr, + nsrefcnt aNewRefCnt, + const char* aTypeName, + PRUint32 aInstanceSize); + + static NS_COM void LogRelease(void* aPtr, + nsrefcnt aNewRefCnt, + const char* aTypeName); + + static NS_COM void LogCtor(void* aPtr, const char* aTypeName, + PRUint32 aInstanceSize); + + static NS_COM void LogDtor(void* aPtr, const char* aTypeName, + PRUint32 aInstanceSize); + + static NS_COM void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject); + + static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject); + +}; +#endif /* nsTraceRefcnt_h___ */ diff --git a/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp new file mode 100644 index 00000000..76d9f593 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp @@ -0,0 +1,169 @@ +/* -*- 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 the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@netscape.com> + * Pierre Phaneuf <pp@ludusdesign.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 ***** */ + +// nsWeakReference.cpp + +#include "nsWeakReference.h" +#include "nsCOMPtr.h" + +nsresult +nsQueryReferent::operator()( const nsIID& aIID, void** answer ) const + { + nsresult status; + if ( mWeakPtr ) + { + if ( NS_FAILED(status = mWeakPtr->QueryReferent(aIID, answer)) ) + *answer = 0; + } + else + status = NS_ERROR_NULL_POINTER; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; + } + +nsresult +nsGetWeakReference::operator()( const nsIID&, void** aResult ) const + { + nsresult status; + // nsIWeakReference** result = &NS_STATIC_CAST(nsIWeakReference*, *aResult); + *aResult = 0; + + if ( mRawPtr ) + { + nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(mRawPtr, &status); + NS_ASSERTION(factoryPtr, "Oops! You're asking for a weak reference to an object that doesn't support that."); + if ( factoryPtr ) + { + nsIWeakReference* temp; + status = factoryPtr->GetWeakReference(&temp); + *aResult = temp; + } + // else, |status| has already been set by |do_QueryInterface| + } + else + status = NS_ERROR_NULL_POINTER; + + if ( mErrorPtr ) + *mErrorPtr = status; + return status; + } + + +NS_COM nsIWeakReference* // or else |already_AddRefed<nsIWeakReference>| +NS_GetWeakReference( nsISupports* aInstancePtr, nsresult* aErrorPtr ) + { + void* result = 0; + nsGetWeakReference(aInstancePtr, aErrorPtr)(NS_GET_IID(nsIWeakReference), &result); + return NS_STATIC_CAST(nsIWeakReference*, result); + } + +NS_COM nsresult +nsSupportsWeakReference::GetWeakReference( nsIWeakReference** aInstancePtr ) + { + if ( !aInstancePtr ) + return NS_ERROR_NULL_POINTER; + + if ( !mProxy ) + mProxy = new nsWeakReference(this); + *aInstancePtr = mProxy; + + nsresult status; + if ( !*aInstancePtr ) + status = NS_ERROR_OUT_OF_MEMORY; + else + { + NS_ADDREF(*aInstancePtr); + status = NS_OK; + } + + return status; + } + +NS_IMETHODIMP_(nsrefcnt) +nsWeakReference::AddRef() + { + return ++mRefCount; + } + +NS_IMETHODIMP_(nsrefcnt) +nsWeakReference::Release() + { + nsrefcnt temp = --mRefCount; + if ( !mRefCount ) + delete this; + return temp; + } + +NS_IMETHODIMP +nsWeakReference::QueryInterface( const nsIID& aIID, void** aInstancePtr ) + { + NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); + + if ( !aInstancePtr ) + return NS_ERROR_NULL_POINTER; + + nsISupports* foundInterface; + if ( aIID.Equals(NS_GET_IID(nsIWeakReference)) ) + foundInterface = NS_STATIC_CAST(nsIWeakReference*, this); + else if ( aIID.Equals(NS_GET_IID(nsISupports)) ) + foundInterface = NS_STATIC_CAST(nsISupports*, this); + else + foundInterface = 0; + + nsresult status; + if ( !foundInterface ) + status = NS_NOINTERFACE; + else + { + NS_ADDREF(foundInterface); + status = NS_OK; + } + + *aInstancePtr = foundInterface; + return status; + } + +NS_IMETHODIMP +nsWeakReference::QueryReferent( const nsIID& aIID, void** aInstancePtr ) + { + return mReferent ? mReferent->QueryInterface(aIID, aInstancePtr) : NS_ERROR_NULL_POINTER; + } diff --git a/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h new file mode 100644 index 00000000..96e63f22 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h @@ -0,0 +1,150 @@ +/* -*- 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 the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * 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 ***** */ + +#ifndef nsWeakReference_h__ +#define nsWeakReference_h__ + +// nsWeakReference.h + +#include "nsIWeakReference.h" + +class nsWeakReference; + +#undef IMETHOD_VISIBILITY +#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT + +class NS_COM nsSupportsWeakReference : public nsISupportsWeakReference + { + public: + nsSupportsWeakReference() + : mProxy(0) + { + // nothing else to do here + } + + NS_DECL_NSISUPPORTSWEAKREFERENCE + + protected: + inline ~nsSupportsWeakReference(); + + private: + friend class nsWeakReference; + + void + NoticeProxyDestruction() + // ...called (only) by an |nsWeakReference| from _its_ dtor. + { + mProxy = 0; + } + + nsWeakReference* mProxy; + + protected: + + inline void ClearWeakReferences(); + PRBool HasWeakReferences() const {return mProxy != 0;} + }; + +#undef IMETHOD_VISIBILITY +#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN + +class NS_COM nsWeakReference : public nsIWeakReference + { + public: + // nsISupports... + NS_IMETHOD_(nsrefcnt) AddRef(); + NS_IMETHOD_(nsrefcnt) Release(); + NS_IMETHOD QueryInterface( const nsIID&, void** ); + + // nsIWeakReference... + NS_DECL_NSIWEAKREFERENCE + + private: + friend class nsSupportsWeakReference; + + nsWeakReference( nsSupportsWeakReference* referent ) + : mRefCount(0), + mReferent(referent) + // ...I can only be constructed by an |nsSupportsWeakReference| + { + // nothing else to do here + } + + ~nsWeakReference() + // ...I will only be destroyed by calling |delete| myself. + { + if ( mReferent ) + mReferent->NoticeProxyDestruction(); + } + + void + NoticeReferentDestruction() + // ...called (only) by an |nsSupportsWeakReference| from _its_ dtor. + { + mReferent = 0; + } + + nsrefcnt mRefCount; + nsSupportsWeakReference* mReferent; + }; + +inline +void +nsSupportsWeakReference::ClearWeakReferences() + /* + Usually being called from |nsSupportsWeakReference::~nsSupportsWeakReference| + will be good enough, but you may have a case where you need to call disconnect + your weak references in an outer destructor (to prevent some client holding a + weak reference from re-entering your destructor). + */ + { + if ( mProxy ) + { + mProxy->NoticeReferentDestruction(); + mProxy = 0; + } + } + +inline +nsSupportsWeakReference::~nsSupportsWeakReference() + { + ClearWeakReferences(); + } + +#endif diff --git a/src/libs/xpcom18a4/xpcom/glue/objs.mk b/src/libs/xpcom18a4/xpcom/glue/objs.mk new file mode 100644 index 00000000..d6d04a5a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/objs.mk @@ -0,0 +1,60 @@ +# ***** 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. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2002 +# 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 ***** + +XPCOM_GLUE_SRC_LCSRCS = \ + nsCOMPtr.cpp \ + nsComponentManagerUtils.cpp \ + nsDebug.cpp \ + nsGenericFactory.cpp \ + nsIInterfaceRequestorUtils.cpp \ + nsMemory.cpp \ + nsTraceRefcnt.cpp \ + nsWeakReference.cpp \ + $(NULL) \ + +XPCOM_GLUE_SRC_LEXPORTS = \ + nsCOMPtr.h \ + nsDebug.h \ + nsGenericFactory.h \ + nsIGenericFactory.h \ + nsMemory.h \ + nsTraceRefcnt.h \ + nsWeakReference.h \ + $(NULL) + + + +XPCOM_GLUE_SRC_CSRCS := $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCSRCS)) diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore b/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore new file mode 100644 index 00000000..a0182c1f --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore @@ -0,0 +1,8 @@ +Makefile +nsCOMPtr.cpp +nsDebug.cpp +nsGenericFactory.cpp +nsIInterfaceRequestorUtils.cpp +nsMemory.cpp +nsWeakReference.cpp +nsComponentManagerUtils.cpp diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in b/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in new file mode 100644 index 00000000..ae23d8e0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in @@ -0,0 +1,88 @@ +# ***** 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. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2002 +# 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk +include $(srcdir)/../objs.mk + +MODULE = xpcom +LIBRARY_NAME = xpcomglue + +REQUIRES = string \ + $(NULL) + +LOCAL_INCLUDES = \ + -I$(srcdir)/../../build \ + $(NULL) + +CPPSRCS = \ + $(XPCOM_GLUE_SRC_LCSRCS) \ + nsXPCOMGlue.cpp \ + nsGREDirServiceProvider.cpp \ + $(NULL) + +SDK_HEADERS = \ + nsXPCOMGlue.h \ + $(NULL) + +SDK_LIBRARY = \ + $(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \ + $(NULL) + +# 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 + +GARBAGE += $(XPCOM_GLUE_SRC_LCSRCS) $(wildcard *.$(OBJ_SUFFIX)) + +ifeq ($(OS_ARCH),WINNT) +GARBAGE += $(addprefix $(srcdir)/,$(XPCOM_GLUE_SRC_LCSRCS)) +endif + +SRCS_IN_OBJDIR = 1 + +include $(topsrcdir)/config/rules.mk + +export:: $(XPCOM_GLUE_SRC_CSRCS) + $(INSTALL) $^ . + +DEFINES += -DXPCOM_GLUE diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp new file mode 100644 index 00000000..4a1247eb --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp @@ -0,0 +1,596 @@ +/* -*- 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 Communicator. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corp. + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sean Su <ssu@netscape.com> + * + * 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 "nsBuildID.h" + +#include "nsEmbedString.h" +#include "nsXPCOMPrivate.h" +#include "nsXPCOMGlue.h" +#include "nsILocalFile.h" +#include "nsIDirectoryService.h" +#include "nsDirectoryServiceDefs.h" +#include "nsCOMPtr.h" + +#include "nspr.h" +#include "plstr.h" + +#ifdef XP_WIN32 +#include <windows.h> +#include <stdlib.h> +#elif defined(XP_OS2) +#define INCL_DOS +#include <os2.h> +#include <stdlib.h> +#include <stdio.h> +#include "prenv.h" +#elif defined(XP_MACOSX) +#include <Processes.h> +#include <CFBundle.h> +#elif defined(XP_UNIX) +#include <unistd.h> +#include <stdlib.h> +#include <sys/param.h> +#include <dlfcn.h> +#include "prenv.h" +#elif defined(XP_BEOS) +#include <FindDirectory.h> +#include <Path.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/param.h> +#include <OS.h> +#include <image.h> +#include "prenv.h" +#endif + +#include <sys/stat.h> + +#include "nsGREDirServiceProvider.h" + +PRBool GRE_GetCurrentProcessDirectory(char* buffer); +PRBool GRE_GetPathFromConfigDir(const char* dirname, char* buffer); +PRBool GRE_GetPathFromConfigFile(const char* dirname, char* buffer); + +//***************************************************************************** +// nsGREDirServiceProvider::nsISupports +//***************************************************************************** + +NS_IMPL_ISUPPORTS1(nsGREDirServiceProvider, nsIDirectoryServiceProvider) + +//***************************************************************************** +// nsGREDirServiceProvider::nsIDirectoryServiceProvider +//***************************************************************************** + +NS_IMETHODIMP +nsGREDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval) +{ + *_retval = nsnull; + *persistant = PR_TRUE; + + //--------------------------------------------------------------- + // Note that by returning a valid localFile's for NS_GRE_DIR, + // your app is indicating to XPCOM that it found a GRE version + // with which it's compatible with and intends to be "run against" + // that GRE. + // + // Please see http://www.mozilla.org/projects/embedding/GRE.html + // for more info on GRE. + //--------------------------------------------------------------- + if(strcmp(prop, NS_GRE_DIR) == 0) + { + nsILocalFile* lfile = nsnull; + nsresult rv = GRE_GetGREDirectory(&lfile); + *_retval = lfile; + return rv; + } + + return NS_ERROR_FAILURE; +} + +//***************************************************************************** +// Implementations from nsXPCOMGlue.h and helper functions. +//***************************************************************************** + +PRBool +GRE_GetCurrentProcessDirectory(char* buffer) +{ + *buffer = '\0'; + +#ifdef XP_WIN + if ( ::GetModuleFileName(0, buffer, MAXPATHLEN) ) { + // chop of the executable name by finding the rightmost backslash + char* lastSlash = PL_strrchr(buffer, '\\'); + if (lastSlash) { + *(lastSlash) = '\0'; + return PR_TRUE; + } + } + +#elif defined(XP_MACOSX) + // Works even if we're not bundled. + CFBundleRef appBundle = CFBundleGetMainBundle(); + if (appBundle != nsnull) + { + CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle); + if (bundleURL != nsnull) + { + CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, bundleURL); + if (parentURL) + { + CFStringRef path = CFURLCopyFileSystemPath(parentURL, kCFURLPOSIXPathStyle); + if (path) + { + CFStringGetCString(path, buffer, MAXPATHLEN, kCFStringEncodingUTF8); + CFRelease(path); + } + CFRelease(parentURL); + } + CFRelease(bundleURL); + } +#if 0 /* bird: Causes crashes in objc_msgSend() later if released. I dunno why really. + Something could be seriously screwed up somewhere else, but this'll have + to do for now. (appBundle isn't released in the other place it's used.) */ + CFRelease(appBundle); +#endif + } + if (*buffer) return PR_TRUE; + +#elif defined(XP_UNIX) + +#if 0 /* we need .so location. */ + // Actually we have a way on linux. + static volatile bool fPathSet = false; + static char szPath[MAXPATHLEN]; + if (!fPathSet) + { + char buf2[MAXPATHLEN + 3]; + buf2[0] = '\0'; + + /* + * Env.var. VBOX_XPCOM_HOME first. + */ + char *psz = PR_GetEnv("VBOX_XPCOM_HOME"); + if (psz) + { + if (strlen(psz) < MAXPATHLEN) + { + if (!realpath(psz, buf2)) + strcpy(buf2, psz); + strcat(buf2, "/x"); /* for the filename stripping */ + } + } + + /* + * The dynamic loader. + */ + if (!buf2[0]) + { + Dl_info DlInfo = {0}; + if ( !dladdr((const void *)GRE_GetCurrentProcessDirectory, &DlInfo) + && DlInfo.dli_fname) + { + if (!realpath(DlInfo.dli_fname, buf2)) + buf2[0] = '\0'; + } + } + + /* + * Executable location. + */ + if (!buf2[0]) + { + char buf[MAXPATHLEN]; + int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (cchLink > 0 || cchLink != sizeof(buf) - 1) + { + buf[cchLink] = '\0'; + if (!realpath(buf, buf2)) + buf2[0] = '\0'; + } + } + + /* + * Copy to static buffer on success. + */ + if (buf2[0]) + { + char *p = strrchr(buf2, '/'); + if (p) + { + p[p == buf2] = '\0'; + #ifdef DEBUG + printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2); + #endif + strcpy(szPath, buf2); + fPathSet = true; + } + } + } + if (fPathSet) + { + strcpy(buffer, szPath); + return PR_TRUE; + } +#endif + + // In the absence of a good way to get the executable directory let + // us try this for unix: + // - if VBOX_XPCOM_HOME is defined, that is it + // - else give the current directory + + // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with + // a --with-default-mozilla-five-home=foo autoconf flag. + // + // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME + // regardless of the environment. This makes it easier to write apps that + // embed mozilla without having to worry about setting up the environment + // + // We do this py putenv()ing the default value into the environment. Note that + // we only do this if it is not already set. +#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME + if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull) + { + putenv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME); + } +#endif + + char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME"); + + if (moz5 && *moz5) + { + if (!realpath(moz5, buffer)) + strcpy(buffer, moz5); + + return PR_TRUE; + } + else + { +#if defined(DEBUG) + static PRBool firstWarning = PR_TRUE; + + if(firstWarning) { + // Warn that VBOX_XPCOM_HOME not set, once. + printf("Warning: VBOX_XPCOM_HOME not set.\n"); + firstWarning = PR_FALSE; + } +#endif /* DEBUG */ + + // Fall back to current directory. + if (getcwd(buffer, MAXPATHLEN)) + { + return PR_TRUE; + } + } + +#elif defined(XP_OS2) + PPIB ppib; + PTIB ptib; + char* p; + DosGetInfoBlocks( &ptib, &ppib); + DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, buffer); + p = strrchr( buffer, '\\'); // XXX DBCS misery + if (p) { + *p = '\0'; + return PR_TRUE; + } + +#elif defined(XP_BEOS) + + char *moz5 = getenv("VBOX_XPCOM_HOME"); + if (moz5) + { + strcpy(buffer, moz5); + return PR_TRUE; + } + else + { + int32 cookie = 0; + image_info info; + char *p; + *buffer = 0; + if(get_next_image_info(0, &cookie, &info) == B_OK) + { + strcpy(buffer, info.name); + if((p = strrchr(buffer, '/')) != 0) + { + *p = 0; + + return PR_TRUE; + } + } + } + +#endif + + return PR_FALSE; +} + +/** + * the GRE location is stored in a static buffer so that we don't have + * to compute it multiple times. + */ + +static char sGRELocation[MAXPATHLEN] = ""; + +extern "C" char const * +GRE_GetGREPath() +{ + // we've already done this... + if (*sGRELocation) + return sGRELocation; + + char buffer[MAXPATHLEN]; + + // If the xpcom library exists in the current process directory, + // then we will not use any GRE. The assumption here is that the + // GRE is in the same directory as the executable. + if (GRE_GetCurrentProcessDirectory(buffer)) { + PRUint32 pathlen = strlen(buffer); + strcpy(buffer + pathlen, XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL); + + struct stat libStat; + int statResult = stat(buffer, &libStat); + + if (statResult != -1) { + //found our xpcom lib in the current process directory + buffer[pathlen] = '\0'; + strcpy(sGRELocation, buffer); + return sGRELocation; + } + } + + // if GRE_HOME is in the environment, use that GRE + const char* env = PR_GetEnv("GRE_HOME"); + if (env && *env) { +#if XP_UNIX + if (!realpath(env, sGRELocation)) + strcpy(sGRELocation, env); +#elif XP_WIN32 + if (!_fullpath(sGRELocation, env, MAXPATHLEN)) + strcpy(sGRELocation, env); +#endif + // xxxbsmedberg: it would help that other platforms had a "make absolute" function + return sGRELocation; + } + + // the Gecko bits that sit next to the application or in the LD_LIBRARY_PATH + env = PR_GetEnv("USE_LOCAL_GRE"); + if (env && *env) + return nsnull; + +#if XP_UNIX + // check in the HOME directory + env = PR_GetEnv("HOME"); + if (env && *env) { +# ifdef VBOX + snprintf(buffer, sizeof(buffer), "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env); +# else + sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env); +# endif + + if (GRE_GetPathFromConfigFile(buffer, sGRELocation)) { + return sGRELocation; + } + } +#endif + + env = PR_GetEnv("MOZ_GRE_CONF"); + if (env) { + if (GRE_GetPathFromConfigFile(env, sGRELocation)) { + return sGRELocation; + } + } + +#if XP_UNIX + // Look for a group of config files in /etc/gre.d/ + if (GRE_GetPathFromConfigDir(GRE_CONF_DIR, sGRELocation)) { + return sGRELocation; + } + + // Look for a global /etc/gre.conf file + if (GRE_GetPathFromConfigFile(GRE_CONF_PATH, sGRELocation)) { + return sGRELocation; + } +#endif + +#if XP_WIN32 + char szKey[256]; + HKEY hRegKey = NULL; + DWORD dwLength = MAXPATHLEN; + + // A couple of key points here: + // 1. Note the usage of the "Software\\Mozilla\\GRE" subkey - this allows + // us to have multiple versions of GREs on the same machine by having + // subkeys such as 1.0, 1.1, 2.0 etc. under it. + // 2. In this sample below we're looking for the location of GRE version 1.2 + // i.e. we're compatible with GRE 1.2 and we're trying to find it's install + // location. + // + // Please see http://www.mozilla.org/projects/embedding/GRE.html for + // more info. + // + strcpy(szKey, GRE_WIN_REG_LOC GRE_BUILD_ID); + + if (::RegOpenKeyEx(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) { + if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) { + *sGRELocation = '\0'; + } + ::RegCloseKey(hRegKey); + + if (*sGRELocation) + return sGRELocation; + } + + if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) { + if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) { + *sGRELocation = '\0'; + } + ::RegCloseKey(hRegKey); + + if (*sGRELocation) + return sGRELocation; + } +#endif + + return nsnull; +} + +PRBool +GRE_GetPathFromConfigDir(const char* dirname, char* buffer) +{ + // Open the directory provided and try to read any files in that + // directory that end with .conf. We look for an entry that might + // point to the GRE that we're interested in. + PRDir *dir = PR_OpenDir(dirname); + if (!dir) + return nsnull; + + PRBool found = PR_FALSE; + PRDirEntry *entry; + + while (!found && (entry = PR_ReadDir(dir, PR_SKIP_BOTH))) { + + // Only look for files that end in .conf + char *offset = PL_strrstr(entry->name, ".conf"); + if (!offset) + continue; + + if (offset != entry->name + strlen(entry->name) - 5) + continue; + + nsEmbedCString fullPath; + NS_CStringAppendData(fullPath, dirname); + NS_CStringAppendData(fullPath, XPCOM_FILE_PATH_SEPARATOR); + NS_CStringAppendData(fullPath, entry->name); + + found = GRE_GetPathFromConfigFile(fullPath.get(), buffer); + } + + PR_CloseDir(dir); + + return found; +} + +PRBool +GRE_GetPathFromConfigFile(const char* filename, char* pathBuffer) +{ + *pathBuffer = '\0'; + char buffer[1024]; + FILE *cfg; + PRBool foundHeader = PR_FALSE; + PRInt32 versionLen = sizeof(GRE_BUILD_ID)-1; + + if((cfg=fopen(filename,"r"))==nsnull) { + return nsnull; + } + + while (fgets(buffer, 1024, cfg) != nsnull) { + // skip over comment lines and blank lines + if (buffer[0] == '#' || buffer[0] == '\n') { + continue; + } + + // we found a section heading, check to see if it is the one we are intersted in. + if (buffer[0] == '[') { + if (!strncmp (buffer+1, GRE_BUILD_ID, versionLen)) { + foundHeader = PR_TRUE; + } + continue; + } + + if (foundHeader && !strncmp (buffer, "GRE_PATH=", 9)) { + strcpy(pathBuffer, buffer + 9); + // kill the line feed if any + PRInt32 len = strlen(pathBuffer); + len--; + + if (pathBuffer[len] == '\n') + pathBuffer[len] = '\0'; + break; + } + } + fclose(cfg); + return (*pathBuffer != '\0'); +} + +extern "C" nsresult +GRE_GetGREDirectory(nsILocalFile* *_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + nsresult rv = NS_ERROR_FAILURE; + + // Get the path of the GRE which is compatible with our embedding application + // from the registry + + const char *pGREDir = GRE_GetGREPath(); + if(pGREDir) { + nsCOMPtr<nsILocalFile> tempLocal; + nsEmbedCString leaf; + NS_CStringSetData(leaf, pGREDir); + rv = NS_NewNativeLocalFile(leaf, PR_TRUE, getter_AddRefs(tempLocal)); + + if (NS_SUCCEEDED(rv)) { + *_retval = tempLocal; + NS_ADDREF(*_retval); + } + } + return rv; +} + +static char sXPCOMPath[MAXPATHLEN]; + +extern "C" const char* +GRE_GetXPCOMPath() +{ + const char* grePath = GRE_GetGREPath(); + + if (!grePath) { + grePath = PR_GetEnv("VBOX_XPCOM_HOME"); + if (!grePath || !*grePath) { + return nsnull; + } + } + +#ifdef VBOX + snprintf(sXPCOMPath, sizeof(sXPCOMPath), "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath); +#else + sprintf(sXPCOMPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath); +#endif + + return sXPCOMPath; +} diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h new file mode 100644 index 00000000..0638a127 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h @@ -0,0 +1,68 @@ +/* ***** 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. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corp. + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sean Su <ssu@netscape.com> + * + * 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 nsGREDirServiceProvider_h_ +#define nsGREDirServiceProvider_h_ + +#include "nsIDirectoryService.h" + +#ifndef MAXPATHLEN +#ifdef _MAX_PATH +#define MAXPATHLEN _MAX_PATH +#elif defined(CCHMAXPATH) +#define MAXPATHLEN CCHMAXPATH +#else +#define MAXPATHLEN 1024 +#endif +#endif + +/** + * the directoryserviceprovider used by GRE_Startup when calling NS_InitXPCOM2 + */ +class nsGREDirServiceProvider : public nsIDirectoryServiceProvider +{ +public: + nsGREDirServiceProvider() { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIDIRECTORYSERVICEPROVIDER + +private: + ~nsGREDirServiceProvider() { } +}; + +#endif // nsGREDirServiceProvider.h diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp new file mode 100644 index 00000000..091538fa --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp @@ -0,0 +1,524 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 et cindent: */ +/* ***** 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 "nsXPCOMGlue.h" + +#include "nspr.h" +#include "nsMemory.h" +#include "nsGREDirServiceProvider.h" +#include "nsXPCOMPrivate.h" +#include <stdlib.h> +#ifdef VBOX +# include <limits.h> +#endif + +#if XP_WIN32 +#include <windows.h> +#endif + +void GRE_AddGREToEnvironment(); + +// functions provided by nsMemory.cpp and nsDebug.cpp +nsresult GlueStartupMemory(); +void GlueShutdownMemory(); +nsresult GlueStartupDebug(); +void GlueShutdownDebug(); + +static PRLibrary *xpcomLib; +static XPCOMFunctions xpcomFunctions; + +extern "C" +nsresult XPCOMGlueStartup(const char* xpcomFile) +{ +#ifdef XPCOM_GLUE_NO_DYNAMIC_LOADING + return NS_OK; +#else + nsresult rv = NS_OK; + GetFrozenFunctionsFunc function = nsnull; + + xpcomFunctions.version = XPCOM_GLUE_VERSION; + xpcomFunctions.size = sizeof(XPCOMFunctions); + + // + // if xpcomFile == ".", then we assume xpcom is already loaded, and we'll + // use NSPR to find NS_GetFrozenFunctions from the list of already loaded + // libraries. + // + // otherwise, we try to load xpcom and then look for NS_GetFrozenFunctions. + // if xpcomFile == NULL, then we try to load xpcom by name w/o a fully + // qualified path. + // + + if (xpcomFile && (xpcomFile[0] == '.' && xpcomFile[1] == '\0')) { + function = (GetFrozenFunctionsFunc) + PR_FindSymbolAndLibrary("NS_GetFrozenFunctions", &xpcomLib); + if (!function) { + // The symbol was not found, so failover to loading XPCOM_DLL, + // and look for the symbol there. See bug 240986 for details. + xpcomFile = nsnull; + } + else { + char *libPath = PR_GetLibraryFilePathname(XPCOM_DLL, (PRFuncPtr) function); + if (!libPath) + rv = NS_ERROR_FAILURE; + else { + rv = (*function)(&xpcomFunctions, libPath); + PR_Free(libPath); + } + } + } + + if (!function) { + PRLibSpec libSpec; + + libSpec.type = PR_LibSpec_Pathname; + if (!xpcomFile) + libSpec.value.pathname = XPCOM_DLL; + else + libSpec.value.pathname = xpcomFile; + + xpcomLib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL); +#ifdef RT_OS_DARWIN /* vbox */ + /* works around bundle problem. */ + if (!xpcomLib) { + const char *home = PR_GetEnv("VBOX_XPCOM_HOME"); + if (home) { + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/%s", home, libSpec.value.pathname); + libSpec.value.pathname = path; + xpcomLib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL); + } + } +#endif + if (!xpcomLib) + return NS_ERROR_FAILURE; + + function = (GetFrozenFunctionsFunc) PR_FindSymbol(xpcomLib, "NS_GetFrozenFunctions"); + + if (!function) + rv = NS_ERROR_FAILURE; + else + rv = (*function)(&xpcomFunctions, libSpec.value.pathname); + } + + if (NS_FAILED(rv)) + goto bail; + + rv = GlueStartupDebug(); + if (NS_FAILED(rv)) + goto bail; + + // startup the nsMemory + rv = GlueStartupMemory(); + if (NS_FAILED(rv)) { + GlueShutdownDebug(); + goto bail; + } + + GRE_AddGREToEnvironment(); + return NS_OK; + +bail: + PR_UnloadLibrary(xpcomLib); + xpcomLib = nsnull; + memset(&xpcomFunctions, 0, sizeof(xpcomFunctions)); + return NS_ERROR_FAILURE; +#endif +} + +extern "C" +nsresult XPCOMGlueShutdown() +{ +#ifdef XPCOM_GLUE_NO_DYNAMIC_LOADING + return NS_OK; +#else + + GlueShutdownMemory(); + + GlueShutdownDebug(); + + if (xpcomLib) { + PR_UnloadLibrary(xpcomLib); + xpcomLib = nsnull; + } + + memset(&xpcomFunctions, 0, sizeof(xpcomFunctions)); + return NS_OK; +#endif +} + +#ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING +extern "C" NS_COM nsresult +NS_InitXPCOM2(nsIServiceManager* *result, + nsIFile* binDirectory, + nsIDirectoryServiceProvider* appFileLocationProvider) +{ + if (!xpcomFunctions.init) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.init(result, binDirectory, appFileLocationProvider); +} + +extern "C" NS_COM nsresult +NS_ShutdownXPCOM(nsIServiceManager* servMgr) +{ + if (!xpcomFunctions.shutdown) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.shutdown(servMgr); +} + +extern "C" NS_COM nsresult +NS_GetServiceManager(nsIServiceManager* *result) +{ + if (!xpcomFunctions.getServiceManager) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.getServiceManager(result); +} + +extern "C" NS_COM nsresult +NS_GetComponentManager(nsIComponentManager* *result) +{ + if (!xpcomFunctions.getComponentManager) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.getComponentManager(result); +} + +extern "C" NS_COM nsresult +NS_GetComponentRegistrar(nsIComponentRegistrar* *result) +{ + if (!xpcomFunctions.getComponentRegistrar) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.getComponentRegistrar(result); +} + +extern "C" NS_COM nsresult +NS_GetMemoryManager(nsIMemory* *result) +{ + if (!xpcomFunctions.getMemoryManager) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.getMemoryManager(result); +} + +extern "C" NS_COM nsresult +NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result) +{ + if (!xpcomFunctions.newLocalFile) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.newLocalFile(path, followLinks, result); +} + +extern "C" NS_COM nsresult +NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result) +{ + if (!xpcomFunctions.newNativeLocalFile) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.newNativeLocalFile(path, followLinks, result); +} + +extern "C" NS_COM nsresult +NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority) +{ + if (!xpcomFunctions.registerExitRoutine) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.registerExitRoutine(exitRoutine, priority); +} + +extern "C" NS_COM nsresult +NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine) +{ + if (!xpcomFunctions.unregisterExitRoutine) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.unregisterExitRoutine(exitRoutine); +} + +extern "C" NS_COM nsresult +NS_GetDebug(nsIDebug* *result) +{ + if (!xpcomFunctions.getDebug) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.getDebug(result); +} + + +extern "C" NS_COM nsresult +NS_GetTraceRefcnt(nsITraceRefcnt* *result) +{ + if (!xpcomFunctions.getTraceRefcnt) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.getTraceRefcnt(result); +} + + +extern "C" NS_COM nsresult +NS_StringContainerInit(nsStringContainer &aStr) +{ + if (!xpcomFunctions.stringContainerInit) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.stringContainerInit(aStr); +} + +extern "C" NS_COM void +NS_StringContainerFinish(nsStringContainer &aStr) +{ + if (xpcomFunctions.stringContainerFinish) + xpcomFunctions.stringContainerFinish(aStr); +} + +extern "C" NS_COM PRUint32 +NS_StringGetData(const nsAString &aStr, const PRUnichar **aBuf, PRBool *aTerm) +{ + if (!xpcomFunctions.stringGetData) { + *aBuf = nsnull; + return 0; + } + return xpcomFunctions.stringGetData(aStr, aBuf, aTerm); +} + +extern "C" NS_COM PRUnichar * +NS_StringCloneData(const nsAString &aStr) +{ + if (!xpcomFunctions.stringCloneData) + return nsnull; + return xpcomFunctions.stringCloneData(aStr); +} + +extern "C" NS_COM nsresult +NS_StringSetData(nsAString &aStr, const PRUnichar *aBuf, PRUint32 aCount) +{ + if (!xpcomFunctions.stringSetData) + return NS_ERROR_NOT_INITIALIZED; + + return xpcomFunctions.stringSetData(aStr, aBuf, aCount); +} + +extern "C" NS_COM nsresult +NS_StringSetDataRange(nsAString &aStr, PRUint32 aCutStart, PRUint32 aCutLength, + const PRUnichar *aBuf, PRUint32 aCount) +{ + if (!xpcomFunctions.stringSetDataRange) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.stringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount); +} + +extern "C" NS_COM nsresult +NS_StringCopy(nsAString &aDest, const nsAString &aSrc) +{ + if (!xpcomFunctions.stringCopy) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.stringCopy(aDest, aSrc); +} + + +extern "C" NS_COM nsresult +NS_CStringContainerInit(nsCStringContainer &aStr) +{ + if (!xpcomFunctions.cstringContainerInit) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.cstringContainerInit(aStr); +} + +extern "C" NS_COM void +NS_CStringContainerFinish(nsCStringContainer &aStr) +{ + if (xpcomFunctions.cstringContainerFinish) + xpcomFunctions.cstringContainerFinish(aStr); +} + +extern "C" NS_COM PRUint32 +NS_CStringGetData(const nsACString &aStr, const char **aBuf, PRBool *aTerm) +{ + if (!xpcomFunctions.cstringGetData) { + *aBuf = nsnull; + return 0; + } + return xpcomFunctions.cstringGetData(aStr, aBuf, aTerm); +} + +extern "C" NS_COM char * +NS_CStringCloneData(const nsACString &aStr) +{ + if (!xpcomFunctions.cstringCloneData) + return nsnull; + return xpcomFunctions.cstringCloneData(aStr); +} + +extern "C" NS_COM nsresult +NS_CStringSetData(nsACString &aStr, const char *aBuf, PRUint32 aCount) +{ + if (!xpcomFunctions.cstringSetData) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.cstringSetData(aStr, aBuf, aCount); +} + +extern "C" NS_COM nsresult +NS_CStringSetDataRange(nsACString &aStr, PRUint32 aCutStart, PRUint32 aCutLength, + const char *aBuf, PRUint32 aCount) +{ + if (!xpcomFunctions.cstringSetDataRange) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.cstringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount); +} + +extern "C" NS_COM nsresult +NS_CStringCopy(nsACString &aDest, const nsACString &aSrc) +{ + if (!xpcomFunctions.cstringCopy) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.cstringCopy(aDest, aSrc); +} + +extern "C" NS_COM nsresult +NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest) +{ + if (!xpcomFunctions.cstringToUTF16) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.cstringToUTF16(aSrc, aSrcEncoding, aDest); +} + +extern "C" NS_COM nsresult +NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest) +{ + if (!xpcomFunctions.utf16ToCString) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.utf16ToCString(aSrc, aDestEncoding, aDest); +} + +#endif // #ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING + + +static char sEnvString[MAXPATHLEN*10]; +static char* spEnvString = 0; + +void +GRE_AddGREToEnvironment() +{ + const char* grePath = GRE_GetGREPath(); + char szPath[MAXPATHLEN]; + if (!grePath) + return; + + const char* path = PR_GetEnv(XPCOM_SEARCH_KEY); + if (!path) + path = ""; +#ifdef VBOX + else + { + /* sEnvString is part of the environment because of putenv(). + * path is only temporarily used and not argument of putenv() itself */ + snprintf(szPath, sizeof(szPath), "%s", path); + path = szPath; + } +#endif + + if (spEnvString) PR_smprintf_free(spEnvString); + + /** + * if the PATH string is longer than our static buffer, allocate a + * buffer for the environment string. This buffer will be leaked at shutdown! + */ + if (strlen(grePath) + strlen(path) + + sizeof(XPCOM_SEARCH_KEY) + sizeof(XPCOM_ENV_PATH_SEPARATOR) > MAXPATHLEN*10) { + if (PR_smprintf(XPCOM_SEARCH_KEY "=%s" XPCOM_ENV_PATH_SEPARATOR "%s", + grePath, + path)) { + PR_SetEnv(spEnvString); + } + } else { + if (sprintf(sEnvString, + XPCOM_SEARCH_KEY "=%s" XPCOM_ENV_PATH_SEPARATOR "%s", + grePath, + path) > 0) { + PR_SetEnv(sEnvString); + } + } + +#if XP_WIN32 + // On windows, the current directory is searched before the + // PATH environment variable. This is a very bad thing + // since libraries in the cwd will be picked up before + // any that are in either the application or GRE directory. + + if (grePath) { + SetCurrentDirectory(grePath); + } +#endif +} + + +// Default GRE startup/shutdown code + +extern "C" +nsresult GRE_Startup() +{ + const char* xpcomLocation = GRE_GetXPCOMPath(); + + // Startup the XPCOM Glue that links us up with XPCOM. + nsresult rv = XPCOMGlueStartup(xpcomLocation); + + if (NS_FAILED(rv)) { + NS_WARNING("gre: XPCOMGlueStartup failed"); + return rv; + } + + nsGREDirServiceProvider *provider = new nsGREDirServiceProvider(); + if ( !provider ) { + NS_WARNING("GRE_Startup failed"); + XPCOMGlueShutdown(); + return NS_ERROR_OUT_OF_MEMORY; + } + + nsCOMPtr<nsIServiceManager> servMan; + NS_ADDREF( provider ); + rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, provider); + NS_RELEASE(provider); + + if ( NS_FAILED(rv) || !servMan) { + NS_WARNING("gre: NS_InitXPCOM failed"); + XPCOMGlueShutdown(); + return rv; + } + + return NS_OK; +} + +extern "C" +nsresult GRE_Shutdown() +{ + NS_ShutdownXPCOM(nsnull); + XPCOMGlueShutdown(); + return NS_OK; +} diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h new file mode 100644 index 00000000..6044e084 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h @@ -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 "nscore.h" + +class nsILocalFile; + +/** + * Initialize the XPCOM glue by dynamically linking against the XPCOM + * shared library indicated by xpcomFile. + */ + +extern "C" +nsresult XPCOMGlueStartup(const char* xpcomFile); + + +/** + * Finish the XPCOM glue after it is no longer needed. + */ + +extern "C" +nsresult XPCOMGlueShutdown(); + + +/** + * Locate the path of a compatible GRE. + * + * @return string buffer pointing to the GRE path (without a trailing + * directory separator). Callers do no need to free this buffer. + */ + +extern "C" +char const * GRE_GetGREPath(); + + +/** + * Locate the path of a compatible GRE. This is returned as an + * nsILocalFile instead of a char*. + * + * @param _retval Ordinary XPCOM getter, returns an addrefed interface. + */ + +extern "C" +nsresult GRE_GetGREDirectory(nsILocalFile* *_retval); + + +/** + * Locate the path of the XPCOM binary of a compatible GRE. + * The result of this function is normally passed directly to + * XPCOMGlueStartup. + * + * @return string buffer pointing to the XPCOM DLL path. Callers do + * not need to free this buffer. + */ + +extern "C" +char const * GRE_GetXPCOMPath(); + + +/** + * Embedding applications which don't need a custom + * directoryserviceprovider may use GRE_Startup to start the XPCOM + * glue and initialize the GRE in one step. + */ + +extern "C" +nsresult GRE_Startup(); + + +/** + * Shut down XPCOM and the XPCOM glue in one step. + */ + +extern "C" +nsresult GRE_Shutdown(); |