|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "xpctest_private.h" |
|
6 #include "xpctest_interfaces.h" |
|
7 #include "js/Value.h" |
|
8 |
|
9 NS_IMPL_ISUPPORTS(nsXPCTestParams, nsIXPCTestParams) |
|
10 |
|
11 nsXPCTestParams::nsXPCTestParams() |
|
12 { |
|
13 } |
|
14 |
|
15 nsXPCTestParams::~nsXPCTestParams() |
|
16 { |
|
17 } |
|
18 |
|
19 #define GENERIC_METHOD_IMPL { \ |
|
20 *_retval = *b; \ |
|
21 *b = a; \ |
|
22 return NS_OK; \ |
|
23 } |
|
24 |
|
25 #define STRING_METHOD_IMPL { \ |
|
26 _retval.Assign(b); \ |
|
27 b.Assign(a); \ |
|
28 return NS_OK; \ |
|
29 } |
|
30 |
|
31 #define TAKE_OWNERSHIP_NOOP(val) {} |
|
32 #define TAKE_OWNERSHIP_INTERFACE(val) {static_cast<nsISupports*>(val)->AddRef();} |
|
33 #define TAKE_OWNERSHIP_STRING(val) { \ |
|
34 nsDependentCString vprime(val); \ |
|
35 val = ToNewCString(vprime); \ |
|
36 } |
|
37 #define TAKE_OWNERSHIP_WSTRING(val) { \ |
|
38 nsDependentString vprime(val); \ |
|
39 val = ToNewUnicode(vprime); \ |
|
40 } |
|
41 |
|
42 // Macro for our buffer-oriented types: |
|
43 // 'type' is the type of element that the buffer contains. |
|
44 // 'padding' is an offset added to length, allowing us to handle |
|
45 // null-terminated strings. |
|
46 // 'TAKE_OWNERSHIP' is one of the macros above. |
|
47 #define BUFFER_METHOD_IMPL(type, padding, TAKE_OWNERSHIP) { \ |
|
48 uint32_t elemSize = sizeof(type); \ |
|
49 \ |
|
50 /* Copy b into rv. */ \ |
|
51 *rvLength = *bLength; \ |
|
52 *rv = static_cast<type*>(NS_Alloc(elemSize * (*bLength + padding))); \ |
|
53 if (!*rv) \ |
|
54 return NS_ERROR_OUT_OF_MEMORY; \ |
|
55 memcpy(*rv, *b, elemSize * (*bLength + padding)); \ |
|
56 \ |
|
57 /* Copy a into b. */ \ |
|
58 *bLength = aLength; \ |
|
59 NS_Free(*b); \ |
|
60 *b = static_cast<type*>(NS_Alloc(elemSize * (aLength + padding))); \ |
|
61 if (!*b) \ |
|
62 return NS_ERROR_OUT_OF_MEMORY; \ |
|
63 memcpy(*b, a, elemSize * (aLength + padding)); \ |
|
64 \ |
|
65 /* We need to take ownership of the data we got from a, \ |
|
66 since the caller owns it. */ \ |
|
67 for (unsigned i = 0; i < *bLength + padding; ++i) \ |
|
68 TAKE_OWNERSHIP((*b)[i]); \ |
|
69 \ |
|
70 return NS_OK; \ |
|
71 } |
|
72 |
|
73 /* boolean testBoolean (in boolean a, inout boolean b); */ |
|
74 NS_IMETHODIMP nsXPCTestParams::TestBoolean(bool a, bool *b, bool *_retval) |
|
75 { |
|
76 GENERIC_METHOD_IMPL; |
|
77 } |
|
78 |
|
79 /* octet testOctet (in octet a, inout octet b); */ |
|
80 NS_IMETHODIMP nsXPCTestParams::TestOctet(uint8_t a, uint8_t *b, uint8_t *_retval) |
|
81 { |
|
82 GENERIC_METHOD_IMPL; |
|
83 } |
|
84 |
|
85 /* short testShort (in short a, inout short b); */ |
|
86 NS_IMETHODIMP nsXPCTestParams::TestShort(int16_t a, int16_t *b, int16_t *_retval) |
|
87 { |
|
88 GENERIC_METHOD_IMPL; |
|
89 } |
|
90 |
|
91 /* long testLong (in long a, inout long b); */ |
|
92 NS_IMETHODIMP nsXPCTestParams::TestLong(int32_t a, int32_t *b, int32_t *_retval) |
|
93 { |
|
94 GENERIC_METHOD_IMPL; |
|
95 } |
|
96 |
|
97 /* long long testLongLong (in long long a, inout long long b); */ |
|
98 NS_IMETHODIMP nsXPCTestParams::TestLongLong(int64_t a, int64_t *b, int64_t *_retval) |
|
99 { |
|
100 GENERIC_METHOD_IMPL; |
|
101 } |
|
102 |
|
103 /* unsigned short testUnsignedShort (in unsigned short a, inout unsigned short b); */ |
|
104 NS_IMETHODIMP nsXPCTestParams::TestUnsignedShort(uint16_t a, uint16_t *b, uint16_t *_retval) |
|
105 { |
|
106 GENERIC_METHOD_IMPL; |
|
107 } |
|
108 |
|
109 /* unsigned long testUnsignedLong (in unsigned long a, inout unsigned long b); */ |
|
110 NS_IMETHODIMP nsXPCTestParams::TestUnsignedLong(uint32_t a, uint32_t *b, uint32_t *_retval) |
|
111 { |
|
112 GENERIC_METHOD_IMPL; |
|
113 } |
|
114 |
|
115 /* unsigned long long testUnsignedLongLong (in unsigned long long a, inout unsigned long long b); */ |
|
116 NS_IMETHODIMP nsXPCTestParams::TestUnsignedLongLong(uint64_t a, uint64_t *b, uint64_t *_retval) |
|
117 { |
|
118 GENERIC_METHOD_IMPL; |
|
119 } |
|
120 |
|
121 /* float testFloat (in float a, inout float b); */ |
|
122 NS_IMETHODIMP nsXPCTestParams::TestFloat(float a, float *b, float *_retval) |
|
123 { |
|
124 GENERIC_METHOD_IMPL; |
|
125 } |
|
126 |
|
127 /* double testDouble (in double a, inout float b); */ |
|
128 NS_IMETHODIMP nsXPCTestParams::TestDouble(double a, float *b, double *_retval) |
|
129 { |
|
130 GENERIC_METHOD_IMPL; |
|
131 } |
|
132 |
|
133 /* char testChar (in char a, inout char b); */ |
|
134 NS_IMETHODIMP nsXPCTestParams::TestChar(char a, char *b, char *_retval) |
|
135 { |
|
136 GENERIC_METHOD_IMPL; |
|
137 } |
|
138 |
|
139 /* string testString (in string a, inout string b); */ |
|
140 NS_IMETHODIMP nsXPCTestParams::TestString(const char * a, char * *b, char * *_retval) |
|
141 { |
|
142 nsDependentCString aprime(a); |
|
143 nsDependentCString bprime(*b); |
|
144 *_retval = ToNewCString(bprime); |
|
145 *b = ToNewCString(aprime); |
|
146 |
|
147 // XPCOM ownership rules dictate that overwritten inout params must be callee-freed. |
|
148 // See https://developer.mozilla.org/en/XPIDL |
|
149 NS_Free(const_cast<char*>(bprime.get())); |
|
150 |
|
151 return NS_OK; |
|
152 } |
|
153 |
|
154 /* wchar testWchar (in wchar a, inout wchar b); */ |
|
155 NS_IMETHODIMP nsXPCTestParams::TestWchar(char16_t a, char16_t *b, char16_t *_retval) |
|
156 { |
|
157 GENERIC_METHOD_IMPL; |
|
158 } |
|
159 |
|
160 /* wstring testWstring (in wstring a, inout wstring b); */ |
|
161 NS_IMETHODIMP nsXPCTestParams::TestWstring(const char16_t * a, char16_t * *b, char16_t * *_retval) |
|
162 { |
|
163 nsDependentString aprime(a); |
|
164 nsDependentString bprime(*b); |
|
165 *_retval = ToNewUnicode(bprime); |
|
166 *b = ToNewUnicode(aprime); |
|
167 |
|
168 // XPCOM ownership rules dictate that overwritten inout params must be callee-freed. |
|
169 // See https://developer.mozilla.org/en/XPIDL |
|
170 NS_Free((void*)bprime.get()); |
|
171 |
|
172 return NS_OK; |
|
173 } |
|
174 |
|
175 /* DOMString testDOMString (in DOMString a, inout DOMString b); */ |
|
176 NS_IMETHODIMP nsXPCTestParams::TestDOMString(const nsAString & a, nsAString & b, nsAString & _retval) |
|
177 { |
|
178 STRING_METHOD_IMPL; |
|
179 } |
|
180 |
|
181 |
|
182 /* AString testAString (in AString a, inout AString b); */ |
|
183 NS_IMETHODIMP nsXPCTestParams::TestAString(const nsAString & a, nsAString & b, nsAString & _retval) |
|
184 { |
|
185 STRING_METHOD_IMPL; |
|
186 } |
|
187 |
|
188 /* AUTF8String testAUTF8String (in AUTF8String a, inout AUTF8String b); */ |
|
189 NS_IMETHODIMP nsXPCTestParams::TestAUTF8String(const nsACString & a, nsACString & b, nsACString & _retval) |
|
190 { |
|
191 STRING_METHOD_IMPL; |
|
192 } |
|
193 |
|
194 /* ACString testACString (in ACString a, inout ACString b); */ |
|
195 NS_IMETHODIMP nsXPCTestParams::TestACString(const nsACString & a, nsACString & b, nsACString & _retval) |
|
196 { |
|
197 STRING_METHOD_IMPL; |
|
198 } |
|
199 |
|
200 /* jsval testJsval (in jsval a, in jsval b); */ |
|
201 NS_IMETHODIMP nsXPCTestParams::TestJsval(JS::Handle<JS::Value> a, |
|
202 JS::MutableHandle<JS::Value> b, |
|
203 JS::MutableHandle<JS::Value> _retval) |
|
204 { |
|
205 _retval.set(b); |
|
206 b.set(a); |
|
207 return NS_OK; |
|
208 } |
|
209 |
|
210 /* void testShortArray (in unsigned long aLength, [array, size_is (aLength)] in short a, |
|
211 * inout unsigned long bLength, [array, size_is (bLength)] inout short b, |
|
212 * out unsigned long rvLength, [array, size_is (rvLength), retval] out short rv); */ |
|
213 NS_IMETHODIMP nsXPCTestParams::TestShortArray(uint32_t aLength, int16_t *a, |
|
214 uint32_t *bLength, int16_t **b, |
|
215 uint32_t *rvLength, int16_t **rv) |
|
216 { |
|
217 BUFFER_METHOD_IMPL(int16_t, 0, TAKE_OWNERSHIP_NOOP); |
|
218 } |
|
219 |
|
220 /* void testDoubleArray (in unsigned long aLength, [array, size_is (aLength)] in double a, |
|
221 * inout unsigned long bLength, [array, size_is (bLength)] inout double b, |
|
222 * out unsigned long rvLength, [array, size_is (rvLength), retval] out double rv); */ |
|
223 NS_IMETHODIMP nsXPCTestParams::TestDoubleArray(uint32_t aLength, double *a, |
|
224 uint32_t *bLength, double **b, |
|
225 uint32_t *rvLength, double **rv) |
|
226 { |
|
227 BUFFER_METHOD_IMPL(double, 0, TAKE_OWNERSHIP_NOOP); |
|
228 } |
|
229 |
|
230 /* void testStringArray (in unsigned long aLength, [array, size_is (aLength)] in string a, |
|
231 * inout unsigned long bLength, [array, size_is (bLength)] inout string b, |
|
232 * out unsigned long rvLength, [array, size_is (rvLength), retval] out string rv); */ |
|
233 NS_IMETHODIMP nsXPCTestParams::TestStringArray(uint32_t aLength, const char * *a, |
|
234 uint32_t *bLength, char * **b, |
|
235 uint32_t *rvLength, char * **rv) |
|
236 { |
|
237 BUFFER_METHOD_IMPL(char*, 0, TAKE_OWNERSHIP_STRING); |
|
238 } |
|
239 |
|
240 /* void testWstringArray (in unsigned long aLength, [array, size_is (aLength)] in wstring a, |
|
241 * inout unsigned long bLength, [array, size_is (bLength)] inout wstring b, |
|
242 * out unsigned long rvLength, [array, size_is (rvLength), retval] out wstring rv); */ |
|
243 NS_IMETHODIMP nsXPCTestParams::TestWstringArray(uint32_t aLength, const char16_t * *a, |
|
244 uint32_t *bLength, char16_t * **b, |
|
245 uint32_t *rvLength, char16_t * **rv) |
|
246 { |
|
247 BUFFER_METHOD_IMPL(char16_t*, 0, TAKE_OWNERSHIP_WSTRING); |
|
248 } |
|
249 |
|
250 /* void testInterfaceArray (in unsigned long aLength, [array, size_is (aLength)] in nsIXPCTestInterfaceA a, |
|
251 * inout unsigned long bLength, [array, size_is (bLength)] inout nsIXPCTestInterfaceA b, |
|
252 * out unsigned long rvLength, [array, size_is (rvLength), retval] out nsIXPCTestInterfaceA rv); */ |
|
253 NS_IMETHODIMP nsXPCTestParams::TestInterfaceArray(uint32_t aLength, nsIXPCTestInterfaceA **a, |
|
254 uint32_t *bLength, nsIXPCTestInterfaceA * **b, |
|
255 uint32_t *rvLength, nsIXPCTestInterfaceA * **rv) |
|
256 { |
|
257 BUFFER_METHOD_IMPL(nsIXPCTestInterfaceA*, 0, TAKE_OWNERSHIP_INTERFACE); |
|
258 } |
|
259 |
|
260 /* void testSizedString (in unsigned long aLength, [size_is (aLength)] in string a, |
|
261 * inout unsigned long bLength, [size_is (bLength)] inout string b, |
|
262 * out unsigned long rvLength, [size_is (rvLength), retval] out string rv); */ |
|
263 NS_IMETHODIMP nsXPCTestParams::TestSizedString(uint32_t aLength, const char * a, |
|
264 uint32_t *bLength, char * *b, |
|
265 uint32_t *rvLength, char * *rv) |
|
266 { |
|
267 BUFFER_METHOD_IMPL(char, 1, TAKE_OWNERSHIP_NOOP); |
|
268 } |
|
269 |
|
270 /* void testSizedWstring (in unsigned long aLength, [size_is (aLength)] in wstring a, |
|
271 * inout unsigned long bLength, [size_is (bLength)] inout wstring b, |
|
272 * out unsigned long rvLength, [size_is (rvLength), retval] out wstring rv); */ |
|
273 NS_IMETHODIMP nsXPCTestParams::TestSizedWstring(uint32_t aLength, const char16_t * a, |
|
274 uint32_t *bLength, char16_t * *b, |
|
275 uint32_t *rvLength, char16_t * *rv) |
|
276 { |
|
277 BUFFER_METHOD_IMPL(char16_t, 1, TAKE_OWNERSHIP_NOOP); |
|
278 } |
|
279 |
|
280 /* void testInterfaceIs (in nsIIDPtr aIID, [iid_is (aIID)] in nsQIResult a, |
|
281 * inout nsIIDPtr bIID, [iid_is (bIID)] inout nsQIResult b, |
|
282 * out nsIIDPtr rvIID, [iid_is (rvIID), retval] out nsQIResult rv); */ |
|
283 NS_IMETHODIMP nsXPCTestParams::TestInterfaceIs(const nsIID *aIID, void *a, |
|
284 nsIID **bIID, void **b, |
|
285 nsIID **rvIID, void **rv) |
|
286 { |
|
287 // |
|
288 // Getting the buffers and ownership right here can be a little tricky. |
|
289 // |
|
290 |
|
291 // The interface pointers are heap-allocated, and b has been AddRef'd |
|
292 // by XPConnect for the duration of the call. If we snatch it away from b |
|
293 // and leave no trace, XPConnect won't Release it. Since we also need to |
|
294 // return an already-AddRef'd pointer in rv, we don't need to do anything |
|
295 // special here. |
|
296 *rv = *b; |
|
297 |
|
298 // rvIID is out-only, so nobody allocated an IID buffer for us. Do that now, |
|
299 // and store b's IID in the new buffer. |
|
300 *rvIID = static_cast<nsIID*>(NS_Alloc(sizeof(nsID))); |
|
301 if (!*rvIID) |
|
302 return NS_ERROR_OUT_OF_MEMORY; |
|
303 **rvIID = **bIID; |
|
304 |
|
305 // Copy the interface pointer from a to b. Since a is in-only, XPConnect will |
|
306 // release it upon completion of the call. AddRef it for b. |
|
307 *b = a; |
|
308 static_cast<nsISupports*>(*b)->AddRef(); |
|
309 |
|
310 // We already had a buffer allocated for b's IID, so we can re-use it. |
|
311 **bIID = *aIID; |
|
312 |
|
313 return NS_OK; |
|
314 } |
|
315 |
|
316 /* void testInterfaceIsArray (in unsigned long aLength, in nsIIDPtr aIID, |
|
317 * [array, size_is (aLength), iid_is (aIID)] in nsQIResult a, |
|
318 * inout unsigned long bLength, inout nsIIDPtr bIID, |
|
319 * [array, size_is (bLength), iid_is (bIID)] inout nsQIResult b, |
|
320 * out unsigned long rvLength, out nsIIDPtr rvIID, |
|
321 * [retval, array, size_is (rvLength), iid_is (rvIID)] out nsQIResult rv); */ |
|
322 NS_IMETHODIMP nsXPCTestParams::TestInterfaceIsArray(uint32_t aLength, const nsIID *aIID, |
|
323 void **a, |
|
324 uint32_t *bLength, nsIID **bIID, |
|
325 void ***b, |
|
326 uint32_t *rvLength, nsIID **rvIID, |
|
327 void ***rv) |
|
328 { |
|
329 // Transfer the IIDs. See the comments in TestInterfaceIs (above) for an |
|
330 // explanation of what we're doing. |
|
331 *rvIID = static_cast<nsIID*>(NS_Alloc(sizeof(nsID))); |
|
332 if (!*rvIID) |
|
333 return NS_ERROR_OUT_OF_MEMORY; |
|
334 **rvIID = **bIID; |
|
335 **bIID = *aIID; |
|
336 |
|
337 // The macro is agnostic to the actual interface types, so we can re-use code here. |
|
338 // |
|
339 // Do this second, since the macro returns. |
|
340 BUFFER_METHOD_IMPL(void*, 0, TAKE_OWNERSHIP_INTERFACE); |
|
341 } |