xpcom/glue/nsCOMPtr.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef nsCOMPtr_h___
     7 #define nsCOMPtr_h___
     9 /*
    10   Having problems?
    12   See the User Manual at:
    13     http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
    16   nsCOMPtr
    17     better than a raw pointer
    18   for owning objects
    19                        -- scc
    20 */
    22 #include "mozilla/Attributes.h"
    23 #include "mozilla/TypeTraits.h"
    24 #include "mozilla/Assertions.h"
    25 #include "mozilla/NullPtr.h"
    26 #include "mozilla/Move.h"
    28 #include "nsDebug.h" // for |NS_ABORT_IF_FALSE|, |NS_ASSERTION|
    29 #include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
    30 #include "nscore.h" // for |NS_COM_GLUE|
    32 #include "nsCycleCollectionNoteChild.h"
    35 /*
    36   WARNING:
    37     This file defines several macros for internal use only.  These macros begin with the
    38     prefix |NSCAP_|.  Do not use these macros in your own code.  They are for internal use
    39     only for cross-platform compatibility, and are subject to change without notice.
    40 */
    43 #ifdef _MSC_VER
    44   #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
    45     // under VC++, we win by inlining StartAssignment
    47     // Also under VC++, at the highest warning level, we are overwhelmed  with warnings
    48     //  about (unused) inline functions being removed.  This is to be expected with
    49     //  templates, so we disable the warning.
    50   #pragma warning( disable: 4514 )
    51 #endif
    53 #define NSCAP_FEATURE_USE_BASE
    55 #ifdef DEBUG
    56   #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
    57   #undef NSCAP_FEATURE_USE_BASE
    58 //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
    59 #endif
    61 #ifdef __GNUC__
    62   // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
    63   // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
    64   // don't reorder instructions based on aliasing assumptions for
    65   // this variable.  Fortunately, gcc versions < 3.3 do not do any
    66   // optimizations that break nsCOMPtr.
    68   #define NS_MAY_ALIAS_PTR(t)    t*  __attribute__((__may_alias__))
    69 #else
    70   #define NS_MAY_ALIAS_PTR(t)    t*
    71 #endif
    73 #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
    74   #define NSCAP_FEATURE_USE_BASE
    75 #endif
    77   /*
    78     The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
    79       allow external clients the ability to add logging or other interesting debug facilities.
    80       In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
    81       provide (e.g., in "nsISupportsImpl.h") suitable definitions
    83         #define NSCAP_ADDREF(this, ptr)         NS_ADDREF(ptr)
    84         #define NSCAP_RELEASE(this, ptr)        NS_RELEASE(ptr)
    85   */
    87 #ifndef NSCAP_ADDREF
    88   #define NSCAP_ADDREF(this, ptr)     (ptr)->AddRef()
    89 #endif
    91 #ifndef NSCAP_RELEASE
    92   #define NSCAP_RELEASE(this, ptr)    (ptr)->Release()
    93 #endif
    95   // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
    96 #ifdef NSCAP_LOG_ASSIGNMENT
    97     // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
    98     //  to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
    99     //  the |nsCOMPtr|.
   100   #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
   101 #else
   102     // ...otherwise, just strip it out of the code
   103   #define NSCAP_LOG_ASSIGNMENT(this, ptr)
   104 #endif
   106 #ifndef NSCAP_LOG_RELEASE
   107   #define NSCAP_LOG_RELEASE(this, ptr)
   108 #endif
   110 namespace mozilla {
   112 struct unused_t;
   114 } // namespace mozilla
   116 template <class T>
   117 struct already_AddRefed
   118     /*
   119       ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
   120       |AddRef|ing it.  You might want to use this as a return type from a function
   121       that produces an already |AddRef|ed pointer as a result.
   123       See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
   125       This type should be a nested class inside |nsCOMPtr<T>|.
   127       Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
   128       avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
   129       case, and perhaps worth the savings in time and space that its specific
   130       implementation affords over the more general solution offered by
   131       |nsCOMPtr_helper|.
   132     */
   133   {
   134     /*
   135      * Prohibit all one-argument overloads but already_AddRefed(T*) and
   136      * already_AddRefed(decltype(nullptr)), and funnel the nullptr case through
   137      * the T* constructor.
   138      */
   139     template<typename N>
   140     already_AddRefed(N,
   141                      typename mozilla::EnableIf<mozilla::IsNullPointer<N>::value,
   142                                                 int>::Type dummy = 0)
   143       : mRawPtr(nullptr)
   144     {
   145       // nothing else to do here
   146     }
   148     already_AddRefed( T* aRawPtr )
   149       : mRawPtr(aRawPtr)
   150     {
   151       // nothing else to do here
   152     }
   154     // Disallowed.  Use move semantics instead.
   155     already_AddRefed(const already_AddRefed<T>& aOther) MOZ_DELETE;
   157     already_AddRefed(already_AddRefed<T>&& aOther)
   158       : mRawPtr(aOther.take())
   159     {
   160       // nothing else to do here
   161     }
   163     ~already_AddRefed()
   164     {
   165       MOZ_ASSERT(!mRawPtr);
   166     }
   168     // Specialize the unused operator<< for already_AddRefed, to allow
   169     // nsCOMPtr<nsIFoo> foo;
   170     // unused << foo.forget();
   171     friend void operator<<(const mozilla::unused_t& unused,
   172                            const already_AddRefed<T>& rhs)
   173     {
   174       auto mutableAlreadyAddRefed = const_cast<already_AddRefed<T>*>(&rhs);
   175       unused << mutableAlreadyAddRefed->take();
   176     }
   178     MOZ_WARN_UNUSED_RESULT T* take()
   179     {
   180       T* rawPtr = mRawPtr;
   181       mRawPtr = nullptr;
   182       return rawPtr;
   183     }
   185     /**
   186      * This helper is useful in cases like
   187      *
   188      *  already_AddRefed<BaseClass>
   189      *  Foo()
   190      *  {
   191      *    nsRefPtr<SubClass> x = ...;
   192      *    return x.forget();
   193      *  }
   194      *
   195      * The autoconversion allows one to omit the idiom
   196      *
   197      *    nsRefPtr<BaseClass> y = x.forget();
   198      *    return y.forget();
   199      */
   200     template<class U>
   201     operator already_AddRefed<U>()
   202     {
   203       U* tmp = mRawPtr;
   204       mRawPtr = nullptr;
   205       return already_AddRefed<U>(tmp);
   206     }
   208     /**
   209      * This helper provides a static_cast replacement for already_AddRefed, so
   210      * if you have
   211      *
   212      *   already_AddRefed<Parent> F();
   213      *
   214      * you can write
   215      *
   216      *   already_AddRefed<Child>
   217      *   G()
   218      *   {
   219      *     return F().downcast<Child>();
   220      *   }
   221      *
   222      * instead of
   223      *
   224      *     return dont_AddRef(static_cast<Child*>(F().get()));
   225      */
   226     template<class U>
   227     already_AddRefed<U> downcast()
   228     {
   229       U* tmp = static_cast<U*>(mRawPtr);
   230       mRawPtr = nullptr;
   231       return already_AddRefed<U>(tmp);
   232     }
   234   private:
   235     T* mRawPtr;
   236   };
   238 template <class T>
   239 inline
   240 already_AddRefed<T>
   241 dont_AddRef( T* aRawPtr )
   242   {
   243     return already_AddRefed<T>(aRawPtr);
   244   }
   246 template <class T>
   247 inline
   248 already_AddRefed<T>&&
   249 dont_AddRef( already_AddRefed<T>&& aAlreadyAddRefedPtr )
   250   {
   251     return mozilla::Move(aAlreadyAddRefedPtr);
   252   }
   256 class nsCOMPtr_helper
   257     /*
   258       An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
   259       that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
   260       Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
   262       Here are the rules for a helper:
   263         - it implements |operator()| to produce an interface pointer
   264         - (except for its name) |operator()| is a valid [XP]COM `getter'
   265         - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
   266         - it matches the type requested with the supplied |nsIID| argument
   267         - its constructor provides an optional |nsresult*| that |operator()| can fill
   268           in with an error when it is executed
   270       See |class nsGetInterface| for an example.
   271     */
   272   {
   273     public:
   274       virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
   275   };
   277 /*
   278   |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
   279   avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
   280   is called often enough that the codesize savings are big enough to
   281   warrant the specialcasing.
   282 */
   284 class
   285   NS_COM_GLUE
   286   MOZ_STACK_CLASS
   287 nsQueryInterface MOZ_FINAL
   288   {
   289     public:
   290       explicit
   291       nsQueryInterface( nsISupports* aRawPtr )
   292           : mRawPtr(aRawPtr)
   293         {
   294           // nothing else to do here
   295         }
   297       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
   299     private:
   300       nsISupports*  mRawPtr;
   301   };
   303 class NS_COM_GLUE nsQueryInterfaceWithError
   304   {
   305     public:
   306       nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
   307           : mRawPtr(aRawPtr),
   308             mErrorPtr(error)
   309         {
   310           // nothing else to do here
   311         }
   313       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
   315     private:
   316       nsISupports*  mRawPtr;
   317       nsresult*     mErrorPtr;
   318   };
   320 inline
   321 nsQueryInterface
   322 do_QueryInterface( nsISupports* aRawPtr )
   323   {
   324     return nsQueryInterface(aRawPtr);
   325   }
   327 inline
   328 nsQueryInterfaceWithError
   329 do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
   330   {
   331     return nsQueryInterfaceWithError(aRawPtr, error);
   332   }
   334 template <class T>
   335 inline
   336 void
   337 do_QueryInterface( already_AddRefed<T>& )
   338   {
   339     // This signature exists solely to _stop_ you from doing the bad thing.
   340     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
   341     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
   342   }
   344 template <class T>
   345 inline
   346 void
   347 do_QueryInterface( already_AddRefed<T>&, nsresult* )
   348   {
   349     // This signature exists solely to _stop_ you from doing the bad thing.
   350     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
   351     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
   352   }
   355 ////////////////////////////////////////////////////////////////////////////
   356 // Using servicemanager with COMPtrs
   357 class NS_COM_GLUE nsGetServiceByCID
   358 {
   359  public:
   360     explicit nsGetServiceByCID(const nsCID& aCID)
   361         : mCID(aCID)
   362         {
   363             // nothing else to do
   364         }
   366     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
   368  private:
   369     const nsCID&                mCID;
   370 };
   372 class NS_COM_GLUE nsGetServiceByCIDWithError
   373 {
   374  public:
   375     nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
   376         : mCID(aCID),
   377           mErrorPtr(aErrorPtr)
   378         {
   379             // nothing else to do
   380         }
   382     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
   384  private:
   385     const nsCID&                mCID;
   386     nsresult*                   mErrorPtr;
   387 };
   389 class NS_COM_GLUE nsGetServiceByContractID
   390 {
   391  public:
   392     explicit nsGetServiceByContractID(const char* aContractID)
   393         : mContractID(aContractID)
   394         {
   395             // nothing else to do
   396         }
   398     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
   400  private:
   401     const char*                 mContractID;
   402 };
   404 class NS_COM_GLUE nsGetServiceByContractIDWithError
   405 {
   406  public:
   407     nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
   408         : mContractID(aContractID),
   409           mErrorPtr(aErrorPtr)
   410         {
   411             // nothing else to do
   412         }
   414     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
   416  private:
   417     const char*                 mContractID;
   418     nsresult*                   mErrorPtr;
   419 };
   421 class
   422 nsCOMPtr_base
   423     /*
   424       ...factors implementation for all template versions of |nsCOMPtr|.
   426       This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
   427       because unlike the
   429       Here's the way people normally do things like this
   431         template <class T> class Foo { ... };
   432         template <> class Foo<void*> { ... };
   433         template <class T> class Foo<T*> : private Foo<void*> { ... };
   434     */
   435   {
   436     public:
   438       nsCOMPtr_base( nsISupports* rawPtr = 0 )
   439           : mRawPtr(rawPtr)
   440         {
   441           // nothing else to do here
   442         }
   444       NS_COM_GLUE NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base()
   445         {
   446           NSCAP_LOG_RELEASE(this, mRawPtr);
   447             if ( mRawPtr )
   448               NSCAP_RELEASE(this, mRawPtr);
   449         }
   451       NS_COM_GLUE void NS_FASTCALL   assign_with_AddRef( nsISupports* );
   452       NS_COM_GLUE void NS_FASTCALL   assign_from_qi( const nsQueryInterface, const nsIID& );
   453       NS_COM_GLUE void NS_FASTCALL   assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
   454       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
   455       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
   456       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
   457       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
   458       NS_COM_GLUE void NS_FASTCALL   assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
   459       NS_COM_GLUE void** NS_FASTCALL begin_assignment();
   461     protected:
   462       NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
   464       void
   465       assign_assuming_AddRef( nsISupports* newPtr )
   466         {
   467             /*
   468               |AddRef()|ing the new value (before entering this function) before
   469               |Release()|ing the old lets us safely ignore the self-assignment case.
   470               We must, however, be careful only to |Release()| _after_ doing the
   471               assignment, in case the |Release()| leads to our _own_ destruction,
   472               which would, in turn, cause an incorrect second |Release()| of our old
   473               pointer.  Thank <waterson@netscape.com> for discovering this.
   474             */
   475           nsISupports* oldPtr = mRawPtr;
   476           mRawPtr = newPtr;
   477           NSCAP_LOG_ASSIGNMENT(this, newPtr);
   478           NSCAP_LOG_RELEASE(this, oldPtr);
   479           if ( oldPtr )
   480             NSCAP_RELEASE(this, oldPtr);
   481         }
   482   };
   484 // template <class T> class nsGetterAddRefs;
   486 template <class T>
   487 class nsCOMPtr MOZ_FINAL
   488 #ifdef NSCAP_FEATURE_USE_BASE
   489     : private nsCOMPtr_base
   490 #endif
   491   {
   493 #ifdef NSCAP_FEATURE_USE_BASE
   494   #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
   495 #else
   496   #define NSCAP_CTOR_BASE(x) mRawPtr(x)
   498     private:
   499       void    assign_with_AddRef( nsISupports* );
   500       void    assign_from_qi( const nsQueryInterface, const nsIID& );
   501       void    assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
   502       void    assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
   503       void    assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
   504       void    assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
   505       void    assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
   506       void    assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
   507       void**  begin_assignment();
   509       void
   510       assign_assuming_AddRef( T* newPtr )
   511         {
   512           T* oldPtr = mRawPtr;
   513           mRawPtr = newPtr;
   514           NSCAP_LOG_ASSIGNMENT(this, newPtr);
   515           NSCAP_LOG_RELEASE(this, oldPtr);
   516           if ( oldPtr )
   517             NSCAP_RELEASE(this, oldPtr);
   518         }
   520     private:
   521       T* mRawPtr;
   522 #endif
   524     public:
   525       typedef T element_type;
   527 #ifndef NSCAP_FEATURE_USE_BASE
   528      ~nsCOMPtr()
   529         {
   530           NSCAP_LOG_RELEASE(this, mRawPtr);
   531           if ( mRawPtr )
   532             NSCAP_RELEASE(this, mRawPtr);
   533         }
   534 #endif
   536 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
   537       void
   538       Assert_NoQueryNeeded()
   539         {
   540           if ( mRawPtr )
   541             {
   542               nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
   543               NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
   544             }
   545         }
   547   #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
   548 #else
   549   #define NSCAP_ASSERT_NO_QUERY_NEEDED()
   550 #endif
   553         // Constructors
   555       nsCOMPtr()
   556             : NSCAP_CTOR_BASE(0)
   557           // default constructor
   558         {
   559           NSCAP_LOG_ASSIGNMENT(this, 0);
   560         }
   562       nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
   563             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
   564           // copy-constructor
   565         {
   566           if ( mRawPtr )
   567             NSCAP_ADDREF(this, mRawPtr);
   568           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
   569         }
   571       nsCOMPtr( T* aRawPtr )
   572             : NSCAP_CTOR_BASE(aRawPtr)
   573           // construct from a raw pointer (of the right type)
   574         {
   575           if ( mRawPtr )
   576             NSCAP_ADDREF(this, mRawPtr);
   577           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
   578           NSCAP_ASSERT_NO_QUERY_NEEDED();
   579         }
   581       nsCOMPtr( already_AddRefed<T>& aSmartPtr )
   582             : NSCAP_CTOR_BASE(aSmartPtr.take())
   583           // construct from |already_AddRefed|
   584         {
   585           NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
   586           NSCAP_ASSERT_NO_QUERY_NEEDED();
   587         }
   589       nsCOMPtr( already_AddRefed<T>&& aSmartPtr )
   590             : NSCAP_CTOR_BASE(aSmartPtr.take())
   591           // construct from |otherComPtr.forget()|
   592         {
   593           NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
   594           NSCAP_ASSERT_NO_QUERY_NEEDED();
   595         }
   597       template<typename U>
   598       nsCOMPtr( already_AddRefed<U>& aSmartPtr )
   599             : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
   600           // construct from |already_AddRefed|
   601         {
   602           // But make sure that U actually inherits from T
   603           static_assert(mozilla::IsBaseOf<T, U>::value,
   604                         "U is not a subclass of T");
   605           NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
   606           NSCAP_ASSERT_NO_QUERY_NEEDED();
   607         }
   609       template<typename U>
   610       nsCOMPtr( already_AddRefed<U>&& aSmartPtr )
   611             : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
   612           // construct from |otherComPtr.forget()|
   613         {
   614           // But make sure that U actually inherits from T
   615           static_assert(mozilla::IsBaseOf<T, U>::value,
   616                         "U is not a subclass of T");
   617           NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
   618           NSCAP_ASSERT_NO_QUERY_NEEDED();
   619         }
   621       nsCOMPtr( const nsQueryInterface qi )
   622             : NSCAP_CTOR_BASE(0)
   623           // construct from |do_QueryInterface(expr)|
   624         {
   625           NSCAP_LOG_ASSIGNMENT(this, 0);
   626           assign_from_qi(qi, NS_GET_TEMPLATE_IID(T));
   627         }
   629       nsCOMPtr( const nsQueryInterfaceWithError& qi )
   630             : NSCAP_CTOR_BASE(0)
   631           // construct from |do_QueryInterface(expr, &rv)|
   632         {
   633           NSCAP_LOG_ASSIGNMENT(this, 0);
   634           assign_from_qi_with_error(qi, NS_GET_TEMPLATE_IID(T));
   635         }
   637       nsCOMPtr( const nsGetServiceByCID gs )
   638             : NSCAP_CTOR_BASE(0)
   639           // construct from |do_GetService(cid_expr)|
   640         {
   641           NSCAP_LOG_ASSIGNMENT(this, 0);
   642           assign_from_gs_cid(gs, NS_GET_TEMPLATE_IID(T));
   643         }
   645       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
   646             : NSCAP_CTOR_BASE(0)
   647           // construct from |do_GetService(cid_expr, &rv)|
   648         {
   649           NSCAP_LOG_ASSIGNMENT(this, 0);
   650           assign_from_gs_cid_with_error(gs, NS_GET_TEMPLATE_IID(T));
   651         }
   653       nsCOMPtr( const nsGetServiceByContractID gs )
   654             : NSCAP_CTOR_BASE(0)
   655           // construct from |do_GetService(contractid_expr)|
   656         {
   657           NSCAP_LOG_ASSIGNMENT(this, 0);
   658           assign_from_gs_contractid(gs, NS_GET_TEMPLATE_IID(T));
   659         }
   661       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
   662             : NSCAP_CTOR_BASE(0)
   663           // construct from |do_GetService(contractid_expr, &rv)|
   664         {
   665           NSCAP_LOG_ASSIGNMENT(this, 0);
   666           assign_from_gs_contractid_with_error(gs, NS_GET_TEMPLATE_IID(T));
   667         }
   669       nsCOMPtr( const nsCOMPtr_helper& helper )
   670             : NSCAP_CTOR_BASE(0)
   671           // ...and finally, anything else we might need to construct from
   672           //  can exploit the |nsCOMPtr_helper| facility
   673         {
   674           NSCAP_LOG_ASSIGNMENT(this, 0);
   675           assign_from_helper(helper, NS_GET_TEMPLATE_IID(T));
   676           NSCAP_ASSERT_NO_QUERY_NEEDED();
   677         }
   680         // Assignment operators
   682       nsCOMPtr<T>&
   683       operator=( const nsCOMPtr<T>& rhs )
   684           // copy assignment operator
   685         {
   686           assign_with_AddRef(rhs.mRawPtr);
   687           return *this;
   688         }
   690       nsCOMPtr<T>&
   691       operator=( T* rhs )
   692           // assign from a raw pointer (of the right type)
   693         {
   694           assign_with_AddRef(rhs);
   695           NSCAP_ASSERT_NO_QUERY_NEEDED();
   696           return *this;
   697         }
   699       template<typename U>
   700       nsCOMPtr<T>&
   701       operator=( already_AddRefed<U>& rhs )
   702           // assign from |already_AddRefed|
   703         {
   704           // Make sure that U actually inherits from T
   705           static_assert(mozilla::IsBaseOf<T, U>::value,
   706                         "U is not a subclass of T");
   707           assign_assuming_AddRef(static_cast<T*>(rhs.take()));
   708           NSCAP_ASSERT_NO_QUERY_NEEDED();
   709           return *this;
   710         }
   712       template<typename U>
   713       nsCOMPtr<T>&
   714       operator=( already_AddRefed<U>&& rhs )
   715           // assign from |otherComPtr.forget()|
   716         {
   717           // Make sure that U actually inherits from T
   718           static_assert(mozilla::IsBaseOf<T, U>::value,
   719                         "U is not a subclass of T");
   720           assign_assuming_AddRef(static_cast<T*>(rhs.take()));
   721           NSCAP_ASSERT_NO_QUERY_NEEDED();
   722           return *this;
   723         }
   725       nsCOMPtr<T>&
   726       operator=( const nsQueryInterface rhs )
   727           // assign from |do_QueryInterface(expr)|
   728         {
   729           assign_from_qi(rhs, NS_GET_TEMPLATE_IID(T));
   730           return *this;
   731         }
   733       nsCOMPtr<T>&
   734       operator=( const nsQueryInterfaceWithError& rhs )
   735           // assign from |do_QueryInterface(expr, &rv)|
   736         {
   737           assign_from_qi_with_error(rhs, NS_GET_TEMPLATE_IID(T));
   738           return *this;
   739         }
   741       nsCOMPtr<T>&
   742       operator=( const nsGetServiceByCID rhs )
   743           // assign from |do_GetService(cid_expr)|
   744         {
   745           assign_from_gs_cid(rhs, NS_GET_TEMPLATE_IID(T));
   746           return *this;
   747         }
   749       nsCOMPtr<T>&
   750       operator=( const nsGetServiceByCIDWithError& rhs )
   751           // assign from |do_GetService(cid_expr, &rv)|
   752         {
   753           assign_from_gs_cid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
   754           return *this;
   755         }
   757       nsCOMPtr<T>&
   758       operator=( const nsGetServiceByContractID rhs )
   759           // assign from |do_GetService(contractid_expr)|
   760         {
   761           assign_from_gs_contractid(rhs, NS_GET_TEMPLATE_IID(T));
   762           return *this;
   763         }
   765       nsCOMPtr<T>&
   766       operator=( const nsGetServiceByContractIDWithError& rhs )
   767           // assign from |do_GetService(contractid_expr, &rv)|
   768         {
   769           assign_from_gs_contractid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
   770           return *this;
   771         }
   773       nsCOMPtr<T>&
   774       operator=( const nsCOMPtr_helper& rhs )
   775           // ...and finally, anything else we might need to assign from
   776           //  can exploit the |nsCOMPtr_helper| facility.
   777         {
   778           assign_from_helper(rhs, NS_GET_TEMPLATE_IID(T));
   779           NSCAP_ASSERT_NO_QUERY_NEEDED();
   780           return *this;
   781         }
   783       void
   784       swap( nsCOMPtr<T>& rhs )
   785           // ...exchange ownership with |rhs|; can save a pair of refcount operations
   786         {
   787 #ifdef NSCAP_FEATURE_USE_BASE
   788           nsISupports* temp = rhs.mRawPtr;
   789 #else
   790           T* temp = rhs.mRawPtr;
   791 #endif
   792           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
   793           NSCAP_LOG_ASSIGNMENT(this, temp);
   794           NSCAP_LOG_RELEASE(this, mRawPtr);
   795           NSCAP_LOG_RELEASE(&rhs, temp);
   796           rhs.mRawPtr = mRawPtr;
   797           mRawPtr = temp;
   798           // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
   799         }
   801       void
   802       swap( T*& rhs )
   803           // ...exchange ownership with |rhs|; can save a pair of refcount operations
   804         {
   805 #ifdef NSCAP_FEATURE_USE_BASE
   806           nsISupports* temp = rhs;
   807 #else
   808           T* temp = rhs;
   809 #endif
   810           NSCAP_LOG_ASSIGNMENT(this, temp);
   811           NSCAP_LOG_RELEASE(this, mRawPtr);
   812           rhs = reinterpret_cast<T*>(mRawPtr);
   813           mRawPtr = temp;
   814           NSCAP_ASSERT_NO_QUERY_NEEDED();
   815         }
   818         // Other pointer operators
   820       already_AddRefed<T>
   821       forget()
   822           // return the value of mRawPtr and null out mRawPtr. Useful for
   823           // already_AddRefed return values.
   824         {
   825           T* temp = 0;
   826           swap(temp);
   827           return already_AddRefed<T>(temp);
   828         }
   830       template <typename I>
   831       void
   832       forget( I** rhs )
   833           // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
   834           // Useful to avoid unnecessary AddRef/Release pairs with "out"
   835           // parameters where rhs bay be a T** or an I** where I is a base class
   836           // of T.
   837         {
   838           NS_ASSERTION(rhs, "Null pointer passed to forget!");
   839           NSCAP_LOG_RELEASE(this, mRawPtr);
   840           *rhs = get();
   841           mRawPtr = 0;
   842         }
   844       T*
   845       get() const
   846           /*
   847             Prefer the implicit conversion provided automatically by |operator T*() const|.
   848             Use |get()| to resolve ambiguity or to get a castable pointer.
   849           */
   850         {
   851           return reinterpret_cast<T*>(mRawPtr);
   852         }
   854       operator T*() const
   855           /*
   856             ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
   857             is used in a context where a raw pointer is expected.  It is this operator
   858             that makes an |nsCOMPtr| substitutable for a raw pointer.
   860             Prefer the implicit use of this operator to calling |get()|, except where
   861             necessary to resolve ambiguity.
   862           */
   863         {
   864           return get();
   865         }
   867       T*
   868       operator->() const
   869         {
   870           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
   871           return get();
   872         }
   874       nsCOMPtr<T>*
   875       get_address()
   876           // This is not intended to be used by clients.  See |address_of|
   877           // below.
   878         {
   879           return this;
   880         }
   882       const nsCOMPtr<T>*
   883       get_address() const
   884           // This is not intended to be used by clients.  See |address_of|
   885           // below.
   886         {
   887           return this;
   888         }
   890     public:
   891       T&
   892       operator*() const
   893         {
   894           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
   895           return *get();
   896         }
   898       T**
   899       StartAssignment()
   900         {
   901 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
   902           return reinterpret_cast<T**>(begin_assignment());
   903 #else
   904           assign_assuming_AddRef(0);
   905           return reinterpret_cast<T**>(&mRawPtr);
   906 #endif
   907         }
   908   };
   912   /*
   913     Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
   914     same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
   915     to any valid [XP]COM interface.  Otherwise, an |nsCOMPtr<nsISupports>| would only be able
   916     to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
   917     querying ensues.  Clients need to be able to pass around arbitrary interface pointers,
   918     without hassles, through intermediary code that doesn't know the exact type.
   919   */
   921 template <>
   922 class nsCOMPtr<nsISupports>
   923     : private nsCOMPtr_base
   924   {
   925     public:
   926       typedef nsISupports element_type;
   928         // Constructors
   930       nsCOMPtr()
   931             : nsCOMPtr_base(0)
   932           // default constructor
   933         {
   934           NSCAP_LOG_ASSIGNMENT(this, 0);
   935         }
   937       nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
   938             : nsCOMPtr_base(aSmartPtr.mRawPtr)
   939           // copy constructor
   940         {
   941           if ( mRawPtr )
   942             NSCAP_ADDREF(this, mRawPtr);
   943           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
   944         }
   946       nsCOMPtr( nsISupports* aRawPtr )
   947             : nsCOMPtr_base(aRawPtr)
   948           // construct from a raw pointer (of the right type)
   949         {
   950           if ( mRawPtr )
   951             NSCAP_ADDREF(this, mRawPtr);
   952           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
   953         }
   955       nsCOMPtr( already_AddRefed<nsISupports>& aSmartPtr )
   956             : nsCOMPtr_base(aSmartPtr.take())
   957           // construct from |already_AddRefed|
   958         {
   959           NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
   960         }
   962       nsCOMPtr( already_AddRefed<nsISupports>&& aSmartPtr )
   963             : nsCOMPtr_base(aSmartPtr.take())
   964           // construct from |otherComPtr.forget()|
   965         {
   966           NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
   967         }
   969       nsCOMPtr( const nsQueryInterface qi )
   970             : nsCOMPtr_base(0)
   971           // assign from |do_QueryInterface(expr)|
   972         {
   973           NSCAP_LOG_ASSIGNMENT(this, 0);
   974           assign_from_qi(qi, NS_GET_IID(nsISupports));
   975         }
   977       nsCOMPtr( const nsQueryInterfaceWithError& qi )
   978             : nsCOMPtr_base(0)
   979           // assign from |do_QueryInterface(expr, &rv)|
   980         {
   981           NSCAP_LOG_ASSIGNMENT(this, 0);
   982           assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
   983         }
   985       nsCOMPtr( const nsGetServiceByCID gs )
   986             : nsCOMPtr_base(0)
   987           // assign from |do_GetService(cid_expr)|
   988         {
   989           NSCAP_LOG_ASSIGNMENT(this, 0);
   990           assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
   991         }
   993       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
   994             : nsCOMPtr_base(0)
   995           // assign from |do_GetService(cid_expr, &rv)|
   996         {
   997           NSCAP_LOG_ASSIGNMENT(this, 0);
   998           assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
   999         }
  1001       nsCOMPtr( const nsGetServiceByContractID gs )
  1002             : nsCOMPtr_base(0)
  1003           // assign from |do_GetService(contractid_expr)|
  1005           NSCAP_LOG_ASSIGNMENT(this, 0);
  1006           assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
  1009       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  1010             : nsCOMPtr_base(0)
  1011           // assign from |do_GetService(contractid_expr, &rv)|
  1013           NSCAP_LOG_ASSIGNMENT(this, 0);
  1014           assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
  1017       nsCOMPtr( const nsCOMPtr_helper& helper )
  1018             : nsCOMPtr_base(0)
  1019           // ...and finally, anything else we might need to construct from
  1020           //  can exploit the |nsCOMPtr_helper| facility
  1022           NSCAP_LOG_ASSIGNMENT(this, 0);
  1023           assign_from_helper(helper, NS_GET_IID(nsISupports));
  1027         // Assignment operators
  1029       nsCOMPtr<nsISupports>&
  1030       operator=( const nsCOMPtr<nsISupports>& rhs )
  1031           // copy assignment operator
  1033           assign_with_AddRef(rhs.mRawPtr);
  1034           return *this;
  1037       nsCOMPtr<nsISupports>&
  1038       operator=( nsISupports* rhs )
  1039           // assign from a raw pointer (of the right type)
  1041           assign_with_AddRef(rhs);
  1042           return *this;
  1045       nsCOMPtr<nsISupports>&
  1046       operator=( already_AddRefed<nsISupports>& rhs )
  1047           // assign from |already_AddRefed|
  1049           assign_assuming_AddRef(rhs.take());
  1050           return *this;
  1053       nsCOMPtr<nsISupports>&
  1054       operator=( already_AddRefed<nsISupports>&& rhs )
  1055           // assign from |otherComPtr.forget()|
  1057           assign_assuming_AddRef(rhs.take());
  1058           return *this;
  1061       nsCOMPtr<nsISupports>&
  1062       operator=( const nsQueryInterface rhs )
  1063           // assign from |do_QueryInterface(expr)|
  1065           assign_from_qi(rhs, NS_GET_IID(nsISupports));
  1066           return *this;
  1069       nsCOMPtr<nsISupports>&
  1070       operator=( const nsQueryInterfaceWithError& rhs )
  1071           // assign from |do_QueryInterface(expr, &rv)|
  1073           assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
  1074           return *this;
  1077       nsCOMPtr<nsISupports>&
  1078       operator=( const nsGetServiceByCID rhs )
  1079           // assign from |do_GetService(cid_expr)|
  1081           assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
  1082           return *this;
  1085       nsCOMPtr<nsISupports>&
  1086       operator=( const nsGetServiceByCIDWithError& rhs )
  1087           // assign from |do_GetService(cid_expr, &rv)|
  1089           assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
  1090           return *this;
  1093       nsCOMPtr<nsISupports>&
  1094       operator=( const nsGetServiceByContractID rhs )
  1095           // assign from |do_GetService(contractid_expr)|
  1097           assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
  1098           return *this;
  1101       nsCOMPtr<nsISupports>&
  1102       operator=( const nsGetServiceByContractIDWithError& rhs )
  1103           // assign from |do_GetService(contractid_expr, &rv)|
  1105           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
  1106           return *this;
  1109       nsCOMPtr<nsISupports>&
  1110       operator=( const nsCOMPtr_helper& rhs )
  1111           // ...and finally, anything else we might need to assign from
  1112           //  can exploit the |nsCOMPtr_helper| facility.
  1114           assign_from_helper(rhs, NS_GET_IID(nsISupports));
  1115           return *this;
  1118       void
  1119       swap( nsCOMPtr<nsISupports>& rhs )
  1120           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  1122           nsISupports* temp = rhs.mRawPtr;
  1123           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  1124           NSCAP_LOG_ASSIGNMENT(this, temp);
  1125           NSCAP_LOG_RELEASE(this, mRawPtr);
  1126           NSCAP_LOG_RELEASE(&rhs, temp);
  1127           rhs.mRawPtr = mRawPtr;
  1128           mRawPtr = temp;
  1131       void
  1132       swap( nsISupports*& rhs )
  1133           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  1135           nsISupports* temp = rhs;
  1136           NSCAP_LOG_ASSIGNMENT(this, temp);
  1137           NSCAP_LOG_RELEASE(this, mRawPtr);
  1138           rhs = mRawPtr;
  1139           mRawPtr = temp;
  1142       already_AddRefed<nsISupports>
  1143       forget()
  1144           // return the value of mRawPtr and null out mRawPtr. Useful for
  1145           // already_AddRefed return values.
  1147           nsISupports* temp = 0;
  1148           swap(temp);
  1149           return already_AddRefed<nsISupports>(temp);
  1152       void
  1153       forget( nsISupports** rhs )
  1154           // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
  1155           // Useful to avoid unnecessary AddRef/Release pairs with "out"
  1156           // parameters.
  1158           NS_ASSERTION(rhs, "Null pointer passed to forget!");
  1159           *rhs = 0;
  1160           swap(*rhs);
  1163         // Other pointer operators
  1165       nsISupports*
  1166       get() const
  1167           /*
  1168             Prefer the implicit conversion provided automatically by
  1169             |operator nsISupports*() const|.
  1170             Use |get()| to resolve ambiguity or to get a castable pointer.
  1171           */
  1173           return reinterpret_cast<nsISupports*>(mRawPtr);
  1176       operator nsISupports*() const
  1177           /*
  1178             ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
  1179             is used in a context where a raw pointer is expected.  It is this operator
  1180             that makes an |nsCOMPtr| substitutable for a raw pointer.
  1182             Prefer the implicit use of this operator to calling |get()|, except where
  1183             necessary to resolve ambiguity.
  1184           */
  1186           return get();
  1189       nsISupports*
  1190       operator->() const
  1192           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  1193           return get();
  1196       nsCOMPtr<nsISupports>*
  1197       get_address()
  1198           // This is not intended to be used by clients.  See |address_of|
  1199           // below.
  1201           return this;
  1204       const nsCOMPtr<nsISupports>*
  1205       get_address() const
  1206           // This is not intended to be used by clients.  See |address_of|
  1207           // below.
  1209           return this;
  1212     public:
  1214       nsISupports&
  1215       operator*() const
  1217           NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  1218           return *get();
  1221       nsISupports**
  1222       StartAssignment()
  1224 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  1225           return reinterpret_cast<nsISupports**>(begin_assignment());
  1226 #else
  1227           assign_assuming_AddRef(0);
  1228           return reinterpret_cast<nsISupports**>(&mRawPtr);
  1229 #endif
  1231   };
  1233 template <typename T>
  1234 inline void
  1235 ImplCycleCollectionUnlink(nsCOMPtr<T>& aField)
  1237   aField = nullptr;
  1240 template <typename T>
  1241 inline void
  1242 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
  1243                             nsCOMPtr<T>& aField,
  1244                             const char* aName,
  1245                             uint32_t aFlags = 0)
  1247   CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
  1250 #ifndef NSCAP_FEATURE_USE_BASE
  1251 template <class T>
  1252 void
  1253 nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
  1255     if ( rawPtr )
  1256       NSCAP_ADDREF(this, rawPtr);
  1257     assign_assuming_AddRef(reinterpret_cast<T*>(rawPtr));
  1260 template <class T>
  1261 void
  1262 nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
  1264     void* newRawPtr;
  1265     if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
  1266       newRawPtr = 0;
  1267     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1270 template <class T>
  1271 void
  1272 nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
  1274     void* newRawPtr;
  1275     if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
  1276       newRawPtr = 0;
  1277     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1280 template <class T>
  1281 void
  1282 nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
  1284     void* newRawPtr;
  1285     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1286       newRawPtr = 0;
  1287     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1290 template <class T>
  1291 void
  1292 nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
  1294     void* newRawPtr;
  1295     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1296       newRawPtr = 0;
  1297     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1300 template <class T>
  1301 void
  1302 nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
  1304     void* newRawPtr;
  1305     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1306       newRawPtr = 0;
  1307     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1310 template <class T>
  1311 void
  1312 nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
  1314     void* newRawPtr;
  1315     if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1316       newRawPtr = 0;
  1317     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1320 template <class T>
  1321 void
  1322 nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
  1324     void* newRawPtr;
  1325     if ( NS_FAILED( helper(aIID, &newRawPtr) ) )
  1326       newRawPtr = 0;
  1327     assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1330 template <class T>
  1331 void**
  1332 nsCOMPtr<T>::begin_assignment()
  1334     assign_assuming_AddRef(0);
  1335     union { T** mT; void** mVoid; } result;
  1336     result.mT = &mRawPtr;
  1337     return result.mVoid;
  1339 #endif
  1341 template <class T>
  1342 inline
  1343 nsCOMPtr<T>*
  1344 address_of( nsCOMPtr<T>& aPtr )
  1346     return aPtr.get_address();
  1349 template <class T>
  1350 inline
  1351 const nsCOMPtr<T>*
  1352 address_of( const nsCOMPtr<T>& aPtr )
  1354     return aPtr.get_address();
  1357 template <class T>
  1358 class nsGetterAddRefs
  1359     /*
  1360       ...
  1362       This class is designed to be used for anonymous temporary objects in the
  1363       argument list of calls that return COM interface pointers, e.g.,
  1365         nsCOMPtr<IFoo> fooP;
  1366         ...->QueryInterface(iid, getter_AddRefs(fooP))
  1368       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
  1370       When initialized with a |nsCOMPtr|, as in the example above, it returns
  1371       a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
  1372       case) can fill in.
  1374       This type should be a nested class inside |nsCOMPtr<T>|.
  1375     */
  1377     public:
  1378       explicit
  1379       nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
  1380           : mTargetSmartPtr(aSmartPtr)
  1382           // nothing else to do
  1385 #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
  1386      ~nsGetterAddRefs()
  1388 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1389           NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1390 #endif
  1392 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  1393           mTargetSmartPtr.Assert_NoQueryNeeded();
  1394 #endif
  1396 #endif
  1398       operator void**()
  1400           return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
  1402       operator T**()
  1404           return mTargetSmartPtr.StartAssignment();
  1407       T*&
  1408       operator*()
  1410           return *(mTargetSmartPtr.StartAssignment());
  1413     private:
  1414       nsCOMPtr<T>& mTargetSmartPtr;
  1415   };
  1418 template <>
  1419 class nsGetterAddRefs<nsISupports>
  1421     public:
  1422       explicit
  1423       nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
  1424           : mTargetSmartPtr(aSmartPtr)
  1426           // nothing else to do
  1429 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1430      ~nsGetterAddRefs()
  1432           NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1434 #endif
  1436       operator void**()
  1438           return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
  1441       operator nsISupports**()
  1443           return mTargetSmartPtr.StartAssignment();
  1446       nsISupports*&
  1447       operator*()
  1449           return *(mTargetSmartPtr.StartAssignment());
  1452     private:
  1453       nsCOMPtr<nsISupports>& mTargetSmartPtr;
  1454   };
  1457 template <class T>
  1458 inline
  1459 nsGetterAddRefs<T>
  1460 getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
  1461     /*
  1462       Used around a |nsCOMPtr| when 
  1463       ...makes the class |nsGetterAddRefs<T>| invisible.
  1464     */
  1466     return nsGetterAddRefs<T>(aSmartPtr);
  1469 template <class T, class DestinationType>
  1470 inline
  1471 nsresult
  1472 CallQueryInterface( T* aSource, nsGetterAddRefs<DestinationType> aDestination )
  1474     return CallQueryInterface(aSource,
  1475                               static_cast<DestinationType**>(aDestination));
  1479   // Comparing two |nsCOMPtr|s
  1481 template <class T, class U>
  1482 inline
  1483 bool
  1484 operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1486     return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
  1490 template <class T, class U>
  1491 inline
  1492 bool
  1493 operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1495     return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
  1499   // Comparing an |nsCOMPtr| to a raw pointer
  1501 template <class T, class U>
  1502 inline
  1503 bool
  1504 operator==( const nsCOMPtr<T>& lhs, const U* rhs )
  1506     return static_cast<const T*>(lhs.get()) == rhs;
  1509 template <class T, class U>
  1510 inline
  1511 bool
  1512 operator==( const U* lhs, const nsCOMPtr<T>& rhs )
  1514     return lhs == static_cast<const T*>(rhs.get());
  1517 template <class T, class U>
  1518 inline
  1519 bool
  1520 operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
  1522     return static_cast<const T*>(lhs.get()) != rhs;
  1525 template <class T, class U>
  1526 inline
  1527 bool
  1528 operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
  1530     return lhs != static_cast<const T*>(rhs.get());
  1533   // To avoid ambiguities caused by the presence of builtin |operator==|s
  1534   // creating a situation where one of the |operator==| defined above
  1535   // has a better conversion for one argument and the builtin has a
  1536   // better conversion for the other argument, define additional
  1537   // |operator==| without the |const| on the raw pointer.
  1538   // See bug 65664 for details.
  1540 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1541 template <class T, class U>
  1542 inline
  1543 bool
  1544 operator==( const nsCOMPtr<T>& lhs, U* rhs )
  1546     return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
  1549 template <class T, class U>
  1550 inline
  1551 bool
  1552 operator==( U* lhs, const nsCOMPtr<T>& rhs )
  1554     return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
  1557 template <class T, class U>
  1558 inline
  1559 bool
  1560 operator!=( const nsCOMPtr<T>& lhs, U* rhs )
  1562     return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
  1565 template <class T, class U>
  1566 inline
  1567 bool
  1568 operator!=( U* lhs, const nsCOMPtr<T>& rhs )
  1570     return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
  1572 #endif
  1576   // Comparing an |nsCOMPtr| to |0|
  1578 class NSCAP_Zero;
  1580 template <class T>
  1581 inline
  1582 bool
  1583 operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1584     // specifically to allow |smartPtr == 0|
  1586     return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
  1589 template <class T>
  1590 inline
  1591 bool
  1592 operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1593     // specifically to allow |0 == smartPtr|
  1595     return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
  1598 template <class T>
  1599 inline
  1600 bool
  1601 operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1602     // specifically to allow |smartPtr != 0|
  1604     return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
  1607 template <class T>
  1608 inline
  1609 bool
  1610 operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1611     // specifically to allow |0 != smartPtr|
  1613     return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
  1617 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
  1619   // We need to explicitly define comparison operators for `int'
  1620   // because the compiler is lame.
  1622 template <class T>
  1623 inline
  1624 bool
  1625 operator==( const nsCOMPtr<T>& lhs, int rhs )
  1626     // specifically to allow |smartPtr == 0|
  1628     return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
  1631 template <class T>
  1632 inline
  1633 bool
  1634 operator==( int lhs, const nsCOMPtr<T>& rhs )
  1635     // specifically to allow |0 == smartPtr|
  1637     return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
  1640 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
  1642   // Comparing any two [XP]COM objects for identity
  1644 inline
  1645 bool
  1646 SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
  1648     return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
  1653 template <class SourceType, class DestinationType>
  1654 inline
  1655 nsresult
  1656 CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
  1658     return CallQueryInterface(aSourcePtr.get(), aDestPtr);
  1661 #endif // !defined(nsCOMPtr_h___)

mercurial