/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__ |