Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/nsAgg.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 nsAgg_h___
8
#define nsAgg_h___
9
10
#include "nsISupports.h"
11
#include "nsCycleCollectionParticipant.h"
12
13
14
////////////////////////////////////////////////////////////////////////////////
15
16
// Put NS_DECL_AGGREGATED or NS_DECL_CYCLE_COLLECTING_AGGREGATED in your class's
17
// declaration.
18
#define NS_DECL_AGGREGATED                                                  \
19
  NS_DECL_ISUPPORTS                                                         \
20
  NS_DECL_AGGREGATED_HELPER
21
22
#define NS_DECL_CYCLE_COLLECTING_AGGREGATED                                 \
23
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS                                        \
24
  NS_DECL_AGGREGATED_HELPER
25
26
#define NS_DECL_AGGREGATED_HELPER                                           \
27
public:                                                                     \
28
                                                                            \
29
    /**                                                                     \
30
     * Returns the nsISupports pointer of the inner object (aka the         \
31
     * aggregatee). This pointer is really only useful to the outer object  \
32
     * (aka the aggregator), which can use it to hold on to the inner       \
33
     * object. Anything else wants the nsISupports pointer of the outer     \
34
     * object (gotten by QI'ing inner or outer to nsISupports). This method \
35
     * returns a non-addrefed pointer.                                      \
36
     * @return the nsISupports pointer of the inner object                  \
37
     */                                                                     \
38
3
    nsISupports* InnerObject(void) { return &fAggregated; }                 \
Unexecuted instantiation: nsProperties::InnerObject()
mozilla::net::nsLoadGroup::InnerObject()
Line
Count
Source
38
3
    nsISupports* InnerObject(void) { return &fAggregated; }                 \
39
                                                                            \
40
    /**                                                                     \
41
     * Returns true if this object is part of an aggregated object.      \
42
     */                                                                     \
43
0
    bool IsPartOfAggregated(void) { return fOuter != InnerObject(); }     \
Unexecuted instantiation: nsProperties::IsPartOfAggregated()
Unexecuted instantiation: mozilla::net::nsLoadGroup::IsPartOfAggregated()
44
                                                                            \
45
private:                                                                    \
46
                                                                            \
47
    /* You must implement this operation instead of the nsISupports */      \
48
    /* methods. */                                                          \
49
    nsresult                                                                \
50
    AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr);       \
51
                                                                            \
52
    class Internal : public nsISupports {                                   \
53
    public:                                                                 \
54
                                                                            \
55
3
        Internal() {}                                                       \
Unexecuted instantiation: nsProperties::Internal::Internal()
mozilla::net::nsLoadGroup::Internal::Internal()
Line
Count
Source
55
3
        Internal() {}                                                       \
56
                                                                            \
57
        NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr)   \
58
                                  override;                                 \
59
        NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override;         \
60
        NS_IMETHOD_(MozExternalRefCountType) Release(void) override;        \
61
                                                                            \
62
        NS_DECL_OWNINGTHREAD                                                \
63
    };                                                                      \
64
                                                                            \
65
    friend class Internal;                                                  \
66
                                                                            \
67
    nsISupports* MOZ_UNSAFE_REF("fOuter can either point to fAggregated "   \
68
                                "or to an outer object, and the safety "    \
69
                                "of this reference depends on the exact "   \
70
                                "lifetime semantics of the AddRef/Release " \
71
                                "functions created by these macros.")       \
72
                        fOuter;                                             \
73
    Internal            fAggregated;                                        \
74
                                                                            \
75
public:                                                                     \
76
77
#define NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(_class)                   \
78
class NS_CYCLE_COLLECTION_INNERCLASS                                        \
79
 : public nsXPCOMCycleCollectionParticipant                                 \
80
{                                                                           \
81
public:                                                                     \
82
  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)    \
83
    : nsXPCOMCycleCollectionParticipant(aSkip) {}                           \
84
                                                                            \
85
  NS_IMETHOD_(void) Unlink(void *p) override;                               \
86
  NS_IMETHOD TraverseNative(void *p, nsCycleCollectionTraversalCallback &cb)\
87
    override;                                                               \
88
  NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(_class)                        \
89
  NS_IMETHOD_(void) DeleteCycleCollectable(void* p) override                \
90
  {                                                                         \
91
    NS_CYCLE_COLLECTION_CLASSNAME(_class)::                                 \
92
      Downcast(static_cast<nsISupports*>(p))->DeleteCycleCollectable();     \
93
  }                                                                         \
94
  static _class* Downcast(nsISupports* s)                                   \
