~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/js/src/liveconnect/nsCLiveconnect.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 *
 
3
 * ***** BEGIN LICENSE BLOCK *****
 
4
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
5
 *
 
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/
 
10
 *
 
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.
 
15
 *
 
16
 * The Original Code is Mozilla Communicator client code, released
 
17
 * March 31, 1998.
 
18
 *
 
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.
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
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.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
/*
 
40
 * This file is part of the Java-vendor-neutral implementation of LiveConnect
 
41
 *
 
42
 * It contains the implementation providing nsIFactory XP-COM interface.
 
43
 *
 
44
 */
 
45
 
 
46
 
 
47
#include <stdlib.h>
 
48
#include <string.h>
 
49
#include "prtypes.h"
 
50
#include "prprf.h"
 
51
#include "prlog.h"
 
52
 
 
53
#include "jsj_private.h"
 
54
#include "jsjava.h"
 
55
 
 
56
#include "jscntxt.h"        /* For js_ReportErrorAgain().*/
 
57
 
 
58
#include "netscape_javascript_JSObject.h"   /* javah-generated headers */
 
59
#include "nsISecurityContext.h"
 
60
#include "nsIServiceManager.h"
 
61
#include "nsIJSContextStack.h"
 
62
 
 
63
PR_BEGIN_EXTERN_C
 
64
 
 
65
/* A captured JavaScript error, created when JS_ReportError() is called while
 
66
   running JavaScript code that is itself called from Java. */
 
67
struct CapturedJSError {
 
68
    char *              message;
 
69
    JSErrorReport       report;         /* Line # of error, etc. */
 
70
    jthrowable          java_exception; /* Java exception, error, or null */
 
71
    CapturedJSError *   next;                   /* Next oldest captured JS error */
 
72
};
 
73
PR_END_EXTERN_C
 
74
 
 
75
#include "nsCLiveconnect.h"
 
76
 
 
77
#include "jsinterp.h"  // XXX private API so we can auto-push a JSStackFrame
 
78
#include "nsIScriptSecurityManager.h"
 
79
#include "nsIPrincipal.h"
 
80
#include "nsNetUtil.h"
 
81
#include "nsISecurityContext.h"
 
82
#include "prmem.h"
 
83
 
 
84
/***************************************************************************/
 
85
// A class to put on the stack to manage JS contexts when we are entering JS.
 
86
// This pushes and pops the given context
 
87
// with the nsThreadJSContextStack service as this object goes into and out
 
88
// of scope. It is optimized to not push/pop the cx if it is already on top
 
89
// of the stack. We need to push the JSContext when we enter JS because the
 
90
// JS security manager looks on the context stack for permissions information.
 
91
 
 
92
class AutoPushJSContext
 
93
{
 
94
public:
 
95
    AutoPushJSContext(nsISupports* aSecuritySupports,
 
96
                      JSContext *cx);
 
97
 
 
98
    ~AutoPushJSContext();
 
99
 
 
100
    nsresult ResultOfPush() { return mPushResult; };
 
101
 
 
102
private:
 
103
    nsCOMPtr<nsIJSContextStack> mContextStack;
 
104
    JSContext*                  mContext;
 
105
    JSStackFrame                mFrame;
 
106
    nsresult                    mPushResult;
 
107
};
 
108
 
 
109
AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports,
 
110
                                     JSContext *cx) 
 
111
                                     : mContext(cx), mPushResult(NS_OK)
 
112
{
 
113
    mContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
 
114
 
 
115
    if(mContextStack)
 
116
    {
 
117
        JSContext* currentCX;
 
118
        if(NS_SUCCEEDED(mContextStack->Peek(&currentCX)))
 
119
        {
 
120
            // Is the current context already on the stack?
 
121
            if(cx == currentCX)
 
122
                mContextStack = nsnull;
 
123
            else
 
124
            {
 
125
                mContextStack->Push(cx);
 
126
                // Leave the reference to the mContextStack to
 
127
                // indicate that we need to pop it in our dtor.                                               
 
128
            }
 
129
        }
 
130
    }
 
131
 
 
132
    nsCOMPtr<nsIScriptSecurityManager> secMan(
 
133
        do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &mPushResult));
 
134
 
 
135
    if (NS_FAILED(mPushResult))
 
136
        return;
 
137
 
 
138
    nsCOMPtr<nsIPrincipal> principal;
 
139
    mPushResult = secMan->GetPrincipalFromContext(cx, getter_AddRefs(principal));
 
