Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/nsIClassInfoImpl.h
Line
Count
Source (jump to first uncovered line)
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
  explicit GenericClassInfo(const ClassInfoData* aData) : mData(aData) {}
111
112
private:
113
  const ClassInfoData* mData;
114
};
115
116
14
#define NS_CLASSINFO_NAME(_class) g##_class##_classInfoGlobal
117
0
#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
108
  if ( aIID.Equals(NS_GET_IID(nsIClassInfo)) ) {                              \
135
14
    if (!NS_CLASSINFO_NAME(_class))                                           \
136
14
      NS_CLASSINFO_NAME(_class) = new (k##_class##ClassInfoDataPlace.addr())  \
137
6
        GenericClassInfo(&k##_class##ClassInfoData);                          \
138
14
    foundInterface = NS_CLASSINFO_NAME(_class);                               \
139
14
  } else
140
141
#define NS_CLASSINFO_HELPER_BEGIN(_class, _c)                                 \
142
NS_IMETHODIMP                                                                 \
143
6
NS_CI_INTERFACE_GETTER_NAME(_class)(uint32_t *count, nsIID ***array)          \
144
6
{                                                                             \
145
6
    *count = _c;                                                              \
146
6
    *array = (nsIID **)moz_xmalloc(sizeof (nsIID *) * _c);                    \
147
6
    uint32_t i = 0;
148
149
#define NS_CLASSINFO_HELPER_ENTRY(_interface)                                 \
150
8
    (*array)[i++] = NS_GET_IID(_interface).Clone();                           \
151
152
#define NS_CLASSINFO_HELPER_END                                               \
153
6
    MOZ_ASSERT(i == *count, "Incorrent number of entries");                   \
154
6
    return NS_OK;                                                             \
155
6
}
156
157
#define NS_IMPL_CI_INTERFACE_GETTER(aClass, ...)                              \
158
  static_assert(MOZ_ARG_COUNT(__VA_ARGS__) > 0,                               \
159
                "Need more arguments to NS_IMPL_CI_INTERFACE_GETTER");        \
160
6
  NS_CLASSINFO_HELPER_BEGIN(aClass, MOZ_ARG_COUNT(__VA_ARGS__))               \
161
8
    MOZ_FOR_EACH(NS_CLASSINFO_HELPER_ENTRY, (), (__VA_ARGS__))                \
162
6
  NS_CLASSINFO_HELPER_END
Unexecuted instantiation: nsMultiplexInputStream_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsPipeInputStream_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsPipeOutputStream_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsStringInputStream_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsThread_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsThreadManager_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsThreadPool_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsBufferedInputStream_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsFileInputStream_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsMIMEInputStream_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: mozilla::net::nsProtocolProxyService_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: mozilla::net::nsSocketTransport_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsXPCComponentsBase_GetInterfacesHelper(unsigned int*, nsID***)
nsXPCComponents_GetInterfacesHelper(unsigned int*, nsID***)
Line
Count
Source
160
3
  NS_CLASSINFO_HELPER_BEGIN(aClass, MOZ_ARG_COUNT(__VA_ARGS__))               \
161
3
    MOZ_FOR_EACH(NS_CLASSINFO_HELPER_ENTRY, (), (__VA_ARGS__))                \
162
3
  NS_CLASSINFO_HELPER_END
nsJSID_GetInterfacesHelper(unsigned int*, nsID***)
Line
Count
Source
160
1
  NS_CLASSINFO_HELPER_BEGIN(aClass, MOZ_ARG_COUNT(__VA_ARGS__))               \
161
1
    MOZ_FOR_EACH(NS_CLASSINFO_HELPER_ENTRY, (), (__VA_ARGS__))                \
162
1
  NS_CLASSINFO_HELPER_END
nsJSIID_GetInterfacesHelper(unsigned int*, nsID***)
Line
Count
Source
160
1
  NS_CLASSINFO_HELPER_BEGIN(aClass, MOZ_ARG_COUNT(__VA_ARGS__))               \
161
1
    MOZ_FOR_EACH(NS_CLASSINFO_HELPER_ENTRY, (), (__VA_ARGS__))                \
162
1
  NS_CLASSINFO_HELPER_END
nsJSCID_GetInterfacesHelper(unsigned int*, nsID***)
Line
Count
Source
160
1
  NS_CLASSINFO_HELPER_BEGIN(aClass, MOZ_ARG_COUNT(__VA_ARGS__))               \
161
1
    MOZ_FOR_EACH(NS_CLASSINFO_HELPER_ENTRY, (), (__VA_ARGS__))                \
162
1
  NS_CLASSINFO_HELPER_END
Unexecuted instantiation: XPCVariant_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: mozilla::storage::AsyncStatement_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: mozilla::storage::Statement_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsPermission_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsDBusHandlerApp_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: ContentPrincipal_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: ExpandedPrincipal_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: NullPrincipal_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: SystemPrincipal_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsCSPContext_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsNSSCertList_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsCommandLine_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsFaviconService_GetInterfacesHelper(unsigned int*, nsID***)
Unexecuted instantiation: nsNavHistory_GetInterfacesHelper(unsigned int*, nsID***)
163
164
#define NS_IMPL_QUERY_INTERFACE_CI(aClass, ...)                               \
165
  static_assert(MOZ_ARG_COUNT(__VA_ARGS__) > 0,                               \
166
                "Need more arguments to NS_IMPL_QUERY_INTERFACE_CI");         \
167
5.92k
  NS_INTERFACE_MAP_BEGIN(aClass)                                              \
168
6.08k
    MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
169
160
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__))     \
170
100
    NS_IMPL_QUERY_CLASSINFO(aClass)                                           \
