Bug 469739 - Add support for displaying Vista UAC shield icon; r=joe sr=vladimir
[wine-gecko.git] / js / src / liveconnect / nsCLiveconnect.cpp
blob265dc33bc0bd449dc19e4fdd93578e7cab957638
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 * This file is part of the Java-vendor-neutral implementation of LiveConnect
42 * It contains the implementation providing nsIFactory XP-COM interface.
47 #include <stdlib.h>
48 #include <string.h>
49 #include "prtypes.h"
50 #include "prprf.h"
51 #include "prlog.h"
53 #include "jsj_private.h"
54 #include "jsjava.h"
56 #include "jsdbgapi.h"
57 #include "jsarena.h"
58 #include "jsfun.h"
59 #include "jscntxt.h" /* For js_ReportErrorAgain().*/
60 #include "jsscript.h"
61 #include "jsstaticcheck.h"
63 #include "netscape_javascript_JSObject.h" /* javah-generated headers */
64 #include "nsISecurityContext.h"
65 #include "nsIServiceManager.h"
66 #include "nsIJSContextStack.h"
68 PR_BEGIN_EXTERN_C
70 /* A captured JavaScript error, created when JS_ReportError() is called while
71 running JavaScript code that is itself called from Java. */
72 struct CapturedJSError {
73 char * message;
74 JSErrorReport report; /* Line # of error, etc. */
75 jthrowable java_exception; /* Java exception, error, or null */
76 CapturedJSError * next; /* Next oldest captured JS error */
78 PR_END_EXTERN_C
80 #include "nsCLiveconnect.h"
82 #include "jsinterp.h" // XXX private API so we can auto-push a JSStackFrame
83 #include "nsIScriptSecurityManager.h"
84 #include "nsIPrincipal.h"
85 #include "nsNetUtil.h"
86 #include "nsISecurityContext.h"
87 #include "prmem.h"
89 /***************************************************************************/
90 // A class to put on the stack to manage JS contexts when we are entering JS.
91 // This pushes and pops the given context
92 // with the nsThreadJSContextStack service as this object goes into and out
93 // of scope. It is optimized to not push/pop the cx if it is already on top
94 // of the stack. We need to push the JSContext when we enter JS because the
95 // JS security manager looks on the context stack for permissions information.
97 class AutoPushJSContext
99 public:
100 AutoPushJSContext(nsISupports* aSecuritySupports,
101 JSContext *cx);
103 ~AutoPushJSContext();
105 nsresult ResultOfPush() { return mPushResult; }
107 private:
108 nsCOMPtr<nsIJSContextStack> mContextStack;
109 JSContext* mContext;
110 JSStackFrame mFrame;
111 JSFrameRegs mRegs;
112 nsresult mPushResult;
115 AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports,
116 JSContext *cx)
117 : mContext(cx), mPushResult(NS_OK)
119 nsCOMPtr<nsIJSContextStack> contextStack =
120 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
122 JS_BeginRequest(cx);
124 JSContext* currentCX;
125 if(contextStack &&
126 // Don't push if the current context is already on the stack.
127 (NS_FAILED(contextStack->Peek(&currentCX)) ||
128 cx != currentCX) )
130 if (NS_SUCCEEDED(contextStack->Push(cx)))
132 // Leave the reference in mContextStack to
133 // indicate that we need to pop it in our dtor.
134 mContextStack.swap(contextStack);
138 nsCOMPtr<nsIScriptSecurityManager> secMan(
139 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &mPushResult));
141 if (NS_FAILED(mPushResult))
142 return;
144 nsCOMPtr<nsIPrincipal> principal;
145 mPushResult = secMan->GetPrincipalFromContext(cx, getter_AddRefs(principal));
147 if (NS_FAILED(mPushResult))
149 JS_ReportError(cx, "failed to get a principal");
150 return;
153 // See if JavaScript is enabled for the current window
154 PRBool jsEnabled = PR_FALSE;
155 mPushResult = secMan->CanExecuteScripts(cx, principal, &jsEnabled);
156 if (!jsEnabled)
157 mPushResult = NS_ERROR_FAILURE;
159 memset(&mFrame, 0, sizeof(mFrame));
161 if (NS_SUCCEEDED(mPushResult))
163 // See if there are any scripts on the stack.
164 // If not, we need to add a dummy frame with a principal.
165 JSStackFrame* tempFP = JS_GetScriptedCaller(cx, NULL);
166 JS_ASSERT_NOT_EXECUTING_TRACE(cx);
168 if (!tempFP)
170 JSPrincipals* jsprinc;
171 principal->GetJSPrincipals(cx, &jsprinc);
173 JSFunction *fun = JS_CompileFunctionForPrincipals(cx, JS_GetGlobalObject(cx),
174 jsprinc, "anonymous", 0, nsnull,
175 "", 0, "", 1);
176 JSPRINCIPALS_DROP(cx, jsprinc);
178 if (fun)
180 JSScript *script = JS_GetFunctionScript(cx, fun);
181 mFrame.fun = fun;
182 mFrame.script = script;
183 mFrame.callee = JS_GetFunctionObject(fun);
184 mFrame.scopeChain = JS_GetParent(cx, mFrame.callee);
185 mFrame.down = cx->fp;
186 mRegs.pc = script->code + script->length - 1;
187 JS_ASSERT(static_cast<JSOp>(*mRegs.pc) == JSOP_STOP);
188 mRegs.sp = NULL;
189 mFrame.regs = &mRegs;
190 cx->fp = &mFrame;
192 else
193 mPushResult = NS_ERROR_OUT_OF_MEMORY;
198 AutoPushJSContext::~AutoPushJSContext()
200 if (mContextStack)
201 mContextStack->Pop(nsnull);
203 if (mFrame.callobj)
204 js_PutCallObject(mContext, &mFrame);
205 if (mFrame.argsobj)
206 js_PutArgsObject(mContext, &mFrame);
207 JS_ClearPendingException(mContext);
209 VOUCH_DOES_NOT_REQUIRE_STACK();
210 if (mFrame.script)
211 mContext->fp = mFrame.down;
213 JS_EndRequest(mContext);
217 ////////////////////////////////////////////////////////////////////////////
218 // from nsISupports and AggregatedQueryInterface:
220 // Thes macro expands to the aggregated query interface scheme.
222 NS_IMPL_AGGREGATED(nsCLiveconnect)
223 NS_INTERFACE_MAP_BEGIN_AGGREGATED(nsCLiveconnect)
224 NS_INTERFACE_MAP_ENTRY(nsILiveconnect)
225 NS_INTERFACE_MAP_END
229 ////////////////////////////////////////////////////////////////////////////
230 // from nsILiveconnect:
233 * get member of a Native JSObject for a given name.
235 * @param jEnv - JNIEnv on which the call is being made.
236 * @param obj - A Native JS Object.
237 * @param name - Name of a member.
238 * @param pjobj - return parameter as a java object representing
239 * the member. If it is a basic data type it is converted to
240 * a corresponding java type. If it is a NJSObject, then it is
241 * wrapped up as java wrapper netscape.javascript.JSObject.
243 NS_METHOD
244 nsCLiveconnect::GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[],
245 int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
247 if(jEnv == NULL || obj == 0)
249 return NS_ERROR_FAILURE;
252 JSJavaThreadState *jsj_env = NULL;
253 JSObjectHandle *handle = (JSObjectHandle*)obj;
254 JSObject *js_obj = handle->js_obj;
255 JSContext *cx = NULL;
256 jobject member = NULL;
257 jsval js_val;
258 int dummy_cost = 0;
259 JSBool dummy_bool = PR_FALSE;
260 JSErrorReporter saved_state = NULL;
262 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
263 if (!jsj_env)
264 return NS_ERROR_FAILURE;
266 AutoPushJSContext autopush(securitySupports, cx);
267 if (NS_FAILED(autopush.ResultOfPush()))
268 goto done;
270 if (!name) {
271 JS_ReportError(cx, "illegal null member name");
272 member = NULL;
273 goto done;
276 if (!JS_GetUCProperty(cx, js_obj, name, length, &js_val))
277 goto done;
279 jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
280 &dummy_cost, &member, &dummy_bool);
282 done:
283 if (!jsj_exit_js(cx, jsj_env, saved_state))
284 return NS_ERROR_FAILURE;
286 *pjobj = member;
288 return NS_OK;
293 * get member of a Native JSObject for a given index.
295 * @param jEnv - JNIEnv on which the call is being made.
296 * @param obj - A Native JS Object.
297 * @param index - Index of a member.
298 * @param pjobj - return parameter as a java object representing
299 * the member.
301 NS_METHOD
302 nsCLiveconnect::GetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, void* principalsArray[],
303 int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
305 if(jEnv == NULL || obj == 0)
307 return NS_ERROR_FAILURE;
310 JSJavaThreadState *jsj_env = NULL;
311 JSObjectHandle *handle = (JSObjectHandle*)obj;
312 JSObject *js_obj = handle->js_obj;
313 JSContext *cx = NULL;
314 jobject member = NULL;
315 jsval js_val;
316 int dummy_cost = 0;
317 JSBool dummy_bool = PR_FALSE;
318 JSErrorReporter saved_state = NULL;
320 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
321 if (!jsj_env)
322 return NS_ERROR_FAILURE;
324 AutoPushJSContext autopush(securitySupports, cx);
325 if (NS_FAILED(autopush.ResultOfPush()))
326 goto done;
328 // =-= sudu: check to see if slot can be passed in as is.
329 // Should it be converted to a jsint?
330 if (!JS_GetElement(cx, js_obj, slot, &js_val))
331 goto done;
332 if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
333 &dummy_cost, &member, &dummy_bool))
334 goto done;
336 done:
337 if (!jsj_exit_js(cx, jsj_env, saved_state))
338 return NS_ERROR_FAILURE;
340 *pjobj = member;
341 return NS_OK;
345 * set member of a Native JSObject for a given name.
347 * @param jEnv - JNIEnv on which the call is being made.
348 * @param obj - A Native JS Object.
349 * @param name - Name of a member.
350 * @param jobj - Value to set. If this is a basic data type, it is converted
351 * using standard JNI calls but if it is a wrapper to a JSObject
352 * then a internal mapping is consulted to convert to a NJSObject.
354 NS_METHOD
355 nsCLiveconnect::SetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobject java_obj, void* principalsArray[],
356 int numPrincipals, nsISupports *securitySupports)
358 if(jEnv == NULL || obj == 0)
360 return NS_ERROR_FAILURE;
363 JSJavaThreadState *jsj_env = NULL;
364 JSObjectHandle *handle = (JSObjectHandle*)obj;
365 JSObject *js_obj = handle->js_obj;
366 JSContext *cx = NULL;
367 jsval js_val;
368 JSErrorReporter saved_state = NULL;
370 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
371 if (!jsj_env)
372 return NS_ERROR_FAILURE;
374 AutoPushJSContext autopush(securitySupports, cx);
375 if (NS_FAILED(autopush.ResultOfPush()))
376 goto done;
378 if (!name) {
379 JS_ReportError(cx, "illegal null member name");
380 goto done;
383 if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
384 goto done;
386 JS_SetUCProperty(cx, js_obj, name, length, &js_val);
388 done:
389 jsj_exit_js(cx, jsj_env, saved_state);
390 return NS_OK;
395 * set member of a Native JSObject for a given index.
397 * @param jEnv - JNIEnv on which the call is being made.
398 * @param obj - A Native JS Object.
399 * @param index - Index of a member.
400 * @param jobj - Value to set. If this is a basic data type, it is converted
401 * using standard JNI calls but if it is a wrapper to a JSObject
402 * then a internal mapping is consulted to convert to a NJSObject.
404 NS_METHOD
405 nsCLiveconnect::SetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, jobject java_obj, void* principalsArray[],
406 int numPrincipals, nsISupports *securitySupports)
408 if(jEnv == NULL || obj == 0)
410 return NS_ERROR_FAILURE;
413 JSJavaThreadState *jsj_env = NULL;
414 JSObjectHandle *handle = (JSObjectHandle*)obj;
415 JSObject *js_obj = handle->js_obj;
416 JSContext *cx = NULL;
417 jsval js_val;
418 JSErrorReporter saved_state = NULL;
420 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
421 if (!jsj_env)
422 return NS_ERROR_FAILURE;
424 AutoPushJSContext autopush(securitySupports, cx);
425 if (NS_FAILED(autopush.ResultOfPush()))
426 goto done;
428 if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
429 goto done;
430 JS_SetElement(cx, js_obj, slot, &js_val);
432 done:
433 jsj_exit_js(cx, jsj_env, saved_state);
434 return NS_OK;
439 * remove member of a Native JSObject for a given name.
441 * @param jEnv - JNIEnv on which the call is being made.
442 * @param obj - A Native JS Object.
443 * @param name - Name of a member.
445 NS_METHOD
446 nsCLiveconnect::RemoveMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[],
447 int numPrincipals, nsISupports *securitySupports)
449 if(jEnv == NULL || obj == 0)
451 return NS_ERROR_FAILURE;
454 JSJavaThreadState *jsj_env = NULL;
455 JSObjectHandle *handle = (JSObjectHandle*)obj;
456 JSObject *js_obj = handle->js_obj;
457 JSContext *cx = NULL;
458 jsval js_val;
459 JSErrorReporter saved_state = NULL;
461 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
462 if (!jsj_env)
463 return NS_ERROR_FAILURE;
465 AutoPushJSContext autopush(securitySupports, cx);
466 if (NS_FAILED(autopush.ResultOfPush()))
467 goto done;
469 if (!name) {
470 JS_ReportError(cx, "illegal null member name");
471 goto done;
474 JS_DeleteUCProperty2(cx, js_obj, name, length, &js_val);
476 done:
477 jsj_exit_js(cx, jsj_env, saved_state);
478 return NS_OK;
483 * call a method of Native JSObject.
485 * @param jEnv - JNIEnv on which the call is being made.
486 * @param obj - A Native JS Object.
487 * @param name - Name of a method.
488 * @param jobjArr - Array of jobjects representing parameters of method being caled.
489 * @param pjobj - return value.
491 NS_METHOD
492 nsCLiveconnect::Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[],
493 int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
495 if(jEnv == NULL || obj == 0)
497 return NS_ERROR_FAILURE;
500 int i = 0;
501 int argc = 0;
502 int arg_num = 0;
503 jsval *argv = 0;
504 JSJavaThreadState *jsj_env = NULL;
505 JSObjectHandle *handle = (JSObjectHandle*)obj;
506 JSObject *js_obj = handle->js_obj;
507 JSContext *cx = NULL;
508 jsval js_val;
509 jsval function_val = 0;
510 int dummy_cost = 0;
511 JSBool dummy_bool = PR_FALSE;
512 JSErrorReporter saved_state = NULL;
513 jobject result = NULL;
515 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
516 if (!jsj_env)
517 return NS_ERROR_FAILURE;
519 result = NULL;
520 AutoPushJSContext autopush(securitySupports, cx);
521 if (NS_FAILED(autopush.ResultOfPush()))
522 goto done;
524 if (!name) {
525 JS_ReportError(cx, "illegal null JavaScript function name");
526 goto done;
529 /* Allocate space for JS arguments */
530 argc = java_args ? jEnv->GetArrayLength(java_args) : 0;
531 if (argc) {
532 argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval));
533 if (!argv)
534 goto done;
535 } else {
536 argv = 0;
539 /* Convert arguments from Java to JS values */
540 for (arg_num = 0; arg_num < argc; arg_num++) {
541 jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num);
542 JSBool ret = jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]);
544 jEnv->DeleteLocalRef(arg);
545 if (!ret)
546 goto cleanup_argv;
547 JS_AddRoot(cx, &argv[arg_num]);
550 if (!JS_GetUCProperty(cx, js_obj, name, length, &function_val))
551 goto cleanup_argv;
553 if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val))
554 goto cleanup_argv;
556 jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
557 &dummy_cost, &result, &dummy_bool);
559 cleanup_argv:
560 if (argv) {
561 for (i = 0; i < arg_num; i++)
562 JS_RemoveRoot(cx, &argv[i]);
563 JS_free(cx, argv);
566 done:
567 if (!jsj_exit_js(cx, jsj_env, saved_state))
568 return NS_ERROR_FAILURE;
570 *pjobj = result;
572 return NS_OK;
575 NS_METHOD
576 nsCLiveconnect::Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[],
577 int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
579 if(jEnv == NULL || obj == 0)
581 return NS_ERROR_FAILURE;
584 JSJavaThreadState *jsj_env = NULL;
585 JSObjectHandle *handle = (JSObjectHandle*)obj;
586 JSObject *js_obj = handle->js_obj;
587 JSContext *cx = NULL;
588 jsval js_val;
589 int dummy_cost = 0;
590 JSBool dummy_bool = PR_FALSE;
591 JSErrorReporter saved_state = NULL;
592 jobject result = NULL;
593 const char *codebase = NULL;
594 JSPrincipals *principals = NULL;
595 JSBool eval_succeeded = PR_FALSE;
597 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
598 if (!jsj_env)
599 return NS_ERROR_FAILURE;
601 result = NULL;
602 AutoPushJSContext autopush(securitySupports, cx);
603 if (NS_FAILED(autopush.ResultOfPush()))
604 goto done;
606 if (!script) {
607 JS_ReportError(cx, "illegal null string eval argument");
608 goto done;
611 /* Set up security stuff */
612 if (JSJ_callbacks && JSJ_callbacks->get_JSPrincipals_from_java_caller)
613 principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx, principalsArray, numPrincipals, securitySupports);
614 codebase = principals ? principals->codebase : NULL;
616 /* Have the JS engine evaluate the unicode string */
617 eval_succeeded = JS_EvaluateUCScriptForPrincipals(cx, js_obj, principals,
618 script, length,
619 codebase, 0, &js_val);
621 if (!eval_succeeded)
622 goto done;
624 /* Convert result to a subclass of java.lang.Object */
625 jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
626 &dummy_cost, &result, &dummy_bool);
628 done:
629 if (principals)
630 JSPRINCIPALS_DROP(cx, principals);
631 if (!jsj_exit_js(cx, jsj_env, saved_state))
632 return NS_ERROR_FAILURE;
634 *pjobj = result;
635 return NS_OK;
640 * Get the window object for a plugin instance.
642 * @param jEnv - JNIEnv on which the call is being made.
643 * @param pJavaObject - Either a jobject or a pointer to a plugin instance
644 * representing the java object.
645 * @param pjobj - return value. This is a native js object
646 * representing the window object of a frame
647 * in which a applet/bean resides.
649 NS_METHOD
650 nsCLiveconnect::GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArray[],
651 int numPrincipals, nsISupports *securitySupports, lcjsobject *pobj)
653 if(jEnv == NULL || JSJ_callbacks == NULL)
655 return NS_ERROR_FAILURE;
658 // associate this Java client with this LiveConnect connection.
659 mJavaClient = pJavaObject;
661 char *err_msg = NULL;
662 JSContext *cx = NULL;
663 JSObject *js_obj = NULL;
664 JSErrorReporter saved_state = NULL;
665 JSJavaThreadState *jsj_env = NULL;
666 JSObjectHandle *handle = NULL;
668 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
669 if (!jsj_env)
670 return NS_ERROR_FAILURE;
672 err_msg = NULL;
673 AutoPushJSContext autopush(securitySupports, cx);
674 if (NS_FAILED(autopush.ResultOfPush()))
675 goto done;
677 js_obj = JSJ_callbacks->map_java_object_to_js_object(jEnv, mJavaClient, &err_msg);
678 if (!js_obj) {
679 if (err_msg) {
680 JS_ReportError(cx, err_msg);
681 free(err_msg);
683 goto done;
685 #ifdef PRESERVE_JSOBJECT_IDENTITY
686 *pobj = (jint)js_obj;
687 #else
688 /* FIXME: to handle PRESERVE_JSOBJECT_IDENTITY case, this needs to
689 just return a raw JSObject reference. FIXME !!! */
690 /* Create a tiny stub object to act as the GC root that points to the
691 JSObject from its netscape.javascript.JSObject counterpart. */
692 handle = (JSObjectHandle*)JS_malloc(cx, sizeof(JSObjectHandle));
693 if (handle != NULL)
695 handle->js_obj = js_obj;
696 handle->rt = JS_GetRuntime(cx);
698 *pobj = (lcjsobject)handle;
699 /* FIXME: what if the window is explicitly disposed of, how do we
700 notify Java? */
701 #endif
702 done:
703 if (!jsj_exit_js(cx, jsj_env, saved_state))
704 return NS_ERROR_FAILURE;
706 return NS_OK;
710 * Get the window object for a plugin instance.
712 * @param jEnv - JNIEnv on which the call is being made.
713 * @param obj - A Native JS Object.
715 NS_METHOD
716 nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, lcjsobject obj)
718 if(jEnv == NULL || obj == 0)
720 return NS_ERROR_FAILURE;
723 JSObjectHandle *handle = (JSObjectHandle *)obj;
725 if (!handle)
726 return NS_ERROR_NULL_POINTER;
727 JS_RemoveRootRT(handle->rt, &handle->js_obj);
728 free(handle);
729 return NS_OK;
733 NS_METHOD
734 nsCLiveconnect::ToString(JNIEnv *jEnv, lcjsobject obj, jstring *pjstring)
736 if(jEnv == NULL || obj == 0)
738 return NS_ERROR_FAILURE;
741 JSJavaThreadState *jsj_env = NULL;
742 JSObjectHandle *handle = (JSObjectHandle*)obj;
743 JSObject *js_obj = handle->js_obj;
744 JSContext *cx = NULL;
745 JSErrorReporter saved_state = NULL;
746 jstring result = NULL;
747 JSString *jsstr = NULL;
749 jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, NULL, 0, NULL );
750 if (!jsj_env)
751 return NS_ERROR_FAILURE;
753 result = NULL;
754 AutoPushJSContext autopush(nsnull, cx);
755 if (NS_FAILED(autopush.ResultOfPush()))
756 return NS_ERROR_FAILURE;
758 jsstr = JS_ValueToString(cx, OBJECT_TO_JSVAL(js_obj));
759 if (jsstr)
760 result = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr);
761 if (!result)
762 result = jEnv->NewStringUTF("*JavaObject*");
764 if (!jsj_exit_js(cx, jsj_env, saved_state))
765 return NS_ERROR_FAILURE;
766 *pjstring = result;
767 return NS_OK;
771 ////////////////////////////////////////////////////////////////////////////
772 // from nsCLiveconnect:
774 nsCLiveconnect::nsCLiveconnect(nsISupports *aOuter)
775 : mJavaClient(NULL)
777 NS_INIT_AGGREGATED(aOuter);
778 #ifdef PRESERVE_JSOBJECT_IDENTITY
779 jsj_init_js_obj_reflections_table();
780 #endif
783 nsCLiveconnect::~nsCLiveconnect()