140
 
 
141
    if (NS_FAILED(mPushResult))
 
142
    {
 
143
        JS_ReportError(cx, "failed to get a principal");
 
144
        return;
 
145
    }
 
146
 
 
147
    // See if JavaScript is enabled for the current window
 
148
    PRBool jsEnabled = PR_FALSE;
 
149
    mPushResult = secMan->CanExecuteScripts(cx, principal, &jsEnabled);
 
150
    if (!jsEnabled)
 
151
        mPushResult = NS_ERROR_FAILURE;
 
152
 
 
153
    memset(&mFrame, 0, sizeof(mFrame));
 
154
 
 
155
    if (NS_SUCCEEDED(mPushResult))
 
156
    {
 
157
        // See if there are any scripts on the stack.
 
158
        // If not, we need to add a dummy frame with a principal.
 
159
 
 
160
        PRBool hasScript = PR_FALSE;
 
161
        JSStackFrame* tempFP = cx->fp;
 
162
        while (tempFP)
 
163
        {
 
164
            if (tempFP->script)
 
165
            {
 
166
                hasScript = PR_TRUE;
 
167
                break;
 
168
            }
 
169
            tempFP = tempFP->down;
 
170
        };
 
171
 
 
172
        if (!hasScript)
 
173
        {
 
174
            JSPrincipals* jsprinc;
 
175
            principal->GetJSPrincipals(cx, &jsprinc);
 
176
 
 
177
            mFrame.script = JS_CompileScriptForPrincipals(cx, JS_GetGlobalObject(cx),
 
178
                                                          jsprinc, "", 0, "", 1);
 
179
            JSPRINCIPALS_DROP(cx, jsprinc);
 
180
 
 
181
            if (mFrame.script)
 
182
            {
 
183
                mFrame.down = cx->fp;
 
184
                cx->fp = &mFrame;
 
185
            }
 
186
            else
 
187
                mPushResult = NS_ERROR_OUT_OF_MEMORY;
 
188
        }
 
189
    }
 
190
}
 
191
 
 
192
AutoPushJSContext::~AutoPushJSContext()
 
193
{
 
194
    if (mContextStack)
 
195
        mContextStack->Pop(nsnull);
 
196
 
 
197
    if (mFrame.script)
 
198
        mContext->fp = mFrame.down;
 
199
 
 
200
}
 
201
 
 
202
 
 
203
////////////////////////////////////////////////////////////////////////////
 
204
// from nsISupports and AggregatedQueryInterface:
 
205
 
 
206
// Thes macro expands to the aggregated query interface scheme.
 
207
 
 
208
NS_IMPL_AGGREGATED(nsCLiveconnect)
 
209
 
 
210
NS_METHOD
 
211
nsCLiveconnect::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
 
212
{
 
213
         NS_ENSURE_ARG_POINTER(aInstancePtr);
 
214
 
 
215
    if (aIID.Equals(NS_GET_IID(nsISupports))) {
 
216
      *aInstancePtr = GetInner();
 
217
    }
 
218
    else if (aIID.Equals(NS_GET_IID(nsILiveconnect))) {
 
219
        *aInstancePtr = NS_STATIC_CAST(nsILiveconnect*, this);
 
220
    }
 
221
         else   {
 
222
                  *aInstancePtr = nsnull;
 
223
                  return NS_NOINTERFACE;
 
224
         }
 
225
         NS_ADDREF((nsISupports*) *aInstancePtr);
 
226
         return NS_OK;
 
227
}
 
228
 
 
229
 
 
230
 
 
231
////////////////////////////////////////////////////////////////////////////
 
232
// from nsILiveconnect:
 
233
 
 
234
/**
 
235
 * get member of a Native JSObject for a given name.
 
236
 *
 
237
 * @param jEnv       - JNIEnv on which the call is being made.
 
238
 * @param obj        - A Native JS Object.
 
239
 * @param name       - Name of a member.
 
240
 * @param pjobj      - return parameter as a java object representing 
 
241
 *                     the member. If it is a basic data type it is converted to
 
242
 *                     a corresponding java type. If it is a NJSObject, then it is
 
243
 *                     wrapped up as java wrapper netscape.javascript.JSObject.
 
244
 */
 
245
NS_METHOD       
 
246
nsCLiveconnect::GetMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, void* principalsArray[], 
 
247
                     int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
 