171
83
  NS_INTERFACE_MAP_END
Unexecuted instantiation: nsStringInputStream::QueryInterface(nsID const&, void**)
Unexecuted instantiation: nsThreadManager::QueryInterface(nsID const&, void**)
Unexecuted instantiation: nsThreadPool::QueryInterface(nsID const&, void**)
nsXPCComponentsBase::QueryInterface(nsID const&, void**)
Line
Count
Source
167
22
  NS_INTERFACE_MAP_BEGIN(aClass)                                              \
168
22
    MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
169
22
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__))     \
170
22
    NS_IMPL_QUERY_CLASSINFO(aClass)                                           \
171
16
  NS_INTERFACE_MAP_END
nsJSID::QueryInterface(nsID const&, void**)
Line
Count
Source
167
25
  NS_INTERFACE_MAP_BEGIN(aClass)                                              \
168
25
    MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
169
25
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__))     \
170
20
    NS_IMPL_QUERY_CLASSINFO(aClass)                                           \
171
17
  NS_INTERFACE_MAP_END
nsJSIID::QueryInterface(nsID const&, void**)
Line
Count
Source
167
47
  NS_INTERFACE_MAP_BEGIN(aClass)                                              \
168
79
    MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
169
79
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__))     \
170
30
    NS_IMPL_QUERY_CLASSINFO(aClass)                                           \
171
24
  NS_INTERFACE_MAP_END
nsJSCID::QueryInterface(nsID const&, void**)
Line
Count
Source
167
51
  NS_INTERFACE_MAP_BEGIN(aClass)                                              \
168
81
    MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
169
81
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__))     \
170
28
    NS_IMPL_QUERY_CLASSINFO(aClass)                                           \
171
26
  NS_INTERFACE_MAP_END
Unexecuted instantiation: nsPermission::QueryInterface(nsID const&, void**)
Unexecuted instantiation: nsDBusHandlerApp::QueryInterface(nsID const&, void**)
Unexecuted instantiation: mozilla::ContentPrincipal::QueryInterface(nsID const&, void**)
Unexecuted instantiation: ExpandedPrincipal::QueryInterface(nsID const&, void**)
Unexecuted instantiation: mozilla::NullPrincipal::QueryInterface(nsID const&, void**)
Unexecuted instantiation: mozilla::SystemPrincipal::QueryInterface(nsID const&, void**)
nsCSPContext::QueryInterface(nsID const&, void**)
Line
Count
Source
167
5.77k
  NS_INTERFACE_MAP_BEGIN(aClass)                                              \
168
5.77k
    MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
169
0
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__))     \
170
0
    NS_IMPL_QUERY_CLASSINFO(aClass)                                           \
171
0
  NS_INTERFACE_MAP_END
Unexecuted instantiation: nsNSSCertList::QueryInterface(nsID const&, void**)
Unexecuted instantiation: nsCommandLine::QueryInterface(nsID const&, void**)
Unexecuted instantiation: nsFaviconService::QueryInterface(nsID const&, void**)
172
173
#define NS_IMPL_ISUPPORTS_CI(aClass, ...)                                     \
174
  NS_IMPL_ADDREF(aClass)                                                      \
175
  NS_IMPL_RELEASE(aClass)                                                     \
176
  NS_IMPL_QUERY_INTERFACE_CI(aClass, __VA_ARGS__)                             \
177
  NS_IMPL_CI_INTERFACE_GETTER(aClass, __VA_ARGS__)
178
179
#endif // nsIClassInfoImpl_h__