95
  {                                                                         \
96
    return (_class*)((char*)(s) - offsetof(_class, fAggregated));           \
97
  }                                                                         \
98
  static nsISupports* Upcast(_class *p)                                     \
99
  {                                                                         \
100
    return p->InnerObject();                                                \
101
  }                                                                         \
102
  static nsXPCOMCycleCollectionParticipant* GetParticipant()                \
103
  {                                                                         \
104
    return &_class::NS_CYCLE_COLLECTION_INNERNAME;                          \
105
  }                                                                         \
106
};                                                                          \
107
NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class);                                \
108
static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
109
110
// Put this in your class's constructor:
111
#define NS_INIT_AGGREGATED(outer)                                           \
112
3
  do {                                                                      \
113
3
    fOuter = outer ? outer : &fAggregated;                                  \
114
3
  } while(0)
115
116
117
// Put this in your class's implementation file:
118
#define NS_IMPL_AGGREGATED(_class)                                          \
119
                                                                            \
120
NS_IMPL_AGGREGATED_HELPER(_class)                                           \
121
                                                                            \
122
NS_IMETHODIMP_(MozExternalRefCountType)                                     \
123
9
_class::Internal::AddRef(void)                                              \
124
9
{                                                                           \
125
9
    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
126
9
    MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt");               \
127
9
    NS_ASSERT_OWNINGTHREAD(_class);                                         \
128
9
    ++agg->mRefCnt;                                                         \
129
9
    NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this));              \
130
9
    return agg->mRefCnt;                                                    \
131
9
}                                                                           \
Unexecuted instantiation: nsProperties::Internal::AddRef()
mozilla::net::nsLoadGroup::Internal::AddRef()
Line
Count
Source
123
9
_class::Internal::AddRef(void)                                              \
124
9
{                                                                           \
125
9
    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
126
9
    MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt");               \
127
9
    NS_ASSERT_OWNINGTHREAD(_class);                                         \
128
9
    ++agg->mRefCnt;                                                         \
129
9
    NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this));              \
130
9
    return agg->mRefCnt;                                                    \
131
9
}                                                                           \
132
                                                                            \
133
NS_IMETHODIMP_(MozExternalRefCountType)                                     \
134
6
_class::Internal::Release(void)                                             \
135
6
{                                                                           \
136
6
    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
137
6
    MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release");                   \
138
6
    NS_ASSERT_OWNINGTHREAD(_class);                                         \
139
6
    --agg->mRefCnt;                                                         \
140
6
    NS_LOG_RELEASE(this, agg->mRefCnt, #_class);                            \
141
6
    if (agg->mRefCnt == 0) {                                                \
142
0
        agg->mRefCnt = 1; /* stabilize */                                   \
143
0
        delete agg;                                                         \
144
0
        return 0;                                                           \
145
0
    }                                                                       \
146
6
    return agg->mRefCnt;                                                    \
147
6
}                                                                           \
Unexecuted instantiation: nsProperties::Internal::Release()
mozilla::net::nsLoadGroup::Internal::Release()
Line
Count
Source
134
6
_class::Internal::Release(void)                                             \
135
6
{                                                                           \
136
6
    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
137
6
    MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release");                   \
138
6
    NS_ASSERT_OWNINGTHREAD(_class);                                         \
139
6
    --agg->mRefCnt;                                                         \
140
6
    NS_LOG_RELEASE(this, agg->mRefCnt, #_class);                            \
141
6
    if (agg->mRefCnt == 0) {                                                \
142
0
        agg->mRefCnt = 1; /* stabilize */                                   \
143
0
        delete agg;                                                         \
144
0
        return 0;                                                           \
145
0
    }                                                                       \
146
6
    return agg->mRefCnt;                                                    \
147
6
}                                                                           \
148
149
#define NS_IMPL_CYCLE_COLLECTING_AGGREGATED(_class)                         \
150
                                                                            \
151
NS_IMPL_AGGREGATED_HELPER(_class)                                           \
152
                                                                            \
153
NS_IMETHODIMP_(MozExternalRefCountType)                                     \
154
_class::Internal::AddRef(void)                                              \
155
{                                                                           \
156
    _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this);    \
157
    MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt");               \
158
    NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class);                          \
159
    nsrefcnt count = agg->mRefCnt.incr(this);                               \
160
    NS_LOG_ADDREF(this, count, #_class, sizeof(*agg));                      \
161
    return count;                                                           \
162
}                                                                           \
163
NS_IMETHODIMP_(MozExternalRefCountType)                                     \
164
_class::Internal::Release(void)                                             \
165
{                                                                           \
166
    _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this);    \
167
    MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release");                   \
168
    NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class);                          \
