LCOV - code coverage report
Current view: top level - xpcom/base - nsIClassInfoImpl.h (source / functions) Hit Total Coverage
Test: output.info Lines: 1 1 100.0 %
Date: 2017-07-14 16:53:18 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef nsIClassInfoImpl_h__
       8             : #define nsIClassInfoImpl_h__
       9             : 
      10             : #include "mozilla/Alignment.h"
      11             : #include "mozilla/Assertions.h"
      12             : #include "mozilla/MacroArgs.h"
      13             : #include "mozilla/MacroForEach.h"
      14             : #include "nsIClassInfo.h"
      15             : #include "nsISupportsImpl.h"
      16             : 
      17             : #include <new>
      18             : 
      19             : /**
      20             :  * This header file provides macros which help you make your class implement
      21             :  * nsIClassInfo.  Implementing nsIClassInfo is particularly helpful if you have
      22             :  * a C++ class which implements multiple interfaces and which you access from
      23             :  * JavaScript.  If that class implements nsIClassInfo, the JavaScript code
      24             :  * won't have to call QueryInterface on instances of the class; all methods
      25             :  * from all interfaces returned by GetInterfaces() will be available
      26             :  * automagically.
      27             :  *
      28             :  * Here's all you need to do.  Given a class
      29             :  *
      30             :  *   class nsFooBar : public nsIFoo, public nsIBar { };
      31             :  *
      32             :  * you should already have the following nsISupports implementation in its cpp
      33             :  * file:
      34             :  *
      35             :  *   NS_IMPL_ISUPPORTS(nsFooBar, nsIFoo, nsIBar).
      36             :  *
      37             :  * Change this to
      38             :  *
      39             :  *   NS_IMPL_CLASSINFO(nsFooBar, nullptr, 0, NS_FOOBAR_CID)
      40             :  *   NS_IMPL_ISUPPORTS_CI(nsFooBar, nsIFoo, nsIBar)
      41             :  *
      42             :  * If nsFooBar is threadsafe, change the 0 above to nsIClassInfo::THREADSAFE.
      43             :  * If it's a singleton, use nsIClassInfo::SINGLETON.  The full list of flags is
      44             :  * in nsIClassInfo.idl.
      45             :  *
      46             :  * The nullptr parameter is there so you can pass a function for converting
      47             :  * from an XPCOM object to a scriptable helper.  Unless you're doing
      48             :  * specialized JS work, you can probably leave this as nullptr.
      49             :  *
      50             :  * This file also defines the NS_IMPL_QUERY_INTERFACE_CI macro, which you can
      51             :  * use to replace NS_IMPL_QUERY_INTERFACE, if you use that instead of
      52             :  * NS_IMPL_ISUPPORTS.
      53             :  *
      54             :  * That's it!  The rest is gory details.
      55             :  *
      56             :  *
      57             :  * Notice that nsFooBar didn't need to inherit from nsIClassInfo in order to
      58             :  * "implement" it.  However, after adding these macros to nsFooBar, you you can
      59             :  * QueryInterface an instance of nsFooBar to nsIClassInfo.  How can this be?
      60             :  *
      61             :  * The answer lies in the NS_IMPL_ISUPPORTS_CI macro.  It modifies nsFooBar's
      62             :  * QueryInterface implementation such that, if we ask to QI to nsIClassInfo, it
      63             :  * returns a singleton object associated with the class.  (That singleton is
      64             :  * defined by NS_IMPL_CLASSINFO.)  So all nsFooBar instances will return the
      65             :  * same object when QI'ed to nsIClassInfo.  (You can see this in
      66             :  * NS_IMPL_QUERY_CLASSINFO below.)
      67             :  *
      68             :  * This hack breaks XPCOM's rules, since if you take an instance of nsFooBar,
      69             :  * QI it to nsIClassInfo, and then try to QI to nsIFoo, that will fail.  On the
      70             :  * upside, implementing nsIClassInfo doesn't add a vtable pointer to instances
      71             :  * of your class.
      72             :  *
      73             :  * In principal, you can also implement nsIClassInfo by inheriting from the
      74             :  * interface.  But some code expects that when it QI's an object to
      75             :  * nsIClassInfo, it gets back a singleton which isn't attached to any
      76             :  * particular object.  If a class were to implement nsIClassInfo through
      77             :  * inheritance, that code might QI to nsIClassInfo and keep the resulting
      78             :  * object alive, thinking it was only keeping alive the classinfo singleton,
      79             :  * but in fact keeping a whole instance of the class alive.  See, e.g., bug
      80             :  * 658632.
      81             :  *
      82             :  * Unless you specifically need to have a different nsIClassInfo instance for
      83             :  * each instance of your class, you should probably just implement nsIClassInfo
      84             :  * as a singleton.
      85             :  */
      86             : 
      87             : class GenericClassInfo : public nsIClassInfo
      88             : {
      89             : public:
      90             :   struct ClassInfoData
      91             :   {
      92             :     // This function pointer uses NS_CALLBACK_ because it's always set to an
      93             :     // NS_IMETHOD function, which uses __stdcall on Win32.
      94             :     typedef NS_CALLBACK_(nsresult, GetInterfacesProc)(uint32_t* aCountP,
      95             :                                                       nsIID*** aArray);
      96             :     GetInterfacesProc getinterfaces;
      97             : 
      98             :     // This function pointer doesn't use NS_CALLBACK_ because it's always set to
      99             :     // a vanilla function.
     100             :     typedef nsresult (*GetScriptableHelperProc)(nsIXPCScriptable** aHelper);
     101             :     GetScriptableHelperProc getscriptablehelper;
     102             : 
     103             :     uint32_t flags;
     104             :     nsCID cid;
     105             :   };
     106             : 
     107             :   NS_DECL_ISUPPORTS_INHERITED
     108             :   NS_DECL_NSICLASSINFO
     109             : 
     110          22 :   explicit GenericClassInfo(const ClassInfoData* aData) : mData(aData) {}
     111             : 
     112             : private:
     113             :   const ClassInfoData* mData;
     114             : };
     115             : 
     116             : #define NS_CLASSINFO_NAME(_class) g##_class##_classInfoGlobal
     117             : #define NS_CI_INTERFACE_GETTER_NAME(_class) _class##_GetInterfacesHelper
     118             : #define NS_DECL_CI_INTERFACE_GETTER(_class)                                   \
     119             :   extern NS_IMETHODIMP NS_CI_INTERFACE_GETTER_NAME(_class)                    \
     120             :      (uint32_t *, nsIID ***);
     121             : 
     122             : #define NS_IMPL_CLASSINFO(_class, _getscriptablehelper, _flags, _cid)   \
     123             :   NS_DECL_CI_INTERFACE_GETTER(_class)                                   \
     124             :   static const GenericClassInfo::ClassInfoData k##_class##ClassInfoData = { \
     125             :     NS_CI_INTERFACE_GETTER_NAME(_class),                                \
     126             :     _getscriptablehelper,                                               \
     127             :     _flags | nsIClassInfo::SINGLETON_CLASSINFO,                         \
     128             :     _cid,                                                               \
     129             :   };                                                                    \
     130             :   mozilla::AlignedStorage2<GenericClassInfo> k##_class##ClassInfoDataPlace;   \
     131             :   nsIClassInfo* NS_CLASSINFO_NAME(_class) = nullptr;
     132             : 
     133             : #define NS_IMPL_QUERY_CLASSINFO(_class)                                       \
     134             :   if ( aIID.Equals(NS_GET_IID(nsIClassInfo)) ) {                              \
     135             :     if (!NS_CLASSINFO_NAME(_class))                                           \
     136             :       NS_CLASSINFO_NAME(_class) = new (k##_class##ClassInfoDataPlace.addr())  \
     137             :         GenericClassInfo(&k##_class##ClassInfoData);                          \
     138             :     foundInterface = NS_CLASSINFO_NAME(_class);                               \
     139             :   } else
     140             : 
     141             : #define NS_CLASSINFO_HELPER_BEGIN(_class, _c)                                 \
     142             : NS_IMETHODIMP                                                                 \
     143             : NS_CI_INTERFACE_GETTER_NAME(_class)(uint32_t *count, nsIID ***array)          \
     144             : {                                                                             \
     145             :     *count = _c;                                                              \
     146             :     *array = (nsIID **)moz_xmalloc(sizeof (nsIID *) * _c);                \
     147             :     uint32_t i = 0;
     148             : 
     149             : #define NS_CLASSINFO_HELPER_ENTRY(_interface)                                 \
     150             :     (*array)[i++] = (nsIID*)nsMemory::Clone(&NS_GET_IID(_interface),          \
     151             :                                             sizeof(nsIID));
     152             : 
     153             : #define NS_CLASSINFO_HELPER_END                                               \
     154             :     MOZ_ASSERT(i == *count, "Incorrent number of entries");                   \
     155             :     return NS_OK;                                                             \
     156             : }
     157             : 
     158             : #define NS_IMPL_CI_INTERFACE_GETTER(aClass, ...)                              \
     159             :   static_assert(MOZ_ARG_COUNT(__VA_ARGS__) > 0,                               \
     160             :                 "Need more arguments to NS_IMPL_CI_INTERFACE_GETTER");        \
     161             :   NS_CLASSINFO_HELPER_BEGIN(aClass, MOZ_ARG_COUNT(__VA_ARGS__))               \
     162             :     MOZ_FOR_EACH(NS_CLASSINFO_HELPER_ENTRY, (), (__VA_ARGS__))                \
     163             :   NS_CLASSINFO_HELPER_END
     164             : 
     165             : #define NS_IMPL_QUERY_INTERFACE_CI(aClass, ...)                               \
     166             :   static_assert(MOZ_ARG_COUNT(__VA_ARGS__) > 0,                               \
     167             :                 "Need more arguments to NS_IMPL_QUERY_INTERFACE_CI");         \
     168             :   NS_INTERFACE_MAP_BEGIN(aClass)                                              \
     169             :     MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
     170             :     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__))     \
     171             :     NS_IMPL_QUERY_CLASSINFO(aClass)                                           \
     172             :   NS_INTERFACE_MAP_END
     173             : 
     174             : #define NS_IMPL_ISUPPORTS_CI(aClass, ...)                                     \
     175             :   NS_IMPL_ADDREF(aClass)                                                      \
     176             :   NS_IMPL_RELEASE(aClass)                                                     \
     177             :   NS_IMPL_QUERY_INTERFACE_CI(aClass, __VA_ARGS__)                             \
     178             :   NS_IMPL_CI_INTERFACE_GETTER(aClass, __VA_ARGS__)
     179             : 
     180             : #endif // nsIClassInfoImpl_h__

Generated by: LCOV version 1.13