Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 nsISupportsUtils_h__
7 #define nsISupportsUtils_h__
9 #include "nscore.h"
10 #include "nsISupportsBase.h"
11 #include "nsError.h"
12 #include "nsDebug.h"
13 #include "nsISupportsImpl.h"
14 #include "mozilla/TypeTraits.h"
16 /**
17 * Macro for adding a reference to an interface.
18 * @param _ptr The interface pointer.
19 */
20 #define NS_ADDREF(_ptr) \
21 (_ptr)->AddRef()
23 /**
24 * Macro for adding a reference to this. This macro should be used
25 * because NS_ADDREF (when tracing) may require an ambiguous cast
26 * from the pointers primary type to nsISupports. This macro sidesteps
27 * that entire problem.
28 */
29 #define NS_ADDREF_THIS() \
30 AddRef()
33 extern "C++" {
34 // ...because some one is accidentally including this file inside
35 // an |extern "C"|
38 // Making this a |inline| |template| allows |expr| to be evaluated only once,
39 // yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
40 template <class T>
41 inline
42 void
43 ns_if_addref( T expr )
44 {
45 if (expr) {
46 expr->AddRef();
47 }
48 }
50 } /* extern "C++" */
52 /**
53 * Macro for adding a reference to an interface that checks for nullptr.
54 * @param _expr The interface pointer.
55 */
56 #define NS_IF_ADDREF(_expr) ns_if_addref(_expr)
58 /*
59 * Given these declarations, it explicitly OK and efficient to end a `getter' with:
60 *
61 * NS_IF_ADDREF(*result = mThing);
62 *
63 * even if |mThing| is an |nsCOMPtr|. If |mThing| is an |nsCOMPtr|, however, it is still
64 * _illegal_ to say |NS_IF_ADDREF(mThing)|.
65 */
67 /**
68 * Macro for releasing a reference to an interface.
69 * @param _ptr The interface pointer.
70 */
71 #define NS_RELEASE(_ptr) \
72 do { \
73 (_ptr)->Release(); \
74 (_ptr) = 0; \
75 } while (0)
77 /**
78 * Macro for releasing a reference to this interface.
79 */
80 #define NS_RELEASE_THIS() \
81 Release()
83 /**
84 * Macro for releasing a reference to an interface, except that this
85 * macro preserves the return value from the underlying Release call.
86 * The interface pointer argument will only be NULLed if the reference count
87 * goes to zero.
88 *
89 * @param _ptr The interface pointer.
90 * @param _rc The reference count.
91 */
92 #define NS_RELEASE2(_ptr, _rc) \
93 do { \
94 _rc = (_ptr)->Release(); \
95 if (0 == (_rc)) (_ptr) = 0; \
96 } while (0)
98 /**
99 * Macro for releasing a reference to an interface that checks for nullptr;
100 * @param _ptr The interface pointer.
101 */
102 #define NS_IF_RELEASE(_ptr) \
103 do { \
104 if (_ptr) { \
105 (_ptr)->Release(); \
106 (_ptr) = 0; \
107 } \
108 } while (0)
110 /*
111 * Often you have to cast an implementation pointer, e.g., |this|, to an
112 * |nsISupports*|, but because you have multiple inheritance, a simple cast
113 * is ambiguous. One could simply say, e.g., (given a base |nsIBase|),
114 * |static_cast<nsIBase*>(this)|; but that disguises the fact that what
115 * you are really doing is disambiguating the |nsISupports|. You could make
116 * that more obvious with a double cast, e.g., |static_cast<nsISupports*>
117 (* static_cast<nsIBase*>(this))|, but that is bulky and harder to read...
118 *
119 * The following macro is clean, short, and obvious. In the example above,
120 * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|.
121 */
123 #define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \
124 static_cast<nsISupports*>(static_cast<__unambiguousBase>(__expr))
126 // a type-safe shortcut for calling the |QueryInterface()| member function
127 template <class T, class DestinationType>
128 inline
129 nsresult
130 CallQueryInterface( T* aSource, DestinationType** aDestination )
131 {
132 // We permit nsISupports-to-nsISupports here so that one can still obtain
133 // the canonical nsISupports pointer with CallQueryInterface.
134 static_assert(!mozilla::IsSame<T, DestinationType>::value ||
135 mozilla::IsSame<DestinationType, nsISupports>::value,
136 "don't use CallQueryInterface for compile-time-determinable casts");
138 NS_PRECONDITION(aSource, "null parameter");
139 NS_PRECONDITION(aDestination, "null parameter");
141 return aSource->QueryInterface(NS_GET_TEMPLATE_IID(DestinationType),
142 reinterpret_cast<void**>(aDestination));
143 }
145 #endif /* __nsISupportsUtils_h */