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: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
2 /* vim: set ts=2 sw=2 et tw=79: */
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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_ToJSValue_h
8 #define mozilla_dom_ToJSValue_h
10 #include "mozilla/TypeTraits.h"
11 #include "mozilla/Assertions.h"
12 #include "mozilla/dom/BindingUtils.h"
13 #include "mozilla/dom/TypedArray.h"
14 #include "jsapi.h"
15 #include "nsISupports.h"
16 #include "nsTArray.h"
17 #include "nsWrapperCache.h"
19 namespace mozilla {
20 namespace dom {
22 // If ToJSValue returns false, it must set an exception on the
23 // JSContext.
25 // Accept strings.
26 bool
27 ToJSValue(JSContext* aCx,
28 const nsAString& aArgument,
29 JS::MutableHandle<JS::Value> aValue);
31 // Accept booleans.
32 inline bool
33 ToJSValue(JSContext* aCx,
34 bool aArgument,
35 JS::MutableHandle<JS::Value> aValue)
36 {
37 // Make sure we're called in a compartment
38 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
40 aValue.setBoolean(aArgument);
41 return true;
42 }
44 // Accept integer types
45 inline bool
46 ToJSValue(JSContext* aCx,
47 int32_t aArgument,
48 JS::MutableHandle<JS::Value> aValue)
49 {
50 // Make sure we're called in a compartment
51 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
53 aValue.setInt32(aArgument);
54 return true;
55 }
57 // The uint32_t version is disabled for now because on the super-old b2g
58 // compiler nsresult and uint32_t are the same type. If someone needs this at
59 // some point we'll need to figure out how to make it work (e.g. by switching to
60 // traits structs and using the trick IPC's ParamTraits uses, where a traits
61 // struct templated on the type inherits from a base traits struct of some sort,
62 // templated on the same type, or something). Maybe b2g will update to a modern
63 // compiler before that happens....
64 #if 0
65 inline bool
66 ToJSValue(JSContext* aCx,
67 uint32_t aArgument,
68 JS::MutableHandle<JS::Value> aValue)
69 {
70 // Make sure we're called in a compartment
71 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
73 aValue.setNumber(aArgument);
74 return true;
75 }
76 #endif
78 inline bool
79 ToJSValue(JSContext* aCx,
80 int64_t aArgument,
81 JS::MutableHandle<JS::Value> aValue)
82 {
83 // Make sure we're called in a compartment
84 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
86 aValue.setNumber(double(aArgument));
87 return true;
88 }
90 inline bool
91 ToJSValue(JSContext* aCx,
92 uint64_t aArgument,
93 JS::MutableHandle<JS::Value> aValue)
94 {
95 // Make sure we're called in a compartment
96 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
98 aValue.setNumber(double(aArgument));
99 return true;
100 }
102 // accept floating point types
103 inline bool
104 ToJSValue(JSContext* aCx,
105 float aArgument,
106 JS::MutableHandle<JS::Value> aValue)
107 {
108 // Make sure we're called in a compartment
109 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
111 aValue.setNumber(aArgument);
112 return true;
113 }
115 inline bool
116 ToJSValue(JSContext* aCx,
117 double aArgument,
118 JS::MutableHandle<JS::Value> aValue)
119 {
120 // Make sure we're called in a compartment
121 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
123 aValue.setNumber(aArgument);
124 return true;
125 }
127 // Accept objects that inherit from nsWrapperCache and nsISupports (e.g. most
128 // DOM objects).
129 template <class T>
130 typename EnableIf<IsBaseOf<nsWrapperCache, T>::value &&
131 IsBaseOf<nsISupports, T>::value, bool>::Type
132 ToJSValue(JSContext* aCx,
133 T& aArgument,
134 JS::MutableHandle<JS::Value> aValue)
135 {
136 // Make sure we're called in a compartment
137 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
138 // Make sure non-webidl objects don't sneak in here
139 MOZ_ASSERT(aArgument.IsDOMBinding());
141 return WrapNewBindingObject(aCx, aArgument, aValue);
142 }
144 // Accept typed arrays built from appropriate nsTArray values
145 template<typename T>
146 typename EnableIf<IsBaseOf<AllTypedArraysBase, T>::value, bool>::Type
147 ToJSValue(JSContext* aCx,
148 const TypedArrayCreator<T>& aArgument,
149 JS::MutableHandle<JS::Value> aValue)
150 {
151 // Make sure we're called in a compartment
152 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
154 JSObject* obj = aArgument.Create(aCx);
155 if (!obj) {
156 return false;
157 }
158 aValue.setObject(*obj);
159 return true;
160 }
162 // We don't want to include nsContentUtils here, so use a helper
163 // function for the nsISupports case.
164 namespace tojsvalue_detail {
165 bool
166 ISupportsToJSValue(JSContext* aCx,
167 nsISupports* aArgument,
168 JS::MutableHandle<JS::Value> aValue);
169 } // namespace tojsvalue_detail
171 // Accept objects that inherit from nsISupports but not nsWrapperCache (e.g.
172 // nsIDOMFile).
173 template <class T>
174 typename EnableIf<!IsBaseOf<nsWrapperCache, T>::value &&
175 IsBaseOf<nsISupports, T>::value, bool>::Type
176 ToJSValue(JSContext* aCx,
177 T& aArgument,
178 JS::MutableHandle<JS::Value> aValue)
179 {
180 // Make sure we're called in a compartment
181 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
183 return tojsvalue_detail::ISupportsToJSValue(aCx, &aArgument, aValue);
184 }
186 // Accept nsRefPtr/nsCOMPtr
187 template <typename T>
188 bool
189 ToJSValue(JSContext* aCx,
190 const nsCOMPtr<T>& aArgument,
191 JS::MutableHandle<JS::Value> aValue)
192 {
193 return ToJSValue(aCx, *aArgument.get(), aValue);
194 }
196 template <typename T>
197 bool
198 ToJSValue(JSContext* aCx,
199 const nsRefPtr<T>& aArgument,
200 JS::MutableHandle<JS::Value> aValue)
201 {
202 return ToJSValue(aCx, *aArgument.get(), aValue);
203 }
205 // Accept WebIDL dictionaries
206 template <class T>
207 typename EnableIf<IsBaseOf<DictionaryBase, T>::value, bool>::Type
208 ToJSValue(JSContext* aCx,
209 const T& aArgument,
210 JS::MutableHandle<JS::Value> aValue)
211 {
212 return aArgument.ToObject(aCx, aValue);
213 }
215 // Accept existing JS values (which may not be same-compartment with us
216 inline bool
217 ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument,
218 JS::MutableHandle<JS::Value> aValue)
219 {
220 aValue.set(aArgument);
221 return MaybeWrapValue(aCx, aValue);
222 }
224 // Accept nsresult, for use in rejections, and create an XPCOM
225 // exception object representing that nsresult.
226 bool
227 ToJSValue(JSContext* aCx,
228 nsresult aArgument,
229 JS::MutableHandle<JS::Value> aValue);
231 // Accept arrays of other things we accept
232 template <typename T>
233 bool
234 ToJSValue(JSContext* aCx,
235 T* aArguments,
236 size_t aLength,
237 JS::MutableHandle<JS::Value> aValue)
238 {
239 // Make sure we're called in a compartment
240 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
242 JS::AutoValueVector v(aCx);
243 if (!v.resize(aLength)) {
244 return false;
245 }
246 for (size_t i = 0; i < aLength; ++i) {
247 if (!ToJSValue(aCx, aArguments[i], v.handleAt(i))) {
248 return false;
249 }
250 }
251 JSObject* arrayObj = JS_NewArrayObject(aCx, v);
252 if (!arrayObj) {
253 return false;
254 }
255 aValue.setObject(*arrayObj);
256 return true;
257 }
259 template <typename T>
260 bool
261 ToJSValue(JSContext* aCx,
262 const nsTArray<T>& aArgument,
263 JS::MutableHandle<JS::Value> aValue)
264 {
265 return ToJSValue(aCx, aArgument.Elements(),
266 aArgument.Length(), aValue);
267 }
269 template <typename T>
270 bool
271 ToJSValue(JSContext* aCx,
272 const FallibleTArray<T>& aArgument,
273 JS::MutableHandle<JS::Value> aValue)
274 {
275 return ToJSValue(aCx, aArgument.Elements(),
276 aArgument.Length(), aValue);
277 }
279 template <typename T, int N>
280 bool
281 ToJSValue(JSContext* aCx,
282 const T(&aArgument)[N],
283 JS::MutableHandle<JS::Value> aValue)
284 {
285 return ToJSValue(aCx, aArgument, N, aValue);
286 }
288 } // namespace dom
289 } // namespace mozilla
291 #endif /* mozilla_dom_ToJSValue_h */