169
    nsrefcnt count = agg->mRefCnt.decr(this);                               \
170
    NS_LOG_RELEASE(this, count, #_class);                                   \
171
    return count;                                                           \
172
}                                                                           \
173
NS_IMETHODIMP_(void)                                                        \
174
_class::DeleteCycleCollectable(void)                                        \
175
{                                                                           \
176
  delete this;                                                              \
177
}
178
179
#define NS_IMPL_AGGREGATED_HELPER(_class)                                   \
180
NS_IMETHODIMP                                                               \
181
0
_class::QueryInterface(const nsIID& aIID, void** aInstancePtr)              \
182
0
{                                                                           \
183
0
    return fOuter->QueryInterface(aIID, aInstancePtr);                      \
184
0
}                                                                           \
Unexecuted instantiation: nsProperties::QueryInterface(nsID const&, void**)
Unexecuted instantiation: mozilla::net::nsLoadGroup::QueryInterface(nsID const&, void**)
185
                                                                            \
186
NS_IMETHODIMP_(MozExternalRefCountType)                                     \
187
6
_class::AddRef(void)                                                        \
188
6
{                                                                           \
189
6
    return fOuter->AddRef();                                                \
190
6
}                                                                           \
Unexecuted instantiation: nsProperties::AddRef()
mozilla::net::nsLoadGroup::AddRef()
Line
Count
Source
187
6
_class::AddRef(void)                                                        \
188
6
{                                                                           \
189
6
    return fOuter->AddRef();                                                \
190
6
}                                                                           \
191
                                                                            \
192
NS_IMETHODIMP_(MozExternalRefCountType)                                     \
193
3
_class::Release(void)                                                       \
194
3
{                                                                           \
195
3
    return fOuter->Release();                                               \
196
3
}                                                                           \
Unexecuted instantiation: nsProperties::Release()
mozilla::net::nsLoadGroup::Release()
Line
Count
Source
193
3
_class::Release(void)                                                       \
194
3
{                                                                           \
195
3
    return fOuter->Release();                                               \
196
3
}                                                                           \
197
                                                                            \
198
NS_IMETHODIMP                                                               \
199
3
_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr)    \
200
3
{                                                                           \
201
3
    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
202
3
    return agg->AggregatedQueryInterface(aIID, aInstancePtr);               \
203
3
}                                                                           \
Unexecuted instantiation: nsProperties::Internal::QueryInterface(nsID const&, void**)
mozilla::net::nsLoadGroup::Internal::QueryInterface(nsID const&, void**)
Line
Count
Source
199
3
_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr)    \
200
3
{                                                                           \
201
3
    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
202
3
    return agg->AggregatedQueryInterface(aIID, aInstancePtr);               \
203
3
}                                                                           \
204
205
/**
206
 * To make aggregated objects participate in cycle collection we need to enable
207
 * the outer object (aggregator) to traverse/unlink the objects held by the
208
 * inner object (the aggregatee). We can't just make the inner object QI'able to
209
 * NS_CYCLECOLLECTIONPARTICIPANT_IID, we don't want to return the inner object's
210
 * nsCycleCollectionParticipant for the outer object (which will happen if the
211
 * outer object doesn't participate in cycle collection itself).
212
 * NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID enables the outer object to get
213
 * the inner objects nsCycleCollectionParticipant.
214
 *
215
 * There are three cases:
216
 *   - No aggregation
217
 *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the inner
218
 *     object's nsCycleCollectionParticipant.
219
 *
220
 *   - Aggregation and outer object does not participate in cycle collection
221
 *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will not return anything.
222
 *
223
 *   - Aggregation and outer object does participate in cycle collection
224
 *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the outer
225
 *     object's nsCycleCollectionParticipant. The outer object's
226
 *     nsCycleCollectionParticipant can then QI the inner object to
227
 *     NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID to get the inner object's
228
 *     nsCycleCollectionParticipant, which it can use to traverse/unlink the
229
 *     objects reachable from the inner object.
230
 */
231
#define NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID                        \
232
{                                                                           \
233
    0x32889b7e,                                                             \
234
    0xe4fe,                                                                 \
235
    0x43f4,                                                                 \
236
    { 0x85, 0x31, 0xb5, 0x28, 0x23, 0xa2, 0xe9, 0xfc }                      \
237
}
238
239
/**
240
 * Just holds the IID so NS_GET_IID works.
241
 */
242
class nsAggregatedCycleCollectionParticipant
243
{
244
public:
245
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID)
246
};
247
248
NS_DEFINE_STATIC_IID_ACCESSOR(nsAggregatedCycleCollectionParticipant,
249
                              NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID)
