VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp@ 46478

Last change on this file since 46478 was 46478, checked in by vboxsync, 11 years ago

libs/xpcom: touch up Java XPCOM wrapper generation, new common exception handlin
g model
Main/glue: Java glue code with better exception handling, indentation/coding style fixes both in the XSLT and the generated code, touched up Java sample code showing exception handling and getting all error information, Python indentation/whitespace cleanup
Main/idl: make more interfaces available over the webservice, some minor docs changes, whitespace cleanup
Main/webservice: redo error reporting through exceptions, no longer loses error
information, allow more fine-grained suppression of methods/attributed, touched up C++ webservice sample code to support showing the full error information, build system changes to prepare for incremental Java compilation, indentation fixesFrontends/VBoxShell: minor cleanups, coding style fixes, indentation fixes, elim
inate warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.9 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is Java XPCOM Bindings.
15 *
16 * The Initial Developer of the Original Code is IBM Corporation.
17 * Portions created by the Initial Developer are Copyright (C) 2006
18 * IBM Corporation. All Rights Reserved.
19 *
20 * Contributor(s):
21 * Javier Pedemonte ([email protected])
22 *
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
34 *
35 * ***** END LICENSE BLOCK ***** */
36
37#include "nsJavaInterfaces.h"
38#include "nsJavaWrapper.h"
39#include "nsJavaXPTCStub.h"
40#include "nsJavaXPCOMBindingUtils.h"
41#include "jni.h"
42#include "xptcall.h"
43#include "nsIInterfaceInfoManager.h"
44#include "nsString.h"
45#include "nsCRT.h"
46#include "prmem.h"
47#include "nsServiceManagerUtils.h"
48#include "nsThreadUtils.h"
49#include "nsProxyRelease.h"
50
51static nsID nullID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
52
53#ifdef VBOX
54#include "nsIThread.h"
55static nsresult
56NS_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
57 PRUint32 paramCount, nsXPTCVariant* params)
58{
59 return XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
60}
61
62#endif
63
64nsresult
65CreateJavaArray(JNIEnv* env, PRUint8 aType, PRUint32 aSize, const nsID& aIID,
66 jobject* aResult)
67{
68 jobject array = nsnull;
69 switch (aType)
70 {
71 case nsXPTType::T_I8:
72 array = env->NewByteArray(aSize);
73 break;
74
75 case nsXPTType::T_I16:
76 case nsXPTType::T_U8:
77 array = env->NewShortArray(aSize);
78 break;
79
80 case nsXPTType::T_I32:
81 case nsXPTType::T_U16:
82 array = env->NewIntArray(aSize);
83 break;
84
85 case nsXPTType::T_I64:
86 case nsXPTType::T_U32:
87 array = env->NewLongArray(aSize);
88 break;
89
90 case nsXPTType::T_FLOAT:
91 array = env->NewFloatArray(aSize);
92 break;
93
94 // XXX how do we handle unsigned 64-bit values?
95 case nsXPTType::T_U64:
96 case nsXPTType::T_DOUBLE:
97 array = env->NewDoubleArray(aSize);
98 break;
99
100 case nsXPTType::T_BOOL:
101 array = env->NewBooleanArray(aSize);
102 break;
103
104 case nsXPTType::T_CHAR:
105 case nsXPTType::T_WCHAR:
106 array = env->NewCharArray(aSize);
107 break;
108
109 case nsXPTType::T_CHAR_STR:
110 case nsXPTType::T_WCHAR_STR:
111 case nsXPTType::T_IID:
112 case nsXPTType::T_ASTRING:
113 case nsXPTType::T_DOMSTRING:
114 case nsXPTType::T_UTF8STRING:
115 case nsXPTType::T_CSTRING:
116 array = env->NewObjectArray(aSize, stringClass, nsnull);
117 break;
118
119 case nsXPTType::T_INTERFACE:
120 case nsXPTType::T_INTERFACE_IS:
121 {
122 nsCOMPtr<nsIInterfaceInfoManager>
123 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
124 NS_ASSERTION(iim, "Failed to get InterfaceInfoManager");
125 if (!iim)
126 return NS_ERROR_FAILURE;
127
128 // Get interface info for given IID
129 nsCOMPtr<nsIInterfaceInfo> info;
130 nsresult rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
131 if (NS_FAILED(rv))
132 return rv;
133
134 // Get interface name
135 const char* iface_name;
136 rv = info->GetNameShared(&iface_name);
137 if (NS_FAILED(rv))
138 return rv;
139
140 // Create proper Java interface name
141 nsCAutoString class_name("org/mozilla/interfaces/");
142 class_name.AppendASCII(iface_name);
143 jclass ifaceClass = env->FindClass(class_name.get());
144 if (!ifaceClass)
145 return NS_ERROR_FAILURE;
146
147 array = env->NewObjectArray(aSize, ifaceClass, nsnull);
148 break;
149 }
150
151 case nsXPTType::T_VOID:
152 array = env->NewLongArray(aSize);
153 break;
154
155 default:
156 NS_WARNING("unknown type");
157 return NS_ERROR_FAILURE;
158 }
159
160 if (!array)
161 return NS_ERROR_OUT_OF_MEMORY;
162
163 *aResult = array;
164 return NS_OK;
165}
166
167nsresult
168GetNativeArrayElement(PRUint8 aType, void* aArray, PRUint32 aIndex,
169 nsXPTCVariant* aResult)
170{
171 switch (aType)
172 {
173 case nsXPTType::T_I8:
174 case nsXPTType::T_U8:
175 aResult->val.u8 = static_cast<PRUint8*>(aArray)[aIndex];
176 break;
177
178 case nsXPTType::T_I16:
179 case nsXPTType::T_U16:
180 aResult->val.u16 = static_cast<PRUint16*>(aArray)[aIndex];
181 break;
182
183 case nsXPTType::T_I32:
184 case nsXPTType::T_U32:
185 aResult->val.u32 = static_cast<PRUint32*>(aArray)[aIndex];
186 break;
187
188 case nsXPTType::T_I64:
189 case nsXPTType::T_U64:
190 aResult->val.u64 = static_cast<PRUint64*>(aArray)[aIndex];
191 break;
192
193 case nsXPTType::T_FLOAT:
194 aResult->val.f = static_cast<float*>(aArray)[aIndex];
195 break;
196
197 case nsXPTType::T_DOUBLE:
198 aResult->val.d = static_cast<double*>(aArray)[aIndex];
199 break;
200
201 case nsXPTType::T_BOOL:
202 aResult->val.b = static_cast<PRBool*>(aArray)[aIndex];
203 break;
204
205 case nsXPTType::T_CHAR:
206 aResult->val.c = static_cast<char*>(aArray)[aIndex];
207 break;
208
209 case nsXPTType::T_WCHAR:
210 aResult->val.wc = static_cast<PRUnichar*>(aArray)[aIndex];
211 break;
212
213 case nsXPTType::T_CHAR_STR:
214 aResult->val.p = static_cast<char**>(aArray)[aIndex];
215 break;
216
217 case nsXPTType::T_WCHAR_STR:
218 aResult->val.p = static_cast<PRUnichar**>(aArray)[aIndex];
219 break;
220
221 case nsXPTType::T_IID:
222 aResult->val.p = static_cast<nsID**>(aArray)[aIndex];
223 break;
224
225 case nsXPTType::T_INTERFACE:
226 case nsXPTType::T_INTERFACE_IS:
227 aResult->val.p = static_cast<nsISupports**>(aArray)[aIndex];
228 break;
229
230 case nsXPTType::T_ASTRING:
231 case nsXPTType::T_DOMSTRING:
232 aResult->val.p = static_cast<nsString**>(aArray)[aIndex];
233 break;
234
235 case nsXPTType::T_UTF8STRING:
236 case nsXPTType::T_CSTRING:
237 aResult->val.p = static_cast<nsCString**>(aArray)[aIndex];
238 break;
239
240 case nsXPTType::T_VOID:
241 aResult->val.p = static_cast<void**>(aArray)[aIndex];
242 break;
243
244 default:
245 NS_WARNING("unknown type");
246 return NS_ERROR_FAILURE;
247 }
248
249 return NS_OK;
250}
251
252nsresult
253CreateNativeArray(PRUint8 aType, PRUint32 aSize, void** aResult)
254{
255 void* array = nsnull;
256 switch (aType)
257 {
258 case nsXPTType::T_I8:
259 case nsXPTType::T_U8:
260 array = PR_Malloc(aSize * sizeof(PRUint8));
261 break;
262
263 case nsXPTType::T_I16:
264 case nsXPTType::T_U16:
265 array = PR_Malloc(aSize * sizeof(PRUint16));
266 break;
267
268 case nsXPTType::T_I32:
269 case nsXPTType::T_U32:
270 array = PR_Malloc(aSize * sizeof(PRUint32));
271 break;
272
273 case nsXPTType::T_I64:
274 case nsXPTType::T_U64:
275 array = PR_Malloc(aSize * sizeof(PRUint64));
276 break;
277
278 case nsXPTType::T_FLOAT:
279 array = PR_Malloc(aSize * sizeof(float));
280 break;
281
282 case nsXPTType::T_DOUBLE:
283 array = PR_Malloc(aSize * sizeof(double));
284 break;
285
286 case nsXPTType::T_BOOL:
287 array = PR_Malloc(aSize * sizeof(PRBool));
288 break;
289
290 case nsXPTType::T_CHAR:
291 array = PR_Malloc(aSize * sizeof(char));
292 break;
293
294 case nsXPTType::T_WCHAR:
295 array = PR_Malloc(aSize * sizeof(PRUnichar));
296 break;
297
298 case nsXPTType::T_CHAR_STR:
299 case nsXPTType::T_WCHAR_STR:
300 case nsXPTType::T_IID:
301 case nsXPTType::T_ASTRING:
302 case nsXPTType::T_DOMSTRING:
303 case nsXPTType::T_UTF8STRING:
304 case nsXPTType::T_CSTRING:
305 case nsXPTType::T_INTERFACE:
306 case nsXPTType::T_INTERFACE_IS:
307 array = PR_Malloc(aSize * sizeof(void*));
308 break;
309
310 case nsXPTType::T_VOID:
311 array = PR_Malloc(aSize * sizeof(void*));
312 break;
313
314 default:
315 NS_WARNING("unknown type");
316 return NS_ERROR_FAILURE;
317 }
318
319 if (!array)
320 return NS_ERROR_OUT_OF_MEMORY;
321
322 *aResult = array;
323 return NS_OK;
324}
325
326/**
327 * Handle 'in' and 'inout' params.
328 */
329nsresult
330SetupParams(JNIEnv *env, const jobject aParam, PRUint8 aType, PRBool aIsOut,
331 const nsID& aIID, PRUint8 aArrayType, PRUint32 aArraySize,
332 PRBool aIsArrayElement, PRUint32 aIndex, nsXPTCVariant &aVariant)
333{
334 nsresult rv = NS_OK;
335
336 switch (aType)
337 {
338 case nsXPTType::T_I8:
339 {
340 LOG(("byte\n"));
341 if (!aIsOut && !aIsArrayElement) { // 'in'
342 aVariant.val.i8 = env->CallByteMethod(aParam, byteValueMID);
343 } else { // 'inout' & 'array'
344 jbyte value;
345 if (aParam) {
346 env->GetByteArrayRegion((jbyteArray) aParam, aIndex, 1, &value);
347 }
348
349 if (aIsOut) { // 'inout'
350 if (aParam) {
351 aVariant.val.i8 = value;
352 aVariant.ptr = &aVariant.val;
353 } else {
354 aVariant.ptr = nsnull;
355 }
356 aVariant.SetPtrIsData();
357 } else { // 'array'
358 static_cast<PRInt8*>(aVariant.val.p)[aIndex] = value;
359 }
360 }
361 break;
362 }
363
364 case nsXPTType::T_I16:
365 case nsXPTType::T_U8: // C++ unsigned octet <=> Java short
366 {
367 LOG(("short\n"));
368 if (!aIsOut && !aIsArrayElement) { // 'in'
369 jshort value = env->CallShortMethod(aParam, shortValueMID);
370 if (aType == nsXPTType::T_I16)
371 aVariant.val.i16 = value;
372 else
373 aVariant.val.u8 = value;
374 } else { // 'inout' & 'array'
375 jshort value;
376 if (aParam) {
377 env->GetShortArrayRegion((jshortArray) aParam, aIndex, 1, &value);
378 }
379
380 if (aIsOut) { // 'inout'
381 if (aParam) {
382 if (aType == nsXPTType::T_I16)
383 aVariant.val.i16 = value;
384 else
385 aVariant.val.u8 = value;
386 aVariant.ptr = &aVariant.val;
387 } else {
388 aVariant.ptr = nsnull;
389 }
390 aVariant.SetPtrIsData();
391 } else { // 'array'
392 if (aType == nsXPTType::T_I16)
393 static_cast<PRInt16*>(aVariant.val.p)[aIndex] = value;
394 else
395 static_cast<PRUint8*>(aVariant.val.p)[aIndex] = value;
396 }
397 }
398 break;
399 }
400
401 case nsXPTType::T_I32:
402 case nsXPTType::T_U16: // C++ unsigned short <=> Java int
403 {
404 LOG(("int\n"));
405 if (!aIsOut && !aIsArrayElement) { // 'in'
406 jint value = env->CallIntMethod(aParam, intValueMID);
407 if (aType == nsXPTType::T_I32)
408 aVariant.val.i32 = value;
409 else
410 aVariant.val.u16 = value;
411 } else { // 'inout' & 'array'
412 jint value;
413 if (aParam) {
414 env->GetIntArrayRegion((jintArray) aParam, aIndex, 1, &value);
415 }
416
417 if (aIsOut) { // 'inout'
418 if (aParam) {
419 if (aType == nsXPTType::T_I32)
420 aVariant.val.i32 = value;
421 else
422 aVariant.val.u16 = value;
423 aVariant.ptr = &aVariant.val;
424 } else {
425 aVariant.ptr = nsnull;
426 }
427 aVariant.SetPtrIsData();
428 } else { // 'array'
429 if (aType == nsXPTType::T_I32)
430 static_cast<PRInt32*>(aVariant.val.p)[aIndex] = value;
431 else
432 static_cast<PRUint16*>(aVariant.val.p)[aIndex] = value;
433 }
434 }
435 break;
436 }
437
438 case nsXPTType::T_I64:
439 case nsXPTType::T_U32: // C++ unsigned int <=> Java long
440 {
441 LOG(("long\n"));
442 if (!aIsOut && !aIsArrayElement) { // 'in'
443 jlong value = env->CallLongMethod(aParam, longValueMID);
444 if (aType == nsXPTType::T_I64)
445 aVariant.val.i64 = value;
446 else
447 aVariant.val.u32 = value;
448 } else { // 'inout' & 'array'
449 jlong value;
450 if (aParam) {
451 env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);
452 }
453
454 if (aIsOut) { // 'inout'
455 if (aParam) {
456 if (aType == nsXPTType::T_I64)
457 aVariant.val.i64 = value;
458 else
459 aVariant.val.u32 = value;
460 aVariant.ptr = &aVariant.val;
461 } else {
462 aVariant.ptr = nsnull;
463 }
464 aVariant.SetPtrIsData();
465 } else { // 'array'
466 if (aType == nsXPTType::T_I64)
467 static_cast<PRInt64*>(aVariant.val.p)[aIndex] = value;
468 else
469 static_cast<PRUint32*>(aVariant.val.p)[aIndex] = value;
470 }
471 }
472 break;
473 }
474
475 case nsXPTType::T_FLOAT:
476 {
477 LOG(("float\n"));
478 if (!aIsOut && !aIsArrayElement) { // 'in'
479 aVariant.val.f = env->CallFloatMethod(aParam, floatValueMID);
480 } else { // 'inout' & 'array'
481 jfloat value;
482 if (aParam) {
483 env->GetFloatArrayRegion((jfloatArray) aParam, aIndex, 1, &value);
484 }
485
486 if (aIsOut) { // 'inout'
487 if (aParam) {
488 aVariant.val.f = value;
489 aVariant.ptr = &aVariant.val;
490 } else {
491 aVariant.ptr = nsnull;
492 }
493 aVariant.SetPtrIsData();
494 } else { // 'array'
495 static_cast<float*>(aVariant.val.p)[aIndex] = value;
496 }
497 }
498 break;
499 }
500
501 // XXX how do we handle unsigned 64-bit value?
502 case nsXPTType::T_U64: // C++ unsigned long <=> Java double
503 case nsXPTType::T_DOUBLE:
504 {
505 LOG(("double\n"));
506 if (!aIsOut && !aIsArrayElement) { // 'in'
507 jdouble value = env->CallDoubleMethod(aParam, doubleValueMID);
508 if (aType == nsXPTType::T_DOUBLE)
509 aVariant.val.d = value;
510 else
511 aVariant.val.u64 = static_cast<PRUint64>(value);
512 } else { // 'inout' & 'array'
513 jdouble value;
514 if (aParam) {
515 env->GetDoubleArrayRegion((jdoubleArray) aParam, aIndex, 1, &value);
516 }
517
518 if (aIsOut) { // 'inout'
519 if (aParam) {
520 if (aType == nsXPTType::T_DOUBLE)
521 aVariant.val.d = value;
522 else
523 aVariant.val.u64 = static_cast<PRUint64>(value);
524 aVariant.ptr = &aVariant.val;
525 } else {
526 aVariant.ptr = nsnull;
527 }
528 aVariant.SetPtrIsData();
529 } else { // 'array'
530 if (aType == nsXPTType::T_DOUBLE)
531 static_cast<double*>(aVariant.val.p)[aIndex] = value;
532 else
533 static_cast<PRUint64*>(aVariant.val.p)[aIndex] =
534 static_cast<PRUint64>(value);
535 }
536 }
537 break;
538 }
539
540 case nsXPTType::T_BOOL:
541 {
542 LOG(("boolean\n"));
543 if (!aIsOut && !aIsArrayElement) { // 'in'
544 aVariant.val.b = env->CallBooleanMethod(aParam, booleanValueMID);
545 } else { // 'inout' & 'array'
546 jboolean value;
547 if (aParam) {
548 env->GetBooleanArrayRegion((jbooleanArray) aParam, aIndex, 1, &value);
549 }
550
551 if (aIsOut) { // 'inout'
552 if (aParam) {
553 aVariant.val.b = value;
554 aVariant.ptr = &aVariant.val;
555 } else {
556 aVariant.ptr = nsnull;
557 }
558 aVariant.SetPtrIsData();
559 } else { // 'array'
560 static_cast<PRBool*>(aVariant.val.p)[aIndex] = value;
561 }
562 }
563 break;
564 }
565
566 case nsXPTType::T_CHAR:
567 {
568 LOG(("char\n"));
569 if (!aIsOut && !aIsArrayElement) { // 'in'
570 aVariant.val.c = env->CallCharMethod(aParam, charValueMID);
571 } else { // 'inout' & 'array'
572 jchar value;
573 if (aParam) {
574 env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);
575 }
576
577 if (aIsOut) { // 'inout'
578 if (aParam) {
579 aVariant.val.c = value;
580 aVariant.ptr = &aVariant.val;
581 } else {
582 aVariant.ptr = nsnull;
583 }
584 aVariant.SetPtrIsData();
585 } else { // 'array'
586 static_cast<char*>(aVariant.val.p)[aIndex] = value;
587 }
588 }
589 break;
590 }
591
592 case nsXPTType::T_WCHAR:
593 {
594 LOG(("char\n"));
595 if (!aIsOut && !aIsArrayElement) { // 'in'
596 aVariant.val.wc = env->CallCharMethod(aParam, charValueMID);
597 } else { // 'inout' & 'array'
598 jchar value;
599 if (aParam) {
600 env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);
601 }
602
603 if (aIsOut) { // 'inout'
604 if (aParam) {
605 aVariant.val.wc = value;
606 aVariant.ptr = &aVariant.val;
607 } else {
608 aVariant.ptr = nsnull;
609 }
610 aVariant.SetPtrIsData();
611 } else { // 'array'
612 static_cast<PRUnichar*>(aVariant.val.p)[aIndex] = value;
613 }
614 }
615 break;
616 }
617
618 case nsXPTType::T_CHAR_STR:
619 case nsXPTType::T_WCHAR_STR:
620 {
621 LOG(("String\n"));
622 jstring data = nsnull;
623 if (!aIsOut && !aIsArrayElement) { // 'in'
624 data = (jstring) aParam;
625 } else if (aParam) { // 'inout' & 'array'
626 data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
627 aIndex);
628 }
629
630 void* buf = nsnull;
631 if (data) {
632 jsize uniLength = env->GetStringLength(data);
633 if (uniLength > 0) {
634 if (aType == nsXPTType::T_CHAR_STR) {
635 jsize utf8Length = env->GetStringUTFLength(data);
636 buf = nsMemory::Alloc((utf8Length + 1) * sizeof(char));
637 if (!buf) {
638 rv = NS_ERROR_OUT_OF_MEMORY;
639 break;
640 }
641
642 char* char_str = static_cast<char*>(buf);
643 env->GetStringUTFRegion(data, 0, uniLength, char_str);
644 char_str[utf8Length] = '\0';
645
646 } else { // if T_WCHAR_STR
647 buf = nsMemory::Alloc((uniLength + 1) * sizeof(jchar));
648 if (!buf) {
649 rv = NS_ERROR_OUT_OF_MEMORY;
650 break;
651 }
652
653 jchar* jchar_str = static_cast<jchar*>(buf);
654 env->GetStringRegion(data, 0, uniLength, jchar_str);
655 jchar_str[uniLength] = '\0';
656 }
657 } else {
658 // create empty string
659 buf = nsMemory::Alloc(2);
660 if (!buf) {
661 rv = NS_ERROR_OUT_OF_MEMORY;
662 break;
663 }
664 ((jchar*)buf)[0] = '\0';
665 }
666 }
667
668 if (!aIsArrayElement) { // 'in' & 'inout'
669 aVariant.val.p = buf;
670 if (aIsOut) { // 'inout'
671 aVariant.ptr = &aVariant.val;
672 aVariant.SetPtrIsData();
673 }
674 } else { // 'array'
675 if (aType == nsXPTType::T_CHAR_STR) {
676 char* str = static_cast<char*>(buf);
677 static_cast<char**>(aVariant.val.p)[aIndex] = str;
678 } else {
679 PRUnichar* str = static_cast<PRUnichar*>(buf);
680 static_cast<PRUnichar**>(aVariant.val.p)[aIndex] = str;
681 }
682 }
683 break;
684 }
685
686 case nsXPTType::T_IID:
687 {
688 LOG(("String(IID)\n"));
689 jstring data = nsnull;
690 if (!aIsOut && !aIsArrayElement) { // 'in'
691 data = (jstring) aParam;
692 } else if (aParam) { // 'inout' & 'array'
693 data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
694 aIndex);
695 }
696
697 nsID* iid = new nsID;
698 if (!iid) {
699 rv = NS_ERROR_OUT_OF_MEMORY;
700 break;
701 }
702 if (data) {
703 // extract IID string from Java string
704 const char* str = env->GetStringUTFChars(data, nsnull);
705 if (!str) {
706 delete iid;
707 rv = NS_ERROR_OUT_OF_MEMORY;
708 break;
709 }
710
711 // parse string into IID object
712 iid->Parse(str);
713 env->ReleaseStringUTFChars(data, str);
714 } else {
715 *iid = nullID;
716 }
717
718 if (!aIsArrayElement) { // 'in' & 'inout'
719 aVariant.val.p = iid;
720 if (aIsOut) { // 'inout'
721 aVariant.ptr = &aVariant.val;
722 aVariant.SetPtrIsData();
723 }
724 } else { // 'array'
725 static_cast<nsID**>(aVariant.val.p)[aIndex] = iid;
726 }
727 break;
728 }
729
730 case nsXPTType::T_INTERFACE:
731 case nsXPTType::T_INTERFACE_IS:
732 {
733 LOG(("nsISupports\n"));
734 jobject java_obj = nsnull;
735 if (!aIsOut && !aIsArrayElement) { // 'in'
736 java_obj = (jobject) aParam;
737 } else if (aParam) { // 'inout' & 'array'
738 java_obj = (jobject) env->GetObjectArrayElement((jobjectArray) aParam,
739 aIndex);
740 }
741
742 void* xpcom_obj;
743 if (java_obj) {
744 // If the requested interface is nsIWeakReference, then we look for or
745 // create a stub for the nsISupports interface. Then we create a weak
746 // reference from that stub.
747 PRBool isWeakRef;
748 nsID iid;
749 if (aIID.Equals(NS_GET_IID(nsIWeakReference))) {
750 isWeakRef = PR_TRUE;
751 iid = NS_GET_IID(nsISupports);
752 } else {
753 isWeakRef = PR_FALSE;
754 iid = aIID;
755 }
756
757 rv = JavaObjectToNativeInterface(env, java_obj, iid, &xpcom_obj);
758 if (NS_FAILED(rv))
759 break;
760 rv = ((nsISupports*) xpcom_obj)->QueryInterface(iid, &xpcom_obj);
761 if (NS_FAILED(rv))
762 break;
763
764 // If the function expects a weak reference, then we need to
765 // create it here.
766 if (isWeakRef) {
767 nsISupports* isupports = (nsISupports*) xpcom_obj;
768 nsCOMPtr<nsISupportsWeakReference> supportsweak =
769 do_QueryInterface(isupports);
770 if (supportsweak) {
771 nsWeakPtr weakref;
772 supportsweak->GetWeakReference(getter_AddRefs(weakref));
773 NS_RELEASE(isupports);
774 xpcom_obj = weakref;
775 NS_ADDREF((nsISupports*) xpcom_obj);
776 } else {
777 xpcom_obj = nsnull;
778 }
779 }
780 } else {
781 xpcom_obj = nsnull;
782 }
783
784 if (!aIsArrayElement) { // 'in' & 'inout'
785 aVariant.val.p = xpcom_obj;
786 aVariant.SetValIsInterface();
787 if (aIsOut) { // 'inout'
788 aVariant.ptr = &aVariant.val;
789 aVariant.SetPtrIsData();
790 }
791 } else { // 'array'
792 static_cast<void**>(aVariant.val.p)[aIndex] = xpcom_obj;
793 }
794 break;
795 }
796
797 case nsXPTType::T_ASTRING:
798 case nsXPTType::T_DOMSTRING:
799 {
800 LOG(("String\n"));
801 // Expecting only 'in' and 'in dipper'
802 NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
803 if (aIsOut) {
804 rv = NS_ERROR_UNEXPECTED;
805 break;
806 }
807
808 jstring jstr = static_cast<jstring>(aParam);
809 nsAString* str = jstring_to_nsAString(env, jstr);
810 if (!str) {
811 rv = NS_ERROR_OUT_OF_MEMORY;
812 break;
813 }
814
815 aVariant.val.p = str;
816 aVariant.SetValIsDOMString();
817 break;
818 }
819
820 case nsXPTType::T_UTF8STRING:
821 case nsXPTType::T_CSTRING:
822 {
823 LOG(("StringUTF\n"));
824 // Expecting only 'in' and 'in dipper'
825 NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
826 if (aIsOut) {
827 rv = NS_ERROR_UNEXPECTED;
828 break;
829 }
830
831 jstring jstr = static_cast<jstring>(aParam);
832 nsACString* str = jstring_to_nsACString(env, jstr);
833 if (!str) {
834 rv = NS_ERROR_OUT_OF_MEMORY;
835 break;
836 }
837
838 aVariant.val.p = str;
839 if (aType == nsXPTType::T_CSTRING) {
840 aVariant.SetValIsCString();
841 } else {
842 aVariant.SetValIsUTF8String();
843 }
844 break;
845 }
846
847 // handle "void *" as an "long" in Java
848 case nsXPTType::T_VOID:
849 {
850 LOG(("long (void*)\n"));
851 if (!aIsOut && !aIsArrayElement) { // 'in'
852 aVariant.val.p =
853 reinterpret_cast<void*>(env->CallLongMethod(aParam, longValueMID));
854 } else { // 'inout' & 'array'
855 jlong value;
856 if (aParam) {
857 env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);
858 }
859
860 if (aIsOut) { // 'inout'
861 if (aParam) {
862 aVariant.val.p = reinterpret_cast<void*>(value);
863 aVariant.ptr = &aVariant.val;
864 } else {
865 aVariant.ptr = nsnull;
866 }
867 aVariant.SetPtrIsData();
868 } else { // 'array'
869 static_cast<void**>(aVariant.val.p)[aIndex] =
870 reinterpret_cast<void*>(value);
871 }
872 }
873 break;
874 }
875
876 case nsXPTType::T_ARRAY:
877 {
878 jobject sourceArray = nsnull;
879 if (!aIsOut) { // 'in'
880 sourceArray = aParam;
881 } else if (aParam) { // 'inout'
882 jobjectArray array = static_cast<jobjectArray>(aParam);
883 sourceArray = env->GetObjectArrayElement(array, 0);
884 }
885
886 if (sourceArray) {
887 rv = CreateNativeArray(aArrayType, aArraySize, &aVariant.val.p);
888
889 for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
890 rv = SetupParams(env, sourceArray, aArrayType, PR_FALSE, aIID, 0, 0,
891 PR_TRUE, i, aVariant);
892 }
893 }
894
895 if (aIsOut) { // 'inout'
896 aVariant.ptr = &aVariant.val.p;
897 aVariant.SetPtrIsData();
898 }
899 break;
900 }
901
902 case nsXPTType::T_PSTRING_SIZE_IS:
903 case nsXPTType::T_PWSTRING_SIZE_IS:
904 {
905 NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
906
907 LOG(("Sized string\n"));
908 jstring data = nsnull;
909 if (!aIsOut) { // 'in'
910 data = (jstring) aParam;
911 } else if (aParam) { // 'inout'
912 data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
913 aIndex);
914 }
915
916 PRUint32 length = 0;
917 if (data) {
918 if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
919 length = env->GetStringUTFLength(data);
920 } else {
921 length = env->GetStringLength(data);
922 }
923 if (length > aArraySize) {
924 rv = NS_ERROR_ILLEGAL_VALUE;
925 break;
926 }
927 }
928
929 PRUint32 size_of_char = (aType == nsXPTType::T_PSTRING_SIZE_IS) ?
930 sizeof(char) : sizeof(jchar);
931 PRUint32 allocLength = (aArraySize + 1) * size_of_char;
932 void* buf = nsMemory::Alloc(allocLength);
933 if (!buf) {
934 rv = NS_ERROR_OUT_OF_MEMORY;
935 break;
936 }
937
938 if (data) {
939 if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
940 const char* str = env->GetStringUTFChars(data, nsnull);
941 if (!str) {
942 nsMemory::Free(buf);
943 rv = NS_ERROR_OUT_OF_MEMORY;
944 break;
945 }
946 memcpy(buf, str, length);
947 env->ReleaseStringUTFChars(data, str);
948 } else {
949 jchar* jchar_str = static_cast<jchar*>(buf);
950 env->GetStringRegion(data, 0, length, jchar_str);
951 }
952 }
953
954 aVariant.val.p = buf;
955 if (aIsOut) { // 'inout'
956 aVariant.ptr = &aVariant.val;
957 aVariant.SetPtrIsData();
958 }
959
960 break;
961 }
962
963 default:
964 NS_WARNING("unexpected parameter type");
965 return NS_ERROR_UNEXPECTED;
966 }
967
968 return rv;
969}
970
971/**
972 * Does any cleanup from objects created in SetupParams, as well as converting
973 * any out params to Java.
974 *
975 * NOTE: If aInvokeResult is an error condition, then we just do cleanup in
976 * this function.
977 */
978nsresult
979FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,
980 nsXPTCVariant &aVariant, const nsID& aIID,
981 PRBool aIsArrayElement, PRUint8 aArrayType, PRUint32 aArraySize,
982 PRUint32 aIndex, nsresult aInvokeResult, jobject* aParam)
983{
984 nsresult rv = NS_OK;
985
986 switch (aType)
987 {
988 case nsXPTType::T_I8:
989 {
990 if (NS_SUCCEEDED(aInvokeResult)) {
991 jbyte value = aVariant.val.i8;
992 if (aParamInfo.IsRetval() && !aIsArrayElement) {
993 *aParam = env->NewObject(byteClass, byteInitMID, value);
994 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
995 env->SetByteArrayRegion((jbyteArray) *aParam, aIndex, 1, &value);
996 }
997 }
998 break;
999 }
1000
1001 case nsXPTType::T_I16:
1002 case nsXPTType::T_U8:
1003 {
1004 if (NS_SUCCEEDED(aInvokeResult)) {
1005 jshort value = (aType == nsXPTType::T_I16) ? aVariant.val.i16 :
1006 aVariant.val.u8;
1007 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1008 *aParam = env->NewObject(shortClass, shortInitMID, value);
1009 } else if ((aParamInfo.IsOut() || aIsArrayElement) && aParam) {
1010 env->SetShortArrayRegion((jshortArray) *aParam, aIndex, 1, &value);
1011 }
1012 }
1013 break;
1014 }
1015
1016 case nsXPTType::T_I32:
1017 case nsXPTType::T_U16:
1018 {
1019 if (NS_SUCCEEDED(aInvokeResult)) {
1020 jint value = (aType == nsXPTType::T_I32) ? aVariant.val.i32 :
1021 aVariant.val.u16;
1022 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1023 *aParam = env->NewObject(intClass, intInitMID, value);
1024 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1025 env->SetIntArrayRegion((jintArray) *aParam, aIndex, 1, &value);
1026 }
1027 }
1028 break;
1029 }
1030
1031 case nsXPTType::T_I64:
1032 case nsXPTType::T_U32:
1033 {
1034 if (NS_SUCCEEDED(aInvokeResult)) {
1035 jlong value = (aType == nsXPTType::T_I64) ? aVariant.val.i64 :
1036 aVariant.val.u32;
1037 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1038 *aParam = env->NewObject(longClass, longInitMID, value);
1039 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1040 env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
1041 }
1042 }
1043 break;
1044 }
1045
1046 case nsXPTType::T_FLOAT:
1047 {
1048 if (NS_SUCCEEDED(aInvokeResult)) {
1049 jfloat value = aVariant.val.f;
1050 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1051 *aParam = env->NewObject(floatClass, floatInitMID, value);
1052 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1053 env->SetFloatArrayRegion((jfloatArray) *aParam, aIndex, 1, &value);
1054 }
1055 }
1056 break;
1057 }
1058
1059 // XXX how do we handle unsigned 64-bit values?
1060 case nsXPTType::T_U64:
1061 case nsXPTType::T_DOUBLE:
1062 {
1063 if (NS_SUCCEEDED(aInvokeResult)) {
1064 jdouble value = (aType == nsXPTType::T_DOUBLE) ? aVariant.val.d :
1065 aVariant.val.u64;
1066 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1067 *aParam = env->NewObject(doubleClass, doubleInitMID, value);
1068 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1069 env->SetDoubleArrayRegion((jdoubleArray) *aParam, aIndex, 1, &value);
1070 }
1071 }
1072 break;
1073 }
1074
1075 case nsXPTType::T_BOOL:
1076 {
1077 if (NS_SUCCEEDED(aInvokeResult)) {
1078 jboolean value = aVariant.val.b;
1079 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1080 *aParam = env->NewObject(booleanClass, booleanInitMID, value);
1081 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1082 env->SetBooleanArrayRegion((jbooleanArray) *aParam, aIndex, 1, &value);
1083 }
1084 }
1085 break;
1086 }
1087
1088 case nsXPTType::T_CHAR:
1089 case nsXPTType::T_WCHAR:
1090 {
1091 if (NS_SUCCEEDED(aInvokeResult)) {
1092 jchar value;
1093 if (aType == nsXPTType::T_CHAR)
1094 value = aVariant.val.c;
1095 else
1096 value = aVariant.val.wc;
1097 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1098 *aParam = env->NewObject(charClass, charInitMID, value);
1099 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1100 env->SetCharArrayRegion((jcharArray) *aParam, aIndex, 1, &value);
1101 }
1102 }
1103 break;
1104 }
1105
1106 case nsXPTType::T_CHAR_STR:
1107 case nsXPTType::T_WCHAR_STR:
1108 {
1109 if ((aParamInfo.IsOut() || aIsArrayElement) &&
1110 NS_SUCCEEDED(aInvokeResult))
1111 {
1112 // create new string from data
1113 jstring str = nsnull;
1114 if (aVariant.val.p) {
1115 if (aType == nsXPTType::T_CHAR_STR) {
1116 str = env->NewStringUTF((const char*) aVariant.val.p);
1117 } else {
1118 PRUint32 length = nsCRT::strlen((const PRUnichar*) aVariant.val.p);
1119 str = env->NewString((const jchar*) aVariant.val.p, length);
1120 }
1121 if (!str) {
1122 rv = NS_ERROR_OUT_OF_MEMORY;
1123 break;
1124 }
1125 }
1126
1127 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1128 *aParam = str;
1129 } else if (*aParam) {
1130 // put new string into output array
1131 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
1132 }
1133 }
1134
1135 // cleanup
1136 if (aVariant.val.p)
1137 nsMemory::Free(aVariant.val.p);
1138 break;
1139 }
1140
1141 case nsXPTType::T_IID:
1142 {
1143 nsID* iid = static_cast<nsID*>(aVariant.val.p);
1144
1145 if ((aParamInfo.IsOut() || aIsArrayElement) &&
1146 NS_SUCCEEDED(aInvokeResult))
1147 {
1148 // Create the string from nsID
1149 jstring str = nsnull;
1150 if (iid) {
1151 char iid_str[NSID_LENGTH];
1152 iid->ToProvidedString(iid_str);
1153 str = env->NewStringUTF(iid_str);
1154 if (!str) {
1155 rv = NS_ERROR_OUT_OF_MEMORY;
1156 break;
1157 }
1158 }
1159
1160 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1161 *aParam = str;
1162 } else if (*aParam) {
1163 // put new string into output array
1164 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
1165 }
1166 }
1167
1168 // Ordinarily, we would delete 'iid' here. But we cannot do that until
1169 // we've handled all of the params. See comment in CallXPCOMMethod.
1170 // We can safely delete array elements, though.
1171 if (aIsArrayElement)
1172 delete iid;
1173
1174 break;
1175 }
1176
1177 case nsXPTType::T_INTERFACE:
1178 case nsXPTType::T_INTERFACE_IS:
1179 {
1180 nsISupports* xpcom_obj = static_cast<nsISupports*>(aVariant.val.p);
1181
1182 if ((aParamInfo.IsOut() || aIsArrayElement) &&
1183 NS_SUCCEEDED(aInvokeResult))
1184 {
1185 jobject java_obj = nsnull;
1186 if (xpcom_obj) {
1187 // Get matching Java object for given xpcom object
1188 rv = NativeInterfaceToJavaObject(env, xpcom_obj, aIID, nsnull,
1189 &java_obj);
1190 if (NS_FAILED(rv))
1191 break;
1192 }
1193
1194 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1195 *aParam = java_obj;
1196 } else if (*aParam) {
1197 // put new Java object into output array
1198 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, java_obj);
1199 }
1200 }
1201
1202 // cleanup
1203 NS_IF_RELEASE(xpcom_obj);
1204 break;
1205 }
1206
1207 case nsXPTType::T_ASTRING:
1208 case nsXPTType::T_DOMSTRING:
1209 {
1210 NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
1211 if (!aParamInfo.IsIn()) {
1212 rv = NS_ERROR_UNEXPECTED;
1213 break;
1214 }
1215
1216 nsString* str = static_cast<nsString*>(aVariant.val.p);
1217 if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
1218 // Create Java string from returned nsString
1219 jstring jstr = nsnull;
1220 if (str && !str->IsVoid()) {
1221 jstr = env->NewString((const jchar*) str->get(), str->Length());
1222 if (!jstr) {
1223 rv = NS_ERROR_OUT_OF_MEMORY;
1224 break;
1225 }
1226 }
1227
1228 *aParam = jstr;
1229 }
1230
1231 // cleanup
1232 if (str) {
1233 delete str;
1234 }
1235 break;
1236 }
1237
1238 case nsXPTType::T_UTF8STRING:
1239 case nsXPTType::T_CSTRING:
1240 {
1241 NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
1242 if (!aParamInfo.IsIn()) {
1243 rv = NS_ERROR_UNEXPECTED;
1244 break;
1245 }
1246
1247 nsCString* str = static_cast<nsCString*>(aVariant.val.p);
1248 if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
1249 // Create Java string from returned nsString
1250 jstring jstr = nsnull;
1251 if (str && !str->IsVoid()) {
1252 jstr = env->NewStringUTF((const char*) str->get());
1253 if (!jstr) {
1254 rv = NS_ERROR_OUT_OF_MEMORY;
1255 break;
1256 }
1257 }
1258
1259 *aParam = jstr;
1260 }
1261
1262 // cleanup
1263 if (str) {
1264 delete str;
1265 }
1266 break;
1267 }
1268
1269 case nsXPTType::T_VOID:
1270 {
1271 if (NS_SUCCEEDED(aInvokeResult)) {
1272 jlong value = reinterpret_cast<jlong>(aVariant.val.p);
1273 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1274 *aParam = env->NewObject(longClass, longInitMID, value);
1275 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1276 env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
1277 }
1278 }
1279 break;
1280 }
1281
1282 case nsXPTType::T_ARRAY:
1283 {
1284 if (aParamInfo.IsOut() && NS_SUCCEEDED(aInvokeResult)) {
1285 // Create Java array from returned native array
1286 jobject jarray = nsnull;
1287 if (aVariant.val.p) {
1288 rv = CreateJavaArray(env, aArrayType, aArraySize, aIID, &jarray);
1289 if (NS_FAILED(rv))
1290 break;
1291
1292 nsXPTCVariant var;
1293 for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
1294 rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
1295 if (NS_SUCCEEDED(rv)) {
1296 rv = FinalizeParams(env, aParamInfo, aArrayType, var, aIID,
1297 PR_TRUE, 0, 0, i, aInvokeResult, &jarray);
1298 }
1299 }
1300 }
1301
1302 if (aParamInfo.IsRetval()) {
1303 *aParam = jarray;
1304 } else if (*aParam) {
1305 // put new Java array into output array
1306 env->SetObjectArrayElement((jobjectArray) *aParam, 0, jarray);
1307 }
1308 }
1309
1310 // cleanup
1311 // If this is not an out param or if the invokeResult is a failure case,
1312 // then the array elements have not been cleaned up. Do so now.
1313 if (!aParamInfo.IsOut() || (NS_FAILED(aInvokeResult) && aVariant.val.p)) {
1314 nsXPTCVariant var;
1315 for (PRUint32 i = 0; i < aArraySize; i++) {
1316 rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
1317 if (NS_SUCCEEDED(rv)) {
1318 FinalizeParams(env, aParamInfo, aArrayType, var, aIID, PR_TRUE,
1319 0, 0, i, NS_ERROR_FAILURE, nsnull);
1320 }
1321 }
1322 }
1323 PR_Free(aVariant.val.p);
1324 break;
1325 }
1326
1327 case nsXPTType::T_PSTRING_SIZE_IS:
1328 case nsXPTType::T_PWSTRING_SIZE_IS:
1329 {
1330 NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
1331
1332 if ((aParamInfo.IsOut()) && NS_SUCCEEDED(aInvokeResult))
1333 {
1334 // create new string from data
1335 jstring str = nsnull;
1336 if (aVariant.val.p) {
1337 if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
1338 PRUint32 len = (aArraySize + 1) * sizeof(char);
1339 char* buf = (char*) nsMemory::Alloc(len);
1340 if (buf) {
1341 memcpy(buf, aVariant.val.p, len);
1342 buf[aArraySize] = '\0';
1343 str = env->NewStringUTF((const char*) buf);
1344 nsMemory::Free(buf);
1345 }
1346 } else {
1347 str = env->NewString((const jchar*) aVariant.val.p, aArraySize);
1348 }
1349 if (!str) {
1350 rv = NS_ERROR_OUT_OF_MEMORY;
1351 break;
1352 }
1353 }
1354
1355 if (aParamInfo.IsRetval()) {
1356 *aParam = str;
1357 } else if (*aParam) {
1358 // put new string into output array
1359 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
1360 }
1361 }
1362
1363 // cleanup
1364 if (aVariant.val.p)
1365 nsMemory::Free(aVariant.val.p);
1366 break;
1367 }
1368
1369 default:
1370 NS_WARNING("unexpected parameter type");
1371 return NS_ERROR_UNEXPECTED;
1372 }
1373
1374 // Check for Java exception, but don't overwrite pre-existing error code.
1375 if (NS_SUCCEEDED(rv) && env->ExceptionCheck())
1376 rv = NS_ERROR_FAILURE;
1377
1378 return rv;
1379}
1380
1381nsresult
1382QueryAttributeInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
1383 PRBool aCapitalizedAttr, PRUint16* aMethodIndex,
1384 const nsXPTMethodInfo** aMethodInfo)
1385
1386{
1387 nsresult rv = NS_ERROR_FAILURE;
1388
1389 // An 'attribute' will start with either "get" or "set". But first,
1390 // we check the length, in order to skip over method names that match exactly
1391 // "get" or "set".
1392 if (strlen(aMethodName) > 3) {
1393 if (strncmp("get", aMethodName, 3) == 0) {
1394 char* getterName = strdup(aMethodName + 3);
1395 if (!aCapitalizedAttr) {
1396 getterName[0] = tolower(getterName[0]);
1397 }
1398 rv = aIInfo->GetMethodInfoForName(getterName, aMethodIndex, aMethodInfo);
1399 free(getterName);
1400 } else if (strncmp("set", aMethodName, 3) == 0) {
1401 char* setterName = strdup(aMethodName + 3);
1402 if (!aCapitalizedAttr) {
1403 setterName[0] = tolower(setterName[0]);
1404 }
1405 rv = aIInfo->GetMethodInfoForName(setterName, aMethodIndex, aMethodInfo);
1406 if (NS_SUCCEEDED(rv)) {
1407 // If this succeeded, GetMethodInfoForName will have returned the
1408 // method info for the 'getter'. We want the 'setter', so increase
1409 // method index by one ('setter' immediately follows the 'getter'),
1410 // and get its method info.
1411 (*aMethodIndex)++;
1412 rv = aIInfo->GetMethodInfo(*aMethodIndex, aMethodInfo);
1413 if (NS_SUCCEEDED(rv)) {
1414 // Double check that this methodInfo matches the given method.
1415 if (!(*aMethodInfo)->IsSetter() ||
1416 strcmp(setterName, (*aMethodInfo)->name) != 0) {
1417 rv = NS_ERROR_FAILURE;
1418 }
1419 }
1420 }
1421 free(setterName);
1422 }
1423 }
1424
1425 return rv;
1426}
1427
1428/**
1429 * Given an interface info struct and a method name, returns the method info
1430 * and index, if that method exists.
1431 *
1432 * Most method names are lower case. Unfortunately, the method names of some
1433 * interfaces (such as nsIAppShell) start with a capital letter. This function
1434 * will try all of the permutations.
1435 */
1436nsresult
1437QueryMethodInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
1438 PRUint16* aMethodIndex, const nsXPTMethodInfo** aMethodInfo)
1439{
1440 // Skip over any leading underscores, since these are methods that conflicted
1441 // with existing Java keywords
1442 const char* methodName = aMethodName;
1443 if (methodName[0] == '_') {
1444 methodName++;
1445 }
1446
1447 // The common case is that the method name is lower case, so we check
1448 // that first.
1449 nsresult rv;
1450 rv = aIInfo->GetMethodInfoForName(methodName, aMethodIndex, aMethodInfo);
1451 if (NS_SUCCEEDED(rv))
1452 return rv;
1453
1454 // If there is no method called <aMethodName>, then maybe it is an
1455 // 'attribute'.
1456 rv = QueryAttributeInfo(aIInfo, methodName, PR_FALSE, aMethodIndex,
1457 aMethodInfo);
1458 if (NS_SUCCEEDED(rv))
1459 return rv;
1460
1461 // If we get here, then maybe the method name is capitalized.
1462 char* name = strdup(methodName);
1463 name[0] = toupper(name[0]);
1464 rv = aIInfo->GetMethodInfoForName(name, aMethodIndex, aMethodInfo);
1465 free(name);
1466 if (NS_SUCCEEDED(rv))
1467 return rv;
1468
1469 // If there is no method called <aMethodName>, then maybe it is an
1470 // 'attribute'.
1471 rv = QueryAttributeInfo(aIInfo, methodName, PR_TRUE, aMethodIndex,
1472 aMethodInfo);
1473
1474 return rv;
1475}
1476
1477#ifdef VBOX
1478#include <nsIExceptionService.h>
1479#include <iprt/err.h>
1480#include "nspr.h"
1481
1482static void makeErrorMessage(nsresult r, char* msg, size_t msgSize)
1483{
1484 bool gotMsg = false;
1485
1486 if (!gotMsg)
1487 {
1488 nsresult rc;
1489 nsCOMPtr <nsIExceptionService> es;
1490 es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
1491 if (NS_SUCCEEDED (rc))
1492 {
1493 nsCOMPtr <nsIExceptionManager> em;
1494 rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
1495 if (NS_SUCCEEDED (rc))
1496 {
1497 nsCOMPtr <nsIException> ex;
1498 rc = em->GetCurrentException(getter_AddRefs (ex));
1499 if (NS_SUCCEEDED (rc) && ex)
1500 {
1501 nsXPIDLCString emsg;
1502 ex->GetMessage(getter_Copies(emsg));
1503 PR_snprintf(msg, msgSize, "%s",
1504 emsg.get());
1505 gotMsg = true;
1506 }
1507 }
1508 }
1509 }
1510
1511 if (!gotMsg)
1512 {
1513 const RTCOMERRMSG* pMsg = RTErrCOMGet(r);
1514 if (strncmp(pMsg->pszMsgFull, "Unknown", 7) != 0)
1515 {
1516 PR_snprintf(msg, msgSize, "%s (%s)",
1517 pMsg->pszMsgFull, pMsg->pszDefine);
1518 gotMsg = true;
1519 }
1520 }
1521
1522 if (!gotMsg)
1523 {
1524 PR_snprintf(msg, msgSize, "Error 0x%x in module 0x%x",
1525 NS_ERROR_GET_CODE(r), NS_ERROR_GET_MODULE(r));
1526 }
1527}
1528#endif
1529
1530/**
1531 * org.mozilla.xpcom.XPCOMJavaProxy.internal.callXPCOMMethod
1532 */
1533extern "C" NS_EXPORT jobject JNICALL
1534JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
1535 jstring aMethodName, jobjectArray aParams)
1536{
1537 nsresult rv;
1538
1539 // Get native XPCOM instance
1540 void* xpcom_obj;
1541 rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
1542 if (NS_FAILED(rv)) {
1543 ThrowException(env, 0, "Failed to get matching XPCOM object");
1544 return nsnull;
1545 }
1546 JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(xpcom_obj);
1547
1548 // Get method info
1549 PRUint16 methodIndex;
1550 const nsXPTMethodInfo* methodInfo;
1551 nsIInterfaceInfo* iinfo = inst->InterfaceInfo();
1552 const char* methodName = env->GetStringUTFChars(aMethodName, nsnull);
1553 rv = QueryMethodInfo(iinfo, methodName, &methodIndex, &methodInfo);
1554 env->ReleaseStringUTFChars(aMethodName, methodName);
1555
1556 if (NS_FAILED(rv)) {
1557 ThrowException(env, rv, "GetMethodInfoForName failed");
1558 return nsnull;
1559 }
1560
1561#ifdef DEBUG_JAVAXPCOM
1562 const char* ifaceName;
1563 iinfo->GetNameShared(&ifaceName);
1564 LOG(("===> (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
1565#endif
1566
1567 // Convert the Java params
1568 PRUint8 paramCount = methodInfo->GetParamCount();
1569 nsXPTCVariant* params = nsnull;
1570 if (paramCount)
1571 {
1572 params = new nsXPTCVariant[paramCount];
1573 if (!params) {
1574 ThrowException(env, NS_ERROR_OUT_OF_MEMORY, "Can't create params array");
1575 return nsnull;
1576 }
1577 memset(params, 0, paramCount * sizeof(nsXPTCVariant));
1578
1579 PRBool foundDependentParam = PR_FALSE;
1580 for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
1581 {
1582 LOG(("\t Param %d: ", i));
1583 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
1584 params[i].type = paramInfo.GetType();
1585
1586 if (params[i].type.IsDependent() && paramInfo.IsIn()) {
1587 foundDependentParam = PR_TRUE;
1588 continue;
1589 }
1590
1591 if (paramInfo.IsIn()) {
1592 PRUint8 type = params[i].type.TagPart();
1593
1594 // get IID for interface params
1595 nsID iid;
1596 if (type == nsXPTType::T_INTERFACE) {
1597 rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
1598 methodIndex, params, PR_TRUE, iid);
1599 }
1600
1601 if (NS_SUCCEEDED(rv)) {
1602 jobject param = nsnull;
1603 if (aParams && !paramInfo.IsRetval()) {
1604 param = env->GetObjectArrayElement(aParams, i);
1605 }
1606 rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, 0, 0,
1607 PR_FALSE, 0, params[i]);
1608 }
1609 } else {
1610 LOG(("out/retval\n"));
1611 params[i].ptr = &(params[i].val);
1612 params[i].SetPtrIsData();
1613 }
1614 }
1615
1616 // Handle any dependent params by doing a second pass
1617 if (foundDependentParam) {
1618
1619 for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++) {
1620
1621 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
1622 params[j].type = paramInfo.GetType();
1623
1624 if (!params[j].type.IsDependent())
1625 continue;
1626
1627 if (paramInfo.IsIn()) {
1628 PRUint8 type = params[j].type.TagPart();
1629
1630 // is paramater an array or sized string?
1631 PRUint8 arrayType = 0;
1632 PRUint32 arraySize = 0;
1633 PRBool isArray = params[j].type.IsArray();
1634 PRBool isSizedString = isArray ? PR_FALSE :
1635 type == nsXPTType::T_PSTRING_SIZE_IS ||
1636 type == nsXPTType::T_PWSTRING_SIZE_IS;
1637
1638 if (isArray) {
1639 // get array type
1640 nsXPTType xpttype;
1641 rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &xpttype);
1642 if (NS_FAILED(rv))
1643 break;
1644 arrayType = xpttype.TagPart();
1645 // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
1646 // therefore, treat as a signed 8bit value
1647 if (arrayType == nsXPTType::T_U8)
1648 arrayType = nsXPTType::T_I8;
1649 }
1650
1651 if (isArray || isSizedString) {
1652 // get size of array or string
1653 PRUint8 argnum;
1654 rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
1655 &argnum);
1656 if (NS_FAILED(rv))
1657 break;
1658 arraySize = params[argnum].val.u32;
1659 }
1660
1661 // get IID for interface params
1662 nsID iid;
1663 if (type == nsXPTType::T_INTERFACE_IS ||
1664 (type == nsXPTType::T_ARRAY &&
1665 (arrayType == nsXPTType::T_INTERFACE ||
1666 arrayType == nsXPTType::T_INTERFACE_IS)))
1667 {
1668 PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
1669 rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
1670 methodIndex, params, PR_TRUE, iid);
1671 }
1672
1673 if (NS_SUCCEEDED(rv)) {
1674 jobject param = nsnull;
1675 if (aParams && !paramInfo.IsRetval()) {
1676 param = env->GetObjectArrayElement(aParams, j);
1677 }
1678 rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, arrayType,
1679 arraySize, PR_FALSE, 0, params[j]);
1680 }
1681 }
1682 }
1683 }
1684
1685 if (NS_FAILED(rv)) {
1686 ThrowException(env, rv, "SetupParams failed");
1687 return nsnull;
1688 }
1689 }
1690
1691 // Call the XPCOM method
1692 const nsIID* iid;
1693 iinfo->GetIIDShared(&iid);
1694 nsISupports* realObject;
1695 rv = inst->GetInstance()->QueryInterface(*iid, (void**) &realObject);
1696 if (NS_FAILED(rv)) {
1697 ThrowException(env, rv, "Failed to get real XPCOM object");
1698 return nsnull;
1699 }
1700 nsresult invokeResult = NS_InvokeByIndex(realObject, methodIndex,
1701 paramCount, params);
1702 NS_RELEASE(realObject);
1703
1704 // Clean up params
1705 jobject result = nsnull;
1706 for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
1707 {
1708 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
1709 PRUint8 type = paramInfo.GetType().TagPart();
1710
1711 // is paramater an array or sized string?
1712 PRUint8 arrayType = 0;
1713 PRUint32 arraySize = 0;
1714 PRBool isArray = params[i].type.IsArray();
1715 PRBool isSizedString = isArray ? PR_FALSE :
1716 type == nsXPTType::T_PSTRING_SIZE_IS ||
1717 type == nsXPTType::T_PWSTRING_SIZE_IS;
1718
1719 if (isArray) {
1720 // get array type
1721 nsXPTType array_xpttype;
1722 rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &array_xpttype);
1723 if (NS_FAILED(rv))
1724 break;
1725 arrayType = array_xpttype.TagPart();
1726 // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
1727 // therefore, treat as a signed 8bit value
1728 if (arrayType == nsXPTType::T_U8)
1729 arrayType = nsXPTType::T_I8;
1730 }
1731
1732 if (isArray || isSizedString) {
1733 // get size of array
1734 PRUint8 argnum;
1735 rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
1736 &argnum);
1737 if (NS_FAILED(rv))
1738 break;
1739 arraySize = params[argnum].val.u32;
1740 }
1741
1742 // get IID for interface params
1743 nsID iid;
1744 if (type == nsXPTType::T_INTERFACE || type == nsXPTType::T_INTERFACE_IS ||
1745 (type == nsXPTType::T_ARRAY && (arrayType == nsXPTType::T_INTERFACE ||
1746 arrayType == nsXPTType::T_INTERFACE_IS)))
1747 {
1748 PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
1749 rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
1750 methodIndex, params, PR_TRUE, iid);
1751 if (NS_FAILED(rv))
1752 break;
1753 }
1754
1755 jobject* javaElement;
1756 if (!paramInfo.IsRetval()) {
1757 jobject element = env->GetObjectArrayElement(aParams, i);
1758 javaElement = &element;
1759 } else {
1760 javaElement = &result;
1761 }
1762 rv = FinalizeParams(env, paramInfo, type, params[i], iid, PR_FALSE,
1763 arrayType, arraySize, 0, invokeResult, javaElement);
1764 }
1765
1766 // Normally, we would delete any created nsID object in the above loop.
1767 // However, GetIIDForMethodParam may need some of the nsID params when it's
1768 // looking for the IID of an INTERFACE_IS. Therefore, we can't delete it
1769 // until we've gone through the 'Finalize' loop once and created the result.
1770 for (PRUint8 j = 0; j < paramCount; j++)
1771 {
1772 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
1773 const nsXPTType &type = paramInfo.GetType();
1774 if (type.TagPart() == nsXPTType::T_IID) {
1775 nsID* iid = (nsID*) params[j].val.p;
1776 delete iid;
1777 }
1778 }
1779
1780 if (params) {
1781 delete params;
1782 }
1783
1784 // If the XPCOM method invocation failed, we don't immediately throw an
1785 // exception and return so that we can clean up any parameters.
1786 if (NS_FAILED(invokeResult)) {
1787 nsCAutoString message("The function \"");
1788 message.AppendASCII(methodInfo->GetName());
1789 message.AppendLiteral("\" returned an error condition");
1790#ifdef VBOX
1791 char vboxMsg[1024];
1792 message.AppendLiteral(": \"");
1793 makeErrorMessage(invokeResult, vboxMsg, sizeof vboxMsg);
1794 message.AppendASCII(vboxMsg);
1795 message.AppendLiteral("\"");
1796#endif
1797 ThrowException(env, invokeResult, message.get());
1798 }
1799 if (NS_FAILED(rv)) {
1800 ThrowException(env, rv, "FinalizeParams failed");
1801 return nsnull;
1802 }
1803
1804 LOG(("<=== (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
1805 return result;
1806}
1807
1808nsresult
1809GetNewOrUsedJavaWrapper(JNIEnv* env, nsISupports* aXPCOMObject,
1810 const nsIID& aIID, jobject aObjectLoader,
1811 jobject* aResult)
1812{
1813 NS_PRECONDITION(aResult != nsnull, "null ptr");
1814 if (!aResult)
1815 return NS_ERROR_NULL_POINTER;
1816
1817 // Get the root nsISupports of the xpcom object
1818 nsresult rv;
1819 nsCOMPtr<nsISupports> rootObject = do_QueryInterface(aXPCOMObject, &rv);
1820 NS_ENSURE_SUCCESS(rv, rv);
1821
1822 // Get associated Java object from hash table
1823 rv = gNativeToJavaProxyMap->Find(env, rootObject, aIID, aResult);
1824 NS_ENSURE_SUCCESS(rv, rv);
1825 if (*aResult)
1826 return NS_OK;
1827
1828 // No Java object is associated with the given XPCOM object, so we
1829 // create a Java proxy.
1830
1831 nsCOMPtr<nsIInterfaceInfoManager>
1832 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
1833 NS_ASSERTION(iim, "Failed to get InterfaceInfoManager");
1834 if (!iim)
1835 return NS_ERROR_FAILURE;
1836
1837 // Get interface info for class
1838 nsCOMPtr<nsIInterfaceInfo> info;
1839 rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
1840 if (NS_FAILED(rv))
1841 return rv;
1842
1843 // Wrap XPCOM object (addrefs rootObject)
1844 JavaXPCOMInstance* inst = new JavaXPCOMInstance(rootObject, info);
1845 if (!inst)
1846 return NS_ERROR_OUT_OF_MEMORY;
1847
1848 // Get interface name
1849 const char* iface_name;
1850 rv = info->GetNameShared(&iface_name);
1851
1852 if (NS_SUCCEEDED(rv)) {
1853 jobject java_obj = nsnull;
1854
1855 // Create proper Java interface name
1856 nsCAutoString class_name("org.mozilla.interfaces.");
1857 class_name.AppendASCII(iface_name);
1858 jclass ifaceClass = FindClassInLoader(env, aObjectLoader, class_name.get());
1859
1860 if (ifaceClass) {
1861 java_obj = env->CallStaticObjectMethod(xpcomJavaProxyClass,
1862 createProxyMID, ifaceClass,
1863 reinterpret_cast<jlong>(inst));
1864 if (env->ExceptionCheck())
1865 java_obj = nsnull;
1866 }
1867
1868 if (java_obj) {
1869#ifdef DEBUG_JAVAXPCOM
1870 char* iid_str = aIID.ToString();
1871 LOG(("+ CreateJavaProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
1872 (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
1873 java_obj),
1874 (PRUint32) rootObject, iid_str));
1875 PR_Free(iid_str);
1876#endif
1877
1878 // Associate XPCOM object with Java proxy
1879 rv = gNativeToJavaProxyMap->Add(env, rootObject, aIID, java_obj);
1880 if (NS_SUCCEEDED(rv)) {
1881 *aResult = java_obj;
1882 return NS_OK;
1883 }
1884 } else {
1885 rv = NS_ERROR_FAILURE;
1886 }
1887 }
1888
1889 // If there was an error, clean up.
1890 delete inst;
1891 return rv;
1892}
1893
1894nsresult
1895GetXPCOMInstFromProxy(JNIEnv* env, jobject aJavaObject, void** aResult)
1896{
1897 NS_PRECONDITION(aResult != nsnull, "null ptr");
1898 if (!aResult)
1899 return NS_ERROR_NULL_POINTER;
1900
1901 jlong xpcom_obj = env->CallStaticLongMethod(xpcomJavaProxyClass,
1902 getNativeXPCOMInstMID, aJavaObject);
1903
1904 if (!xpcom_obj || env->ExceptionCheck()) {
1905 return NS_ERROR_FAILURE;
1906 }
1907
1908 *aResult = reinterpret_cast<void*>(xpcom_obj);
1909#ifdef DEBUG_JAVAXPCOM
1910 JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(*aResult);
1911 nsIID* iid;
1912 inst->InterfaceInfo()->GetInterfaceIID(&iid);
1913 char* iid_str = iid->ToString();
1914 LOG(("< GetXPCOMInstFromProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
1915 (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
1916 aJavaObject),
1917 (PRUint32) inst->GetInstance(), iid_str));
1918 PR_Free(iid_str);
1919 nsMemory::Free(iid);
1920#endif
1921 return NS_OK;
1922}
1923
1924/**
1925 * org.mozilla.xpcom.internal.XPCOMJavaProxy.finalizeProxy
1926 */
1927extern "C" NS_EXPORT void JNICALL
1928JAVAPROXY_NATIVE(finalizeProxy) (JNIEnv *env, jclass that, jobject aJavaProxy)
1929{
1930#ifdef DEBUG_JAVAXPCOM
1931 PRUint32 xpcom_addr = 0;
1932#endif
1933
1934 // Due to Java's garbage collection, this finalize statement may get called
1935 // after FreeJavaGlobals(). So check to make sure that everything is still
1936 // initialized.
1937 if (gJavaXPCOMLock) {
1938 nsAutoLock lock(gJavaXPCOMLock);
1939
1940 // If may be possible for the lock to be acquired here when FreeGlobals is
1941 // in the middle of running. If so, then this thread will sleep until
1942 // FreeGlobals releases its lock. At that point, we resume this thread
1943 // here, but JavaXPCOM may no longer be initialized. So we need to check
1944 // that everything is legit after acquiring the lock.
1945 if (gJavaXPCOMInitialized) {
1946 // Get native XPCOM instance
1947 void* xpcom_obj;
1948 nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
1949 if (NS_SUCCEEDED(rv)) {
1950 JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(xpcom_obj);
1951#ifdef DEBUG_JAVAXPCOM
1952 xpcom_addr = reinterpret_cast<PRUint32>(inst->GetInstance());
1953#endif
1954 nsIID* iid;
1955 rv = inst->InterfaceInfo()->GetInterfaceIID(&iid);
1956 if (NS_SUCCEEDED(rv)) {
1957 rv = gNativeToJavaProxyMap->Remove(env, inst->GetInstance(), *iid);
1958 nsMemory::Free(iid);
1959 }
1960 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to RemoveJavaProxy");
1961 // Release gJavaXPCOMLock before deleting inst (see bug 340022)
1962 lock.unlock();
1963 delete inst;
1964 }
1965 }
1966 }
1967
1968#ifdef DEBUG_JAVAXPCOM
1969 LOG(("- Finalize (Java=%08x | XPCOM=%08x)\n",
1970 (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
1971 aJavaProxy),
1972 xpcom_addr));
1973#endif
1974}
1975
1976/**
1977 * org.mozilla.xpcom.XPCOMJavaProxy.isSameXPCOMObject
1978 */
1979extern "C" NS_EXPORT jboolean JNICALL
1980JAVAPROXY_NATIVE(isSameXPCOMObject) (JNIEnv *env, jclass that,
1981 jobject aProxy1, jobject aProxy2)
1982{
1983 void* xpcom_obj1;
1984 nsresult rv = GetXPCOMInstFromProxy(env, aProxy1, &xpcom_obj1);
1985 if (NS_SUCCEEDED(rv)) {
1986 void* xpcom_obj2;
1987 rv = GetXPCOMInstFromProxy(env, aProxy2, &xpcom_obj2);
1988 if (NS_SUCCEEDED(rv)) {
1989 JavaXPCOMInstance* inst1 = static_cast<JavaXPCOMInstance*>(xpcom_obj1);
1990 JavaXPCOMInstance* inst2 = static_cast<JavaXPCOMInstance*>(xpcom_obj2);
1991 if (inst1->GetInstance() == inst2->GetInstance()) {
1992 return JNI_TRUE;
1993 }
1994 }
1995 }
1996 return JNI_FALSE;
1997}
1998
1999/**
2000 * org.mozilla.xpcom.ProfileLock.release
2001 */
2002extern "C" NS_EXPORT void JNICALL
2003LOCKPROXY_NATIVE(release) (JNIEnv *env, jclass that, jlong aLockObject)
2004{
2005 // Need to release object on the main thread.
2006 nsresult rv = NS_ERROR_FAILURE;
2007#ifdef VBOX
2008 rv = NS_ProxyRelease(do_GetMainThreadQueue().get(), reinterpret_cast<nsISupports*>(aLockObject));
2009#else
2010 nsCOMPtr<nsIThread> thread = do_GetMainThread();
2011 if (thread) {
2012 rv = NS_ProxyRelease(thread, reinterpret_cast<nsISupports*>(aLockObject));
2013 }
2014#endif
2015 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease");
2016}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette