VirtualBox

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

Last change on this file since 102013 was 102013, checked in by vboxsync, 15 months ago

libs/xpcom/java: Remove unused code, bugref:10545

  • 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 NS_ENSURE_TRUE(xpcom_obj, NS_ERROR_FAILURE);
761 nsISupports *xpcom_nat_obj = (nsISupports*) xpcom_obj;
762 rv = xpcom_nat_obj->QueryInterface(iid, &xpcom_obj);
763 NS_IF_RELEASE(xpcom_nat_obj);
764 if (NS_FAILED(rv))
765 break;
766
767 // If the function expects a weak reference, then we need to
768 // create it here.
769 if (isWeakRef) {
770 nsISupports* isupports = (nsISupports*) xpcom_obj;
771 nsCOMPtr<nsISupportsWeakReference> supportsweak =
772 do_QueryInterface(isupports);
773 if (supportsweak) {
774 nsWeakPtr weakref;
775 supportsweak->GetWeakReference(getter_AddRefs(weakref));
776 NS_RELEASE(isupports);
777 xpcom_obj = weakref;
778 NS_ADDREF((nsISupports*) xpcom_obj);
779 } else {
780 xpcom_obj = nsnull;
781 }
782 }
783 } else {
784 xpcom_obj = nsnull;
785 }
786
787 if (!aIsArrayElement) { // 'in' & 'inout'
788 aVariant.val.p = xpcom_obj;
789 aVariant.SetValIsInterface();
790 if (aIsOut) { // 'inout'
791 aVariant.ptr = &aVariant.val;
792 aVariant.SetPtrIsData();
793 }
794 } else { // 'array'
795 static_cast<void**>(aVariant.val.p)[aIndex] = xpcom_obj;
796 }
797 break;
798 }
799
800 case nsXPTType::T_ASTRING:
801 case nsXPTType::T_DOMSTRING:
802 {
803 LOG(("String\n"));
804 // Expecting only 'in' and 'in dipper'
805 NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
806 if (aIsOut) {
807 rv = NS_ERROR_UNEXPECTED;
808 break;
809 }
810
811 jstring jstr = static_cast<jstring>(aParam);
812 nsAString* str = jstring_to_nsAString(env, jstr);
813 if (!str) {
814 rv = NS_ERROR_OUT_OF_MEMORY;
815 break;
816 }
817
818 aVariant.val.p = str;
819 aVariant.SetValIsDOMString();
820 break;
821 }
822
823 case nsXPTType::T_UTF8STRING:
824 case nsXPTType::T_CSTRING:
825 {
826 LOG(("StringUTF\n"));
827 // Expecting only 'in' and 'in dipper'
828 NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
829 if (aIsOut) {
830 rv = NS_ERROR_UNEXPECTED;
831 break;
832 }
833
834 jstring jstr = static_cast<jstring>(aParam);
835 nsACString* str = jstring_to_nsACString(env, jstr);
836 if (!str) {
837 rv = NS_ERROR_OUT_OF_MEMORY;
838 break;
839 }
840
841 aVariant.val.p = str;
842 if (aType == nsXPTType::T_CSTRING) {
843 aVariant.SetValIsCString();
844 } else {
845 aVariant.SetValIsUTF8String();
846 }
847 break;
848 }
849
850 // handle "void *" as an "long" in Java
851 case nsXPTType::T_VOID:
852 {
853 LOG(("long (void*)\n"));
854 if (!aIsOut && !aIsArrayElement) { // 'in'
855 aVariant.val.p =
856 reinterpret_cast<void*>(env->CallLongMethod(aParam, longValueMID));
857 } else { // 'inout' & 'array'
858 jlong value;
859 if (aParam) {
860 env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);
861 }
862
863 if (aIsOut) { // 'inout'
864 if (aParam) {
865 aVariant.val.p = reinterpret_cast<void*>(value);
866 aVariant.ptr = &aVariant.val;
867 } else {
868 aVariant.ptr = nsnull;
869 }
870 aVariant.SetPtrIsData();
871 } else { // 'array'
872 static_cast<void**>(aVariant.val.p)[aIndex] =
873 reinterpret_cast<void*>(value);
874 }
875 }
876 break;
877 }
878
879 case nsXPTType::T_ARRAY:
880 {
881 jobject sourceArray = nsnull;
882 if (!aIsOut) { // 'in'
883 sourceArray = aParam;
884 } else if (aParam) { // 'inout'
885 jobjectArray array = static_cast<jobjectArray>(aParam);
886 sourceArray = env->GetObjectArrayElement(array, 0);
887 }
888
889 if (sourceArray) {
890 rv = CreateNativeArray(aArrayType, aArraySize, &aVariant.val.p);
891
892 for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
893 rv = SetupParams(env, sourceArray, aArrayType, PR_FALSE, aIID, 0, 0,
894 PR_TRUE, i, aVariant);
895 }
896 }
897
898 if (aIsOut) { // 'inout'
899 aVariant.ptr = &aVariant.val.p;
900 aVariant.SetPtrIsData();
901 }
902 break;
903 }
904
905 case nsXPTType::T_PSTRING_SIZE_IS:
906 case nsXPTType::T_PWSTRING_SIZE_IS:
907 {
908 NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
909
910 LOG(("Sized string\n"));
911 jstring data = nsnull;
912 if (!aIsOut) { // 'in'
913 data = (jstring) aParam;
914 } else if (aParam) { // 'inout'
915 data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
916 aIndex);
917 }
918
919 PRUint32 length = 0;
920 if (data) {
921 if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
922 length = env->GetStringUTFLength(data);
923 } else {
924 length = env->GetStringLength(data);
925 }
926 if (length > aArraySize) {
927 rv = NS_ERROR_ILLEGAL_VALUE;
928 break;
929 }
930 }
931
932 PRUint32 size_of_char = (aType == nsXPTType::T_PSTRING_SIZE_IS) ?
933 sizeof(char) : sizeof(jchar);
934 PRUint32 allocLength = (aArraySize + 1) * size_of_char;
935 void* buf = nsMemory::Alloc(allocLength);
936 if (!buf) {
937 rv = NS_ERROR_OUT_OF_MEMORY;
938 break;
939 }
940
941 if (data) {
942 if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
943 const char* str = env->GetStringUTFChars(data, nsnull);
944 if (!str) {
945 nsMemory::Free(buf);
946 rv = NS_ERROR_OUT_OF_MEMORY;
947 break;
948 }
949 memcpy(buf, str, length);
950 env->ReleaseStringUTFChars(data, str);
951 } else {
952 jchar* jchar_str = static_cast<jchar*>(buf);
953 env->GetStringRegion(data, 0, length, jchar_str);
954 }
955 }
956
957 aVariant.val.p = buf;
958 if (aIsOut) { // 'inout'
959 aVariant.ptr = &aVariant.val;
960 aVariant.SetPtrIsData();
961 }
962
963 break;
964 }
965
966 default:
967 NS_WARNING("unexpected parameter type");
968 return NS_ERROR_UNEXPECTED;
969 }
970
971 return rv;
972}
973
974/**
975 * Does any cleanup from objects created in SetupParams, as well as converting
976 * any out params to Java.
977 *
978 * NOTE: If aInvokeResult is an error condition, then we just do cleanup in
979 * this function.
980 */
981nsresult
982FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,
983 nsXPTCVariant &aVariant, const nsID& aIID,
984 PRBool aIsArrayElement, PRUint8 aArrayType, PRUint32 aArraySize,
985 PRUint32 aIndex, nsresult aInvokeResult, jobject* aParam)
986{
987 nsresult rv = NS_OK;
988
989 switch (aType)
990 {
991 case nsXPTType::T_I8:
992 {
993 if (NS_SUCCEEDED(aInvokeResult)) {
994 jbyte value = aVariant.val.i8;
995 if (aParamInfo.IsRetval() && !aIsArrayElement) {
996 *aParam = env->NewObject(byteClass, byteInitMID, value);
997 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
998 env->SetByteArrayRegion((jbyteArray) *aParam, aIndex, 1, &value);
999 }
1000 }
1001 break;
1002 }
1003
1004 case nsXPTType::T_I16:
1005 case nsXPTType::T_U8:
1006 {
1007 if (NS_SUCCEEDED(aInvokeResult)) {
1008 jshort value = (aType == nsXPTType::T_I16) ? aVariant.val.i16 :
1009 aVariant.val.u8;
1010 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1011 *aParam = env->NewObject(shortClass, shortInitMID, value);
1012 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1013 env->SetShortArrayRegion((jshortArray) *aParam, aIndex, 1, &value);
1014 }
1015 }
1016 break;
1017 }
1018
1019 case nsXPTType::T_I32:
1020 case nsXPTType::T_U16:
1021 {
1022 if (NS_SUCCEEDED(aInvokeResult)) {
1023 jint value = (aType == nsXPTType::T_I32) ? aVariant.val.i32 :
1024 aVariant.val.u16;
1025 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1026 *aParam = env->NewObject(intClass, intInitMID, value);
1027 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1028 env->SetIntArrayRegion((jintArray) *aParam, aIndex, 1, &value);
1029 }
1030 }
1031 break;
1032 }
1033
1034 case nsXPTType::T_I64:
1035 case nsXPTType::T_U32:
1036 {
1037 if (NS_SUCCEEDED(aInvokeResult)) {
1038 jlong value = (aType == nsXPTType::T_I64) ? aVariant.val.i64 :
1039 aVariant.val.u32;
1040 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1041 *aParam = env->NewObject(longClass, longInitMID, value);
1042 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1043 env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
1044 }
1045 }
1046 break;
1047 }
1048
1049 case nsXPTType::T_FLOAT:
1050 {
1051 if (NS_SUCCEEDED(aInvokeResult)) {
1052 jfloat value = aVariant.val.f;
1053 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1054 *aParam = env->NewObject(floatClass, floatInitMID, value);
1055 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1056 env->SetFloatArrayRegion((jfloatArray) *aParam, aIndex, 1, &value);
1057 }
1058 }
1059 break;
1060 }
1061
1062 // XXX how do we handle unsigned 64-bit values?
1063 case nsXPTType::T_U64:
1064 case nsXPTType::T_DOUBLE:
1065 {
1066 if (NS_SUCCEEDED(aInvokeResult)) {
1067 jdouble value = (aType == nsXPTType::T_DOUBLE) ? aVariant.val.d :
1068 aVariant.val.u64;
1069 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1070 *aParam = env->NewObject(doubleClass, doubleInitMID, value);
1071 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1072 env->SetDoubleArrayRegion((jdoubleArray) *aParam, aIndex, 1, &value);
1073 }
1074 }
1075 break;
1076 }
1077
1078 case nsXPTType::T_BOOL:
1079 {
1080 if (NS_SUCCEEDED(aInvokeResult)) {
1081 jboolean value = aVariant.val.b;
1082 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1083 *aParam = env->NewObject(booleanClass, booleanInitMID, value);
1084 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1085 env->SetBooleanArrayRegion((jbooleanArray) *aParam, aIndex, 1, &value);
1086 }
1087 }
1088 break;
1089 }
1090
1091 case nsXPTType::T_CHAR:
1092 case nsXPTType::T_WCHAR:
1093 {
1094 if (NS_SUCCEEDED(aInvokeResult)) {
1095 jchar value;
1096 if (aType == nsXPTType::T_CHAR)
1097 value = aVariant.val.c;
1098 else
1099 value = aVariant.val.wc;
1100 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1101 *aParam = env->NewObject(charClass, charInitMID, value);
1102 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1103 env->SetCharArrayRegion((jcharArray) *aParam, aIndex, 1, &value);
1104 }
1105 }
1106 break;
1107 }
1108
1109 case nsXPTType::T_CHAR_STR:
1110 case nsXPTType::T_WCHAR_STR:
1111 {
1112 if ((aParamInfo.IsOut() || aIsArrayElement) &&
1113 NS_SUCCEEDED(aInvokeResult))
1114 {
1115 // create new string from data
1116 jstring str = nsnull;
1117 if (aVariant.val.p) {
1118 if (aType == nsXPTType::T_CHAR_STR) {
1119 str = env->NewStringUTF((const char*) aVariant.val.p);
1120 } else {
1121 PRUint32 length = nsCRT::strlen((const PRUnichar*) aVariant.val.p);
1122 str = env->NewString((const jchar*) aVariant.val.p, length);
1123 }
1124 if (!str) {
1125 rv = NS_ERROR_OUT_OF_MEMORY;
1126 break;
1127 }
1128 }
1129
1130 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1131 *aParam = str;
1132 } else if (*aParam) {
1133 // put new string into output array
1134 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
1135 }
1136 }
1137
1138 // cleanup
1139 if (aVariant.val.p)
1140 nsMemory::Free(aVariant.val.p);
1141 break;
1142 }
1143
1144 case nsXPTType::T_IID:
1145 {
1146 nsID* iid = static_cast<nsID*>(aVariant.val.p);
1147
1148 if ((aParamInfo.IsOut() || aIsArrayElement) &&
1149 NS_SUCCEEDED(aInvokeResult))
1150 {
1151 // Create the string from nsID
1152 jstring str = nsnull;
1153 if (iid) {
1154 char iid_str[NSID_LENGTH];
1155 iid->ToProvidedString(iid_str);
1156 str = env->NewStringUTF(iid_str);
1157 if (!str) {
1158 rv = NS_ERROR_OUT_OF_MEMORY;
1159 break;
1160 }
1161 }
1162
1163 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1164 *aParam = str;
1165 } else if (*aParam) {
1166 // put new string into output array
1167 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
1168 }
1169 }
1170
1171 // Ordinarily, we would delete 'iid' here. But we cannot do that until
1172 // we've handled all of the params. See comment in CallXPCOMMethod.
1173 // We can safely delete array elements, though.
1174 if (aIsArrayElement)
1175 delete iid;
1176
1177 break;
1178 }
1179
1180 case nsXPTType::T_INTERFACE:
1181 case nsXPTType::T_INTERFACE_IS:
1182 {
1183 nsISupports* xpcom_obj = static_cast<nsISupports*>(aVariant.val.p);
1184
1185 if ((aParamInfo.IsOut() || aIsArrayElement) &&
1186 NS_SUCCEEDED(aInvokeResult))
1187 {
1188 jobject java_obj = nsnull;
1189 if (xpcom_obj) {
1190 // Get matching Java object for given xpcom object
1191 rv = NativeInterfaceToJavaObject(env, xpcom_obj, aIID, nsnull,
1192 &java_obj);
1193 if (NS_FAILED(rv))
1194 break;
1195 }
1196
1197 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1198 *aParam = java_obj;
1199 } else if (*aParam) {
1200 // put new Java object into output array
1201 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, java_obj);
1202 }
1203 }
1204
1205 // cleanup
1206 NS_IF_RELEASE(xpcom_obj);
1207 break;
1208 }
1209
1210 case nsXPTType::T_ASTRING:
1211 case nsXPTType::T_DOMSTRING:
1212 {
1213 NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
1214 if (!aParamInfo.IsIn()) {
1215 rv = NS_ERROR_UNEXPECTED;
1216 break;
1217 }
1218
1219 nsString* str = static_cast<nsString*>(aVariant.val.p);
1220 if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
1221 // Create Java string from returned nsString
1222 jstring jstr = nsnull;
1223 if (str && !str->IsVoid()) {
1224 jstr = env->NewString((const jchar*) str->get(), str->Length());
1225 if (!jstr) {
1226 rv = NS_ERROR_OUT_OF_MEMORY;
1227 break;
1228 }
1229 }
1230
1231 *aParam = jstr;
1232 }
1233
1234 // cleanup
1235 if (str) {
1236 delete str;
1237 }
1238 break;
1239 }
1240
1241 case nsXPTType::T_UTF8STRING:
1242 case nsXPTType::T_CSTRING:
1243 {
1244 NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
1245 if (!aParamInfo.IsIn()) {
1246 rv = NS_ERROR_UNEXPECTED;
1247 break;
1248 }
1249
1250 nsCString* str = static_cast<nsCString*>(aVariant.val.p);
1251 if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
1252 // Create Java string from returned nsString
1253 jstring jstr = nsnull;
1254 if (str && !str->IsVoid()) {
1255 jstr = env->NewStringUTF((const char*) str->get());
1256 if (!jstr) {
1257 rv = NS_ERROR_OUT_OF_MEMORY;
1258 break;
1259 }
1260 }
1261
1262 *aParam = jstr;
1263 }
1264
1265 // cleanup
1266 if (str) {
1267 delete str;
1268 }
1269 break;
1270 }
1271
1272 case nsXPTType::T_VOID:
1273 {
1274 if (NS_SUCCEEDED(aInvokeResult)) {
1275 jlong value = reinterpret_cast<jlong>(aVariant.val.p);
1276 if (aParamInfo.IsRetval() && !aIsArrayElement) {
1277 *aParam = env->NewObject(longClass, longInitMID, value);
1278 } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
1279 env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
1280 }
1281 }
1282 break;
1283 }
1284
1285 case nsXPTType::T_ARRAY:
1286 {
1287 if (aParamInfo.IsOut() && NS_SUCCEEDED(aInvokeResult)) {
1288 // Create Java array from returned native array
1289 jobject jarray = nsnull;
1290 if (aVariant.val.p) {
1291 rv = CreateJavaArray(env, aArrayType, aArraySize, aIID, &jarray);
1292 if (NS_FAILED(rv))
1293 break;
1294
1295 nsXPTCVariant var;
1296 for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
1297 rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
1298 if (NS_SUCCEEDED(rv)) {
1299 rv = FinalizeParams(env, aParamInfo, aArrayType, var, aIID,
1300 PR_TRUE, 0, 0, i, aInvokeResult, &jarray);
1301 }
1302 }
1303 }
1304
1305 if (aParamInfo.IsRetval()) {
1306 *aParam = jarray;
1307 } else if (*aParam) {
1308 // put new Java array into output array
1309 env->SetObjectArrayElement((jobjectArray) *aParam, 0, jarray);
1310 }
1311 }
1312
1313 // cleanup
1314 // If this is not an out param or if the invokeResult is a failure case,
1315 // then the array elements have not been cleaned up. Do so now.
1316 if (!aParamInfo.IsOut() || (NS_FAILED(aInvokeResult) && aVariant.val.p)) {
1317 nsXPTCVariant var;
1318 for (PRUint32 i = 0; i < aArraySize; i++) {
1319 rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
1320 if (NS_SUCCEEDED(rv)) {
1321 FinalizeParams(env, aParamInfo, aArrayType, var, aIID, PR_TRUE,
1322 0, 0, i, NS_ERROR_FAILURE, nsnull);
1323 }
1324 }
1325 }
1326 PR_Free(aVariant.val.p);
1327 break;
1328 }
1329
1330 case nsXPTType::T_PSTRING_SIZE_IS:
1331 case nsXPTType::T_PWSTRING_SIZE_IS:
1332 {
1333 NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
1334
1335 if ((aParamInfo.IsOut()) && NS_SUCCEEDED(aInvokeResult))
1336 {
1337 // create new string from data
1338 jstring str = nsnull;
1339 if (aVariant.val.p) {
1340 if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
1341 PRUint32 len = (aArraySize + 1) * sizeof(char);
1342 char* buf = (char*) nsMemory::Alloc(len);
1343 if (buf) {
1344 memcpy(buf, aVariant.val.p, len);
1345 buf[aArraySize] = '\0';
1346 str = env->NewStringUTF((const char*) buf);
1347 nsMemory::Free(buf);
1348 }
1349 } else {
1350 str = env->NewString((const jchar*) aVariant.val.p, aArraySize);
1351 }
1352 if (!str) {
1353 rv = NS_ERROR_OUT_OF_MEMORY;
1354 break;
1355 }
1356 }
1357
1358 if (aParamInfo.IsRetval()) {
1359 *aParam = str;
1360 } else if (*aParam) {
1361 // put new string into output array
1362 env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
1363 }
1364 }
1365
1366 // cleanup
1367 if (aVariant.val.p)
1368 nsMemory::Free(aVariant.val.p);
1369 break;
1370 }
1371
1372 default:
1373 NS_WARNING("unexpected parameter type");
1374 return NS_ERROR_UNEXPECTED;
1375 }
1376
1377 // Check for Java exception, but don't overwrite pre-existing error code.
1378 if (NS_SUCCEEDED(rv) && env->ExceptionCheck())
1379 rv = NS_ERROR_FAILURE;
1380
1381 return rv;
1382}
1383
1384nsresult
1385QueryAttributeInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
1386 PRBool aCapitalizedAttr, PRUint16* aMethodIndex,
1387 const nsXPTMethodInfo** aMethodInfo)
1388
1389{
1390 nsresult rv = NS_ERROR_FAILURE;
1391
1392 // An 'attribute' will start with either "get" or "set". But first,
1393 // we check the length, in order to skip over method names that match exactly
1394 // "get" or "set".
1395 if (strlen(aMethodName) > 3) {
1396 if (strncmp("get", aMethodName, 3) == 0) {
1397 char* getterName = strdup(aMethodName + 3);
1398 if (!aCapitalizedAttr) {
1399 getterName[0] = tolower(getterName[0]);
1400 }
1401 rv = aIInfo->GetMethodInfoForName(getterName, aMethodIndex, aMethodInfo);
1402 free(getterName);
1403 } else if (strncmp("set", aMethodName, 3) == 0) {
1404 char* setterName = strdup(aMethodName + 3);
1405 if (!aCapitalizedAttr) {
1406 setterName[0] = tolower(setterName[0]);
1407 }
1408 rv = aIInfo->GetMethodInfoForName(setterName, aMethodIndex, aMethodInfo);
1409 if (NS_SUCCEEDED(rv)) {
1410 // If this succeeded, GetMethodInfoForName will have returned the
1411 // method info for the 'getter'. We want the 'setter', so increase
1412 // method index by one ('setter' immediately follows the 'getter'),
1413 // and get its method info.
1414 (*aMethodIndex)++;
1415 rv = aIInfo->GetMethodInfo(*aMethodIndex, aMethodInfo);
1416 if (NS_SUCCEEDED(rv)) {
1417 // Double check that this methodInfo matches the given method.
1418 if (!(*aMethodInfo)->IsSetter() ||
1419 strcmp(setterName, (*aMethodInfo)->name) != 0) {
1420 rv = NS_ERROR_FAILURE;
1421 }
1422 }
1423 }
1424 free(setterName);
1425 }
1426 }
1427
1428 return rv;
1429}
1430
1431/**
1432 * Given an interface info struct and a method name, returns the method info
1433 * and index, if that method exists.
1434 *
1435 * Most method names are lower case. Unfortunately, the method names of some
1436 * interfaces (such as nsIAppShell) start with a capital letter. This function
1437 * will try all of the permutations.
1438 */
1439nsresult
1440QueryMethodInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
1441 PRUint16* aMethodIndex, const nsXPTMethodInfo** aMethodInfo)
1442{
1443 // Skip over any leading underscores, since these are methods that conflicted
1444 // with existing Java keywords
1445 const char* methodName = aMethodName;
1446 if (methodName[0] == '_') {
1447 methodName++;
1448 }
1449
1450 // The common case is that the method name is lower case, so we check
1451 // that first.
1452 nsresult rv;
1453 rv = aIInfo->GetMethodInfoForName(methodName, aMethodIndex, aMethodInfo);
1454 if (NS_SUCCEEDED(rv))
1455 return rv;
1456
1457 // If there is no method called <aMethodName>, then maybe it is an
1458 // 'attribute'.
1459 rv = QueryAttributeInfo(aIInfo, methodName, PR_FALSE, aMethodIndex,
1460 aMethodInfo);
1461 if (NS_SUCCEEDED(rv))
1462 return rv;
1463
1464 // If we get here, then maybe the method name is capitalized.
1465 char* name = strdup(methodName);
1466 name[0] = toupper(name[0]);
1467 rv = aIInfo->GetMethodInfoForName(name, aMethodIndex, aMethodInfo);
1468 free(name);
1469 if (NS_SUCCEEDED(rv))
1470 return rv;
1471
1472 // If there is no method called <aMethodName>, then maybe it is an
1473 // 'attribute'.
1474 rv = QueryAttributeInfo(aIInfo, methodName, PR_TRUE, aMethodIndex,
1475 aMethodInfo);
1476
1477 return rv;
1478}
1479
1480#ifdef VBOX
1481#include <nsIExceptionService.h>
1482#include <iprt/err.h>
1483#include "nspr.h"
1484
1485static void makeErrorMessage(nsresult r, char* msg, size_t msgSize)
1486{
1487 bool gotMsg = false;
1488
1489 if (!gotMsg)
1490 {
1491 nsresult rc;
1492 nsCOMPtr <nsIExceptionService> es;
1493 es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
1494 if (NS_SUCCEEDED (rc))
1495 {
1496 nsCOMPtr <nsIExceptionManager> em;
1497 rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
1498 if (NS_SUCCEEDED (rc))
1499 {
1500 nsCOMPtr <nsIException> ex;
1501 rc = em->GetCurrentException(getter_AddRefs (ex));
1502 if (NS_SUCCEEDED (rc) && ex)
1503 {
1504 nsXPIDLCString emsg;
1505 ex->GetMessage(getter_Copies(emsg));
1506 PR_snprintf(msg, msgSize, "%s",
1507 emsg.get());
1508 gotMsg = true;
1509 }
1510 }
1511 }
1512 }
1513
1514 if (!gotMsg)
1515 {
1516 const RTCOMERRMSG* pMsg = RTErrCOMGet(r);
1517 if (strncmp(pMsg->pszMsgFull, "Unknown", 7) != 0)
1518 {
1519 PR_snprintf(msg, msgSize, "%s (%s)",
1520 pMsg->pszMsgFull, pMsg->pszDefine);
1521 gotMsg = true;
1522 }
1523 }
1524
1525 if (!gotMsg)
1526 {
1527 PR_snprintf(msg, msgSize, "Error 0x%x in module 0x%x",
1528 NS_ERROR_GET_CODE(r), NS_ERROR_GET_MODULE(r));
1529 }
1530}
1531#endif
1532
1533/**
1534 * org.mozilla.xpcom.XPCOMJavaProxy.internal.callXPCOMMethod
1535 */
1536extern "C" NS_EXPORT jobject JNICALL
1537JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
1538 jstring aMethodName, jobjectArray aParams)
1539{
1540 nsresult rv;
1541
1542 // Get native XPCOM instance
1543 void* xpcom_obj;
1544 rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
1545 if (NS_FAILED(rv)) {
1546 ThrowException(env, 0, "Failed to get matching XPCOM object");
1547 return nsnull;
1548 }
1549 JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(xpcom_obj);
1550
1551 // Get method info
1552 PRUint16 methodIndex;
1553 const nsXPTMethodInfo* methodInfo;
1554 nsIInterfaceInfo* iinfo = inst->InterfaceInfo();
1555 const char* methodName = env->GetStringUTFChars(aMethodName, nsnull);
1556 rv = QueryMethodInfo(iinfo, methodName, &methodIndex, &methodInfo);
1557 env->ReleaseStringUTFChars(aMethodName, methodName);
1558
1559 if (NS_FAILED(rv)) {
1560 ThrowException(env, rv, "GetMethodInfoForName failed");
1561 return nsnull;
1562 }
1563
1564#ifdef DEBUG_JAVAXPCOM
1565 const char* ifaceName;
1566 iinfo->GetNameShared(&ifaceName);
1567 LOG(("===> (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
1568#endif
1569
1570 // Convert the Java params
1571 PRUint8 paramCount = methodInfo->GetParamCount();
1572 nsXPTCVariant* params = nsnull;
1573 if (paramCount)
1574 {
1575 params = new nsXPTCVariant[paramCount];
1576 if (!params) {
1577 ThrowException(env, NS_ERROR_OUT_OF_MEMORY, "Can't create params array");
1578 return nsnull;
1579 }
1580 memset(params, 0, paramCount * sizeof(nsXPTCVariant));
1581
1582 PRBool foundDependentParam = PR_FALSE;
1583 for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
1584 {
1585 LOG(("\t Param %d: ", i));
1586 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
1587 params[i].type = paramInfo.GetType();
1588
1589 if (params[i].type.IsDependent() && paramInfo.IsIn()) {
1590 foundDependentParam = PR_TRUE;
1591 continue;
1592 }
1593
1594 if (paramInfo.IsIn()) {
1595 PRUint8 type = params[i].type.TagPart();
1596
1597 // get IID for interface params
1598 nsID iid;
1599 if (type == nsXPTType::T_INTERFACE) {
1600 rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
1601 methodIndex, params, PR_TRUE, iid);
1602 }
1603
1604 if (NS_SUCCEEDED(rv)) {
1605 jobject param = nsnull;
1606 if (aParams && !paramInfo.IsRetval()) {
1607 param = env->GetObjectArrayElement(aParams, i);
1608 }
1609 rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, 0, 0,
1610 PR_FALSE, 0, params[i]);
1611 }
1612 } else {
1613 LOG(("out/retval\n"));
1614 params[i].ptr = &(params[i].val);
1615 params[i].SetPtrIsData();
1616 }
1617 }
1618
1619 // Handle any dependent params by doing a second pass
1620 if (foundDependentParam) {
1621
1622 for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++) {
1623
1624 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
1625 params[j].type = paramInfo.GetType();
1626
1627 if (!params[j].type.IsDependent())
1628 continue;
1629
1630 if (paramInfo.IsIn()) {
1631 PRUint8 type = params[j].type.TagPart();
1632
1633 // is paramater an array or sized string?
1634 PRUint8 arrayType = 0;
1635 PRUint32 arraySize = 0;
1636 PRBool isArray = params[j].type.IsArray();
1637 PRBool isSizedString = isArray ? PR_FALSE :
1638 type == nsXPTType::T_PSTRING_SIZE_IS ||
1639 type == nsXPTType::T_PWSTRING_SIZE_IS;
1640
1641 if (isArray) {
1642 // get array type
1643 nsXPTType xpttype;
1644 rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &xpttype);
1645 if (NS_FAILED(rv))
1646 break;
1647 arrayType = xpttype.TagPart();
1648 // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
1649 // therefore, treat as a signed 8bit value
1650 if (arrayType == nsXPTType::T_U8)
1651 arrayType = nsXPTType::T_I8;
1652 }
1653
1654 if (isArray || isSizedString) {
1655 // get size of array or string
1656 PRUint8 argnum;
1657 rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
1658 &argnum);
1659 if (NS_FAILED(rv))
1660 break;
1661 arraySize = params[argnum].val.u32;
1662 }
1663
1664 // get IID for interface params
1665 nsID iid;
1666 if (type == nsXPTType::T_INTERFACE_IS ||
1667 (type == nsXPTType::T_ARRAY &&
1668 (arrayType == nsXPTType::T_INTERFACE ||
1669 arrayType == nsXPTType::T_INTERFACE_IS)))
1670 {
1671 PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
1672 rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
1673 methodIndex, params, PR_TRUE, iid);
1674 }
1675
1676 if (NS_SUCCEEDED(rv)) {
1677 jobject param = nsnull;
1678 if (aParams && !paramInfo.IsRetval()) {
1679 param = env->GetObjectArrayElement(aParams, j);
1680 }
1681 rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, arrayType,
1682 arraySize, PR_FALSE, 0, params[j]);
1683 }
1684 }
1685 }
1686 }
1687
1688 if (NS_FAILED(rv)) {
1689 ThrowException(env, rv, "SetupParams failed");
1690 return nsnull;
1691 }
1692 }
1693
1694 // Call the XPCOM method
1695 const nsIID* iid;
1696 iinfo->GetIIDShared(&iid);
1697 nsISupports* realObject;
1698 rv = inst->GetInstance()->QueryInterface(*iid, (void**) &realObject);
1699 if (NS_FAILED(rv)) {
1700 ThrowException(env, rv, "Failed to get real XPCOM object");
1701 return nsnull;
1702 }
1703 nsresult invokeResult = NS_InvokeByIndex(realObject, methodIndex,
1704 paramCount, params);
1705 NS_RELEASE(realObject);
1706
1707 // Clean up params
1708 jobject result = nsnull;
1709 for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
1710 {
1711 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
1712 PRUint8 type = paramInfo.GetType().TagPart();
1713
1714 // is paramater an array or sized string?
1715 PRUint8 arrayType = 0;
1716 PRUint32 arraySize = 0;
1717 PRBool isArray = params[i].type.IsArray();
1718 PRBool isSizedString = isArray ? PR_FALSE :
1719 type == nsXPTType::T_PSTRING_SIZE_IS ||
1720 type == nsXPTType::T_PWSTRING_SIZE_IS;
1721
1722 if (isArray) {
1723 // get array type
1724 nsXPTType array_xpttype;
1725 rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &array_xpttype);
1726 if (NS_FAILED(rv))
1727 break;
1728 arrayType = array_xpttype.TagPart();
1729 // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
1730 // therefore, treat as a signed 8bit value
1731 if (arrayType == nsXPTType::T_U8)
1732 arrayType = nsXPTType::T_I8;
1733 }
1734
1735 if (isArray || isSizedString) {
1736 // get size of array
1737 PRUint8 argnum;
1738 rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
1739 &argnum);
1740 if (NS_FAILED(rv))
1741 break;
1742 arraySize = params[argnum].val.u32;
1743 }
1744
1745 // get IID for interface params
1746 nsID iid;
1747 if (type == nsXPTType::T_INTERFACE || type == nsXPTType::T_INTERFACE_IS ||
1748 (type == nsXPTType::T_ARRAY && (arrayType == nsXPTType::T_INTERFACE ||
1749 arrayType == nsXPTType::T_INTERFACE_IS)))
1750 {
1751 PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
1752 rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
1753 methodIndex, params, PR_TRUE, iid);
1754 if (NS_FAILED(rv))
1755 break;
1756 }
1757
1758 jobject* javaElement;
1759 jobject element = nsnull;
1760 if (!paramInfo.IsRetval()) {
1761 element = env->GetObjectArrayElement(aParams, i);
1762 javaElement = &element;
1763 } else {
1764 javaElement = &result;
1765 }
1766 rv = FinalizeParams(env, paramInfo, type, params[i], iid, PR_FALSE,
1767 arrayType, arraySize, 0, invokeResult, javaElement);
1768 }
1769
1770 // Normally, we would delete any created nsID object in the above loop.
1771 // However, GetIIDForMethodParam may need some of the nsID params when it's
1772 // looking for the IID of an INTERFACE_IS. Therefore, we can't delete it
1773 // until we've gone through the 'Finalize' loop once and created the result.
1774 for (PRUint8 j = 0; j < paramCount; j++)
1775 {
1776 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
1777 const nsXPTType &type = paramInfo.GetType();
1778 if (type.TagPart() == nsXPTType::T_IID) {
1779 nsID* iid = (nsID*) params[j].val.p;
1780 delete iid;
1781 }
1782 }
1783
1784 if (params) {
1785 delete params;
1786 }
1787
1788 // If the XPCOM method invocation failed, we don't immediately throw an
1789 // exception and return so that we can clean up any parameters.
1790 if (NS_FAILED(invokeResult)) {
1791 nsCAutoString message("The function \"");
1792 message.AppendASCII(methodInfo->GetName());
1793 message.AppendLiteral("\" returned an error condition");
1794#ifdef VBOX
1795 char vboxMsg[1024];
1796 message.AppendLiteral(": \"");
1797 makeErrorMessage(invokeResult, vboxMsg, sizeof vboxMsg);
1798 message.AppendASCII(vboxMsg);
1799 message.AppendLiteral("\"");
1800#endif
1801 ThrowException(env, invokeResult, message.get());
1802 }
1803 if (NS_FAILED(rv)) {
1804 ThrowException(env, rv, "FinalizeParams failed");
1805 return nsnull;
1806 }
1807
1808 LOG(("<=== (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
1809 return result;
1810}
1811
1812nsresult
1813GetNewOrUsedJavaWrapper(JNIEnv* env, nsISupports* aXPCOMObject,
1814 const nsIID& aIID, jobject aObjectLoader,
1815 jobject* aResult)
1816{
1817 NS_PRECONDITION(aResult != nsnull, "null ptr");
1818 if (!aResult)
1819 return NS_ERROR_NULL_POINTER;
1820
1821 // Get the root nsISupports of the xpcom object
1822 nsresult rv;
1823 nsCOMPtr<nsISupports> rootObject = do_QueryInterface(aXPCOMObject, &rv);
1824 NS_ENSURE_SUCCESS(rv, rv);
1825
1826 // Get associated Java object from hash table
1827 rv = gNativeToJavaProxyMap->Find(env, rootObject, aIID, aResult);
1828 NS_ENSURE_SUCCESS(rv, rv);
1829 if (*aResult)
1830 return NS_OK;
1831
1832 // No Java object is associated with the given XPCOM object, so we
1833 // create a Java proxy.
1834
1835 nsCOMPtr<nsIInterfaceInfoManager>
1836 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
1837 NS_ASSERTION(iim, "Failed to get InterfaceInfoManager");
1838 if (!iim)
1839 return NS_ERROR_FAILURE;
1840
1841 // Get interface info for class
1842 nsCOMPtr<nsIInterfaceInfo> info;
1843 rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
1844 if (NS_FAILED(rv))
1845 return rv;
1846
1847 // Wrap XPCOM object (addrefs rootObject)
1848 JavaXPCOMInstance* inst = new JavaXPCOMInstance(rootObject, info);
1849 if (!inst)
1850 return NS_ERROR_OUT_OF_MEMORY;
1851
1852 // Get interface name
1853 const char* iface_name;
1854 rv = info->GetNameShared(&iface_name);
1855
1856 if (NS_SUCCEEDED(rv)) {
1857 jobject java_obj = nsnull;
1858
1859 // Create proper Java interface name
1860 nsCAutoString class_name("org.mozilla.interfaces.");
1861 class_name.AppendASCII(iface_name);
1862 jclass ifaceClass = FindClassInLoader(env, aObjectLoader, class_name.get());
1863
1864 if (ifaceClass) {
1865 java_obj = env->CallStaticObjectMethod(xpcomJavaProxyClass,
1866 createProxyMID, ifaceClass,
1867 reinterpret_cast<jlong>(inst));
1868 if (env->ExceptionCheck())
1869 java_obj = nsnull;
1870 }
1871
1872 if (java_obj) {
1873#ifdef DEBUG_JAVAXPCOM
1874 char* iid_str = aIID.ToString();
1875 LOG(("+ CreateJavaProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
1876 (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
1877 java_obj),
1878 (PRUint32) rootObject, iid_str));
1879 PR_Free(iid_str);
1880#endif
1881
1882 // Associate XPCOM object with Java proxy
1883 rv = gNativeToJavaProxyMap->Add(env, rootObject, aIID, java_obj);
1884 if (NS_SUCCEEDED(rv)) {
1885 *aResult = java_obj;
1886 return NS_OK;
1887 }
1888 } else {
1889 rv = NS_ERROR_FAILURE;
1890 }
1891 }
1892
1893 // If there was an error, clean up.
1894 delete inst;
1895 return rv;
1896}
1897
1898nsresult
1899GetXPCOMInstFromProxy(JNIEnv* env, jobject aJavaObject, void** aResult)
1900{
1901 NS_PRECONDITION(aResult != nsnull, "null ptr");
1902 if (!aResult)
1903 return NS_ERROR_NULL_POINTER;
1904
1905 jlong xpcom_obj = env->CallStaticLongMethod(xpcomJavaProxyClass,
1906 getNativeXPCOMInstMID, aJavaObject);
1907
1908 if (!xpcom_obj || env->ExceptionCheck()) {
1909 return NS_ERROR_FAILURE;
1910 }
1911
1912 *aResult = reinterpret_cast<void*>(xpcom_obj);
1913#ifdef DEBUG_JAVAXPCOM
1914 JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(*aResult);
1915 nsIID* iid;
1916 inst->InterfaceInfo()->GetInterfaceIID(&iid);
1917 char* iid_str = iid->ToString();
1918 LOG(("< GetXPCOMInstFromProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
1919 (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
1920 aJavaObject),
1921 (PRUint32) inst->GetInstance(), iid_str));
1922 PR_Free(iid_str);
1923 nsMemory::Free(iid);
1924#endif
1925 return NS_OK;
1926}
1927
1928/**
1929 * org.mozilla.xpcom.internal.XPCOMJavaProxy.finalizeProxy
1930 */
1931extern "C" NS_EXPORT void JNICALL
1932JAVAPROXY_NATIVE(finalizeProxy) (JNIEnv *env, jclass that, jobject aJavaProxy)
1933{
1934#ifdef DEBUG_JAVAXPCOM
1935 PRUint32 xpcom_addr = 0;
1936#endif
1937
1938 // Due to Java's garbage collection, this finalize statement may get called
1939 // after FreeJavaGlobals(). So check to make sure that everything is still
1940 // initialized.
1941 if (gJavaXPCOMLock) {
1942 nsAutoLock lock(gJavaXPCOMLock);
1943
1944 // If may be possible for the lock to be acquired here when FreeGlobals is
1945 // in the middle of running. If so, then this thread will sleep until
1946 // FreeGlobals releases its lock. At that point, we resume this thread
1947 // here, but JavaXPCOM may no longer be initialized. So we need to check
1948 // that everything is legit after acquiring the lock.
1949 if (gJavaXPCOMInitialized) {
1950 // Get native XPCOM instance
1951 void* xpcom_obj;
1952 nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
1953 if (NS_SUCCEEDED(rv)) {
1954 JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(xpcom_obj);
1955#ifdef DEBUG_JAVAXPCOM
1956 xpcom_addr = reinterpret_cast<PRUint32>(inst->GetInstance());
1957#endif
1958 nsIID* iid;
1959 rv = inst->InterfaceInfo()->GetInterfaceIID(&iid);
1960 if (NS_SUCCEEDED(rv)) {
1961 rv = gNativeToJavaProxyMap->Remove(env, inst->GetInstance(), *iid);
1962 nsMemory::Free(iid);
1963 }
1964 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to RemoveJavaProxy");
1965 // Release gJavaXPCOMLock before deleting inst (see bug 340022)
1966 lock.unlock();
1967 delete inst;
1968 }
1969 }
1970 }
1971
1972#ifdef DEBUG_JAVAXPCOM
1973 LOG(("- Finalize (Java=%08x | XPCOM=%08x)\n",
1974 (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
1975 aJavaProxy),
1976 xpcom_addr));
1977#endif
1978}
1979
1980/**
1981 * org.mozilla.xpcom.XPCOMJavaProxy.isSameXPCOMObject
1982 */
1983extern "C" NS_EXPORT jboolean JNICALL
1984JAVAPROXY_NATIVE(isSameXPCOMObject) (JNIEnv *env, jclass that,
1985 jobject aProxy1, jobject aProxy2)
1986{
1987 void* xpcom_obj1;
1988 nsresult rv = GetXPCOMInstFromProxy(env, aProxy1, &xpcom_obj1);
1989 if (NS_SUCCEEDED(rv)) {
1990 void* xpcom_obj2;
1991 rv = GetXPCOMInstFromProxy(env, aProxy2, &xpcom_obj2);
1992 if (NS_SUCCEEDED(rv)) {
1993 JavaXPCOMInstance* inst1 = static_cast<JavaXPCOMInstance*>(xpcom_obj1);
1994 JavaXPCOMInstance* inst2 = static_cast<JavaXPCOMInstance*>(xpcom_obj2);
1995 if (inst1->GetInstance() == inst2->GetInstance()) {
1996 return JNI_TRUE;
1997 }
1998 }
1999 }
2000 return JNI_FALSE;
2001}
2002
2003/**
2004 * org.mozilla.xpcom.ProfileLock.release
2005 */
2006extern "C" NS_EXPORT void JNICALL
2007LOCKPROXY_NATIVE(release) (JNIEnv *env, jclass that, jlong aLockObject)
2008{
2009 // Need to release object on the main thread.
2010 nsresult rv = NS_ERROR_FAILURE;
2011 rv = NS_ProxyRelease(do_GetMainThreadQueue().get(), reinterpret_cast<nsISupports*>(aLockObject));
2012 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease");
2013}
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