250
251
// for use with QI macros in nsISupportsUtils.h:
252
253
#define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class)                           \
254
3
  NS_IMPL_AGGREGATED_QUERY_HEAD(_class)
255
256
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class)                              \
257
  if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {       \
258
    *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class);                \
259
    return NS_OK;                                                           \
260
  } else
261
262
#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class)          \
263
  NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
264
265
#define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)                    \
266
  if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) {              \
267
    *aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
268
    return NS_OK;                                                           \
269
  } else
270
271
#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)           \
272
  NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
273
274
#define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION_AGGREGATED(_class)        \
275
  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class)                \
276
  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
277
278
#define NS_IMPL_AGGREGATED_QUERY_HEAD(_class)                               \
279
nsresult                                                                    \
280
3
_class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr)        \
281
3
{                                                                           \
282
3
  NS_ASSERTION(aInstancePtr,                                                \
283
3
               "AggregatedQueryInterface requires a non-NULL result ptr!"); \
284
3
  if ( !aInstancePtr )                                                      \
285
3
    return NS_ERROR_NULL_POINTER;                                           \
286
3
  nsISupports* foundInterface;                                              \
287
3
  if ( aIID.Equals(NS_GET_IID(nsISupports)) )                               \
288
3
    foundInterface = InnerObject();                                         \
289
3
  else
290
291
#define NS_IMPL_AGGREGATED_QUERY_CYCLE_COLLECTION(_class)                   \
292
  if (aIID.Equals(IsPartOfAggregated() ?                                    \
293
                  NS_GET_IID(nsCycleCollectionParticipant) :                \
294
                  NS_GET_IID(nsAggregatedCycleCollectionParticipant)))      \
295
    foundInterface = NS_CYCLE_COLLECTION_PARTICIPANT(_class);               \
296
  else
297
298
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(_class)          \
299
  NS_IMETHODIMP                                                             \
300
  NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseNative                     \
301
                         (void *p, nsCycleCollectionTraversalCallback &cb)  \
302
  {                                                                         \
303
    nsISupports *s = static_cast<nsISupports*>(p);                          \
304
    MOZ_ASSERT(CheckForRightISupports(s),                                   \
305
               "not the nsISupports pointer we expect");                    \
306
    _class *tmp = static_cast<_class*>(Downcast(s));                        \
307
    if (!tmp->IsPartOfAggregated())                                         \
308
        NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
309
310
#define NS_GENERIC_AGGREGATED_CONSTRUCTOR(_InstanceClass)                   \
311
static nsresult                                                             \
312
_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID,             \
313
                            void **aResult)                                 \
314
{                                                                           \
315
    *aResult = nullptr;                                                     \
316
    if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports))))        \
317
        return NS_ERROR_INVALID_ARG;                                        \
318
                                                                            \
319
    RefPtr<_InstanceClass> inst = new _InstanceClass(aOuter);               \
320
    if (!inst) {                                                            \
321
        return NS_ERROR_OUT_OF_MEMORY;                                      \
322
    }                                                                       \
323
                                                                            \
324
    nsISupports* inner = inst->InnerObject();                               \
325
    nsresult rv = inner->QueryInterface(aIID, aResult);                     \
326
                                                                            \
327
    return rv;                                                              \
328
}                                                                           \
329
330
#define NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(_InstanceClass, _InitMethod) \
331
static nsresult                                                             \
332
_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID,             \
333
3
                            void **aResult)                                 \
334
3
{                                                                           \
335
3
    *aResult = nullptr;                                                     \
336
3
    if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports))))        \
337
3
        return NS_ERROR_INVALID_ARG;                                        \
338
3
                                                                            \
339
3
    RefPtr<_InstanceClass> inst = new _InstanceClass(aOuter);               \
340
3
    if (!inst) {                                                            \
341
0
        return NS_ERROR_OUT_OF_MEMORY;                                      \
342
0
    }                                                                       \
343
3
                                                                            \
344
3
    nsISupports* inner = inst->InnerObject();                               \
345
3
    NS_ADDREF(inner);                                                       \
346
3
    nsresult rv = inst->_InitMethod();                                      \
347
3
    if (NS_SUCCEEDED(rv)) {                                                 \
348
3
        rv = inner->QueryInterface(aIID, aResult);                          \
349
3
    }                                                                       \
350
3
    NS_RELEASE(inner);                                                      \
351
3
                                                                            \
352
3
    return rv;                                                              \
353
3
}                                                                           \
354
355
#endif /* nsAgg_h___ */