248
{
 
249
    if(jEnv == NULL || obj == 0)
 
250
    {
 
251
       return NS_ERROR_FAILURE;
 
252
    }
 
253
 
 
254
    JSJavaThreadState *jsj_env        = NULL;
 
255
    JSObjectHandle    *handle         = (JSObjectHandle*)obj;
 
256
    JSObject          *js_obj         = handle->js_obj;
 
257
    JSContext         *cx             = NULL;
 
258
    jobject            member         = NULL;
 
259
    jsval              js_val;
 
260
    int                dummy_cost     = 0;
 
261
    JSBool             dummy_bool     = PR_FALSE;
 
262
    JSErrorReporter    saved_state    = NULL;
 
263
 
 
264
    jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
 
265
    if (!jsj_env)
 
266
        return NS_ERROR_FAILURE;
 
267
 
 
268
    AutoPushJSContext autopush(securitySupports, cx);
 
269
    if (NS_FAILED(autopush.ResultOfPush()))
 
270
        goto done;
 
271
 
 
272
    if (!name) {
 
273
        JS_ReportError(cx, "illegal null member name");
 
274
        member = NULL;
 
275
        goto done;
 
276
    }
 
277
    
 
278
    if (!JS_GetUCProperty(cx, js_obj, name, length, &js_val))
 
279
        goto done;
 
280
 
 
281
    jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
 
282
                                   &dummy_cost, &member, &dummy_bool);
 
283
 
 
284
done:
 
285
    if (!jsj_exit_js(cx, jsj_env, saved_state))
 
286
        return NS_ERROR_FAILURE;
 
287
    
 
288
    *pjobj = member;
 
289
 
 
290
    return NS_OK;
 
291
}
 
292
 
 
293
 
 
294
/**
 
295
 * get member of a Native JSObject for a given index.
 
296
 *
 
297
 * @param jEnv       - JNIEnv on which the call is being made.
 
298
 * @param obj        - A Native JS Object.
 
299
 * @param index      - Index of a member.
 
300
 * @param pjobj      - return parameter as a java object representing 
 
301
 *                     the member. 
 
302
 */
 
303
NS_METHOD       
 
304
nsCLiveconnect::GetSlot(JNIEnv *jEnv, jsobject obj, jint slot, void* principalsArray[], 
 
305
                     int numPrincipals, nsISupports *securitySupports,  jobject *pjobj)
 
306
{
 
307
    if(jEnv == NULL || obj == 0)
 
308
    {
 
309
       return NS_ERROR_FAILURE;
 
310
    }
 
311
 
 
312
    JSJavaThreadState *jsj_env        = NULL;
 
313
    JSObjectHandle    *handle         = (JSObjectHandle*)obj;
 
314
    JSObject          *js_obj         = handle->js_obj;
 
315
    JSContext         *cx             = NULL;
 
316
    jobject            member         = NULL;
 
317
    jsval              js_val;
 
318
    int                dummy_cost     = 0;
 
319
    JSBool             dummy_bool     = PR_FALSE;
 
320
    JSErrorReporter    saved_state    = NULL;
 
321
 
 
322
    jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
 
323
    if (!jsj_env)
 
324
       return NS_ERROR_FAILURE;
 
325
 
 
326
    AutoPushJSContext autopush(securitySupports, cx);
 
327
    if (NS_FAILED(autopush.ResultOfPush()))
 
328
        goto done;
 
329
    
 
330
    // =-= sudu: check to see if slot can be passed in as is.
 
331
    //           Should it be converted to a jsint?
 
332
    if (!JS_GetElement(cx, js_obj, slot, &js_val))
 
333
        goto done;
 
334
    if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
 
335
                                        &dummy_cost, &member, &dummy_bool))
 
336
        goto done;
 
337
 
 
338
done:
 
339
    if (!jsj_exit_js(cx, jsj_env, saved_state))
 
340
       return NS_ERROR_FAILURE;
 
341
    
 
342
    *pjobj = member;
 
343
    return NS_OK;
 
344
}
 
345
 
 
346
/**
 
347
 * set member of a Native JSObject for a given name.
 
348
 *
 
349
 * @param jEnv       - JNIEnv on which the call is being made.
 
350
 * @param obj        - A Native JS Object.
 
351
 * @param name       - Name of a member.
 
352
 * @param jobj       - Value to set. If this is a basic data type, it is converted
 
353
 *                     using standard JNI calls but if it is a wrapper to a JSObject
 
354
 *                     then a internal mapping is consulted to convert to a NJSObject.
 
355
 */
 
356
NS_METHOD       
 
357
nsCLiveconnect::SetMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, jobject java_obj, void* principalsArray[], 
 
358
                     int numPrincipals, nsISupports *securitySupports)
 
359
{
 
360
    if(jEnv == NULL || obj == 0)
 
361
    {
 
362
       return NS_ERROR_FAILURE;
 
363
    }
 
364
 
 
365
    JSJavaThreadState *jsj_env        = NULL;
 
366
    JSObjectHandle    *handle         = (JSObjectHandle*)obj;
 
367
    JSObject          *js_obj         = handle->js_obj;
 
368
    JSContext         *cx             = NULL;
 
369
    jsval              js_val;
 
370
    JSErrorReporter    saved_state    = NULL;
 
371
 
 
372
    jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
 
373
    if (!jsj_env)
 
374
        return NS_ERROR_FAILURE;
 
375
 
 
376
    AutoPushJSContext autopush(securitySupports, cx);
 
377
    if (NS_FAILED(autopush.ResultOfPush()))
 
378
        goto done;
 
379
    
 
380
    if (!name) {
 
381
        JS_ReportError(cx, "illegal null member name");
 
382
        goto done;
 
383
    }
 
384
 
 
385
    if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
 
386
        goto done;
 
387
 
 
388
    JS_SetUCProperty(cx, js_obj, name, length, &js_val);
 
389
 
 
390
done:
 
391
    jsj_exit_js(cx, jsj_env, saved_state);
 
392
   return NS_OK;
 
393
}
 
394
 
 
395
 
 
396
/**
 
397
 * set member of a Native JSObject for a given index.
 
398
 *
 
399
 * @param jEnv       - JNIEnv on which the call is being made.
 
400
 * @param obj        - A Native JS Object.
 
401
 * @param index      - Index of a member.
 
402
 * @param jobj       - Value to set. If this is a basic data type, it is converted
 
403
 *                     using standard JNI calls but if it is a wrapper to a JSObject
 
404
 *                     then a internal mapping is consulted to convert to a NJSObject.
 
405
 */
 
406
NS_METHOD       
 
407
nsCLiveconnect::SetSlot(JNIEnv *jEnv, jsobject obj, jint slot, jobject java_obj,  void* principalsArray[], 
 
408
                     int numPrincipals, nsISupports *securitySupports)
 
409
{
 
410
    if(jEnv == NULL || obj == 0)
 
411
    {
 
412
       return NS_ERROR_FAILURE;
 
413
    }
 
414
 
 
415
    JSJavaThreadState *jsj_env        = NULL;
 
416
    JSObjectHandle    *handle         = (JSObjectHandle*)obj;
 
417
    JSObject          *js_obj         = handle->js_obj;
 
418
    JSContext         *cx             = NULL;
 
419
    jsval              js_val;
 
420
    JSErrorReporter    saved_state    = NULL;
 
421
 
 
422
    jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
 
423
    if (!jsj_env)
 
424
        return NS_ERROR_FAILURE;
 
425
 
 
426
    AutoPushJSContext autopush(securitySupports, cx);
 
427
    if (NS_FAILED(autopush.ResultOfPush()))
 
428
        goto done;
 
429
    
 
430
    if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
 
431
        goto done;
 
432
    JS_SetElement(cx, js_obj, slot, &js_val);
 
433
 
 
434
done:
 
435
    jsj_exit_js(cx, jsj_env, saved_state);
 
436
    return NS_OK;
 
437
}
 
438
 
 
439
 
 
440
/**
 
441
 * remove member of a Native JSObject for a given name.
 
442
 *
 
443
 * @param jEnv       - JNIEnv on which the call is being made.
 
444
 * @param obj        - A Native JS Object.
 
445
 * @param name       - Name of a member.
 
446
 */
 
447
NS_METHOD       
 
448
nsCLiveconnect::RemoveMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length,  void* principalsArray[], 
 
449
                             int numPrincipals, nsISupports *securitySupports)
 
450
{
 
451
    if(jEnv == NULL || obj == 0)
 
452
    {
 
453
       return NS_ERROR_FAILURE;
 
454
    }
 
455
 
 
456
    JSJavaThreadState *jsj_env        = NULL;
 
457
    JSObjectHandle    *handle         = (JSObjectHandle*)obj;
 
458
    JSObject          *js_obj         = handle->js_obj;
 
459
    JSContext         *cx             = NULL;
 
460
    jsval              js_val;
 
461
    JSErrorReporter    saved_state    = NULL;
 
462
 
 
463
    jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
 
464
    if (!jsj_env)
 
465
        return NS_ERROR_FAILURE;
 
466
 
 
467
    AutoPushJSContext autopush(securitySupports, cx);
 
468
    if (NS_FAILED(autopush.ResultOfPush()))
 
469
        goto done;
 
470
    
 
471
    if (!name) {
 
472
        JS_ReportError(cx, "illegal null member name");
 
473
        goto done;
 
474
    }
 
475
 
 
476
    JS_DeleteUCProperty2(cx, js_obj, name, length, &js_val);
 
477
 
 
478
done:
 
479
    jsj_exit_js(cx, jsj_env, saved_state);
 
480
    return NS_OK;
 
481
}
 
482
 
 
483
 
 
484
/**
 
485
 * call a method of Native JSObject. 
 
486
 *
 
487
 * @param jEnv       - JNIEnv on which the call is being made.
 
488
 * @param obj        - A Native JS Object.
 
489
 * @param name       - Name of a method.
 
490
 * @param jobjArr    - Array of jobjects representing parameters of method being caled.
 
491
 * @param pjobj      - return value.
 
492
 */
 
493
NS_METHOD       
 
494
nsCLiveconnect::Call(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[], 
 
495
                     int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
 
496
{
 
497
    if(jEnv == NULL || obj == 0)
 
498
    {
 
499
       return NS_ERROR_FAILURE;
 
500
    }
 
501
 
 
502
    int                i              = 0;
 
503
    int                argc           = 0;
 
504
    int                arg_num        = 0;
 
505
    jsval             *argv           = 0;
 
506
    JSJavaThreadState *jsj_env        = NULL;
 
507
    JSObjectHandle    *handle         = (JSObjectHandle*)obj;
 
508
    JSObject          *js_obj         = handle->js_obj;
 
509
    JSContext         *cx             = NULL;
 
510
    jsval              js_val;
 
511
    jsval              function_val   = 0;
 
512
    int                dummy_cost     = 0;
 
513
    JSBool             dummy_bool     = PR_FALSE;
 
514
    JSErrorReporter    saved_state    = NULL;
 
515
    jobject            result         = NULL;
 
516
 
 
517
    jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports);
 
518
    if (!jsj_env)
 
519
        return NS_ERROR_FAILURE;
 
520
 
 
521
    result = NULL;
 
522
    AutoPushJSContext autopush(securitySupports, cx);
 
523
    if (NS_FAILED(autopush.ResultOfPush()))
 
524
        goto done;
 
525
    
 
526
    if (!name) {
 
527
        JS_ReportError(cx, "illegal null JavaScript function name");
 
528
        goto done;
 
529
    }
 
530
 
 
531
    /* Allocate space for JS arguments */
 
532
    argc = java_args ? jEnv->GetArrayLength(java_args) : 0;
 
533
    if (argc) {
 
534
        argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval));
 
535
        if (!argv)
 
536
            goto done;
 
537
    } else {
 
538
        argv = 0;
 
539
    }
 
540
 
 
541
    /* Convert arguments from Java to JS values */
 
542
    for (arg_num = 0; arg_num < argc; arg_num++) {
 
543
        jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num);
 
544
 
 
545
        if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]))
 
546
            goto cleanup_argv;
 
547
        JS_AddRoot(cx, &argv[arg_num]);
 
548
    }
 
549
 
 
550
    if (!JS_GetUCProperty(cx, js_obj, name, length, &function_val))
 
551
        goto cleanup_argv;
 
552
 
 
553
    if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val))
 
554
        goto cleanup_argv;
 
555
 
 
556
    jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
 
557
                                   &dummy_cost, &result, &dummy_bool);
 
558
 
 
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);
 
564
    }
 
565
 
 
566
done:
 
567
    if (!jsj_exit_js(cx, jsj_env, saved_state))
 
568
        return NS_ERROR_FAILURE;
 
569
    
 
570
    *pjobj = result;
 
571
 
 
572
    return NS_OK;
 
573
}
 
574
 
 
575
NS_METHOD       
 
576
nsCLiveconnect::Eval(JNIEnv *jEnv, jsobject obj, const jchar *script, jsize length, void* principalsArray[], 
 
577
                     int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
 
578
{
 
579
    if(jEnv == NULL || obj == 0)
 
580
    {
 
581
       return NS_ERROR_FAILURE;
 
582
    }
 
583
 
 
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;
 
596
 
 
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;
 
600
 
 
601
    result = NULL;
 
602
    AutoPushJSContext autopush(securitySupports, cx);
 
603
    if (NS_FAILED(autopush.ResultOfPush()))
 
604
        goto done;
 
605
    
 
606
    if (!script) {
 
607
        JS_ReportError(cx, "illegal null string eval argument");
 
608
        goto done;
 
609
    }
 
610
 
 
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;
 
615
 
 
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);
 
620
 
 
621
    if (!eval_succeeded)
 
622
        goto done;
 
623
 
 
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);
 
627
 
 
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;
 
633
    
 
634
    *pjobj = result;
 
635
    return NS_OK;
 
636
}
 
637
 
 
638
 
 
639
/**
 
640
 * Get the window object for a plugin instance.
 
641
 *
 
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.
 
648
 */
 
649
NS_METHOD       
 
650
nsCLiveconnect::GetWindow(JNIEnv *jEnv, void *pJavaObject,  void* principalsArray[], 
 
651
                     int numPrincipals, nsISupports *securitySupports, jsobject *pobj)
 
652
{
 
653
    if(jEnv == NULL || JSJ_callbacks == NULL)
 
654
    {
 
655
       return NS_ERROR_FAILURE;
 
656
    }
 
657
 
 
658
    // associate this Java client with this LiveConnect connection.
 
659
    mJavaClient = pJavaObject;
 
660
 
 
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;
 
667
 
 
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;
 
671
 
 
672
    err_msg = NULL;
 
673
    AutoPushJSContext autopush(securitySupports, cx);
 
674
    if (NS_FAILED(autopush.ResultOfPush()))
 
675
        goto done;
 
676
    
 
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);
 
682
        }
 
683
        goto done;
 
684
    }
 
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)
 
694
    {
 
695
      handle->js_obj = js_obj;
 
696
      handle->rt = JS_GetRuntime(cx);
 
697
    }
 
698
    *pobj = (jsobject)NS_PTR_TO_INT32(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;
 
705
 
 
706
    return NS_OK;
 
707
}
 
708
 
 
709
/**
 
710
 * Get the window object for a plugin instance.
 
711
 *
 
712
 * @param jEnv       - JNIEnv on which the call is being made.
 
713
 * @param obj        - A Native JS Object.
 
714
 */
 
715
NS_METHOD       
 
716
nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, jsobject obj)
 
717
{
 
718
    if(jEnv == NULL || obj == 0)
 
719
    {
 
720
       return NS_ERROR_FAILURE;
 
721
    }
 
722
 
 
723
    JSObjectHandle    *handle         = (JSObjectHandle *)obj;
 
724
    
 
725
    if (!handle)
 
726
        return NS_ERROR_NULL_POINTER;
 
727
    JS_RemoveRootRT(handle->rt, &handle->js_obj);
 
728
    free(handle);
 
729
    return NS_OK;
 
730
}
 
731
 
 
732
 
 
733
NS_METHOD       
 
734
nsCLiveconnect::ToString(JNIEnv *jEnv, jsobject obj, jstring *pjstring)
 
735
{
 
736
    if(jEnv == NULL || obj == 0)
 
737
    {
 
738
       return NS_ERROR_FAILURE;
 
739
    }
 
740
 
 
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;
 
748
 
 
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;
 
752
 
 
753
    result = NULL;
 
754
    AutoPushJSContext autopush(nsnull, cx);
 
755
    if (NS_FAILED(autopush.ResultOfPush()))
 
756
        return NS_ERROR_FAILURE;
 
757
 
 
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*");
 
763
 
 
764
    if (!jsj_exit_js(cx, jsj_env, saved_state))
 
765
        return NS_ERROR_FAILURE;
 
766
    *pjstring = result;     
 
767
    return NS_OK;
 
768
}
 
769
 
 
770
 
 
771
////////////////////////////////////////////////////////////////////////////
 
772
// from nsCLiveconnect:
 
773
 
 
774
nsCLiveconnect::nsCLiveconnect(nsISupports *aOuter)
 
775
    :   mJavaClient(NULL)
 
776
{
 
777
    NS_INIT_AGGREGATED(aOuter);
 
778
#ifdef PRESERVE_JSOBJECT_IDENTITY
 
779
    jsj_init_js_obj_reflections_table();
 
780
#endif
 
781
}
 
782
 
 
783
nsCLiveconnect::~nsCLiveconnect()
 
784
{
 
785
}