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

« back to all changes in this revision

Viewing changes to mozilla/js/src/xpconnect/src/XPCDispObject.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: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 * ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Mozilla Public License Version
 
6
 * 1.1 (the "License"); you may not use this file except in compliance with
 
7
 * the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/MPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is the IDispatch implementation for XPConnect.
 
16
 *
 
17
 * The Initial Developer of the Original Code is
 
18
 * David Bradley.
 
19
 * Portions created by the Initial Developer are Copyright (C) 2002
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the MPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
/**
 
39
 * \file XPCDispObject.cpp
 
40
 * Contains the XPCDispObject class implementation,
 
41
 * XPC_IDispatch_GetterSetter, and XPC_IDispatch_CallMethod
 
42
 */
 
43
#include "xpcprivate.h"
 
44
#include "nsIActiveXSecurityPolicy.h"
 
45
 
 
46
/**
 
47
 * This is COM's IDispatch IID, but in XPCOM's nsID type
 
48
 */
 
49
const nsID NSID_IDISPATCH = { 0x00020400, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
 
50
 
 
51
PRBool
 
52
XPCDispObject::WrapIDispatch(IDispatch *pDispatch, XPCCallContext &ccx,
 
53
                             JSObject *obj, jsval *rval)
 
54
{
 
55
    if(!pDispatch)
 
56
    {
 
57
        return PR_FALSE;
 
58
    }
 
59
 
 
60
    // Wrap the desired COM object
 
61
    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
 
62
    nsresult rv = ccx.GetXPConnect()->WrapNative(
 
63
        ccx, obj, NS_REINTERPRET_CAST(nsISupports*, pDispatch), NSID_IDISPATCH,
 
64
        getter_AddRefs(holder));
 
65
    if(NS_FAILED(rv) || !holder)
 
66
    {
 
67
        return PR_FALSE;
 
68
    }
 
69
    JSObject * jsobj;
 
70
    if(NS_FAILED(holder->GetJSObject(&jsobj)))
 
71
        return PR_FALSE;
 
72
    *rval = OBJECT_TO_JSVAL(jsobj);
 
73
    return PR_TRUE;
 
74
}
 
75
 
 
76
HRESULT XPCDispObject::SecurityCheck(XPCCallContext & ccx, const CLSID & aCID,
 
77
                                     IDispatch ** createdObject)
 
78
{
 
79
    nsresult rv;
 
80
    nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID, &rv);
 
81
    if(NS_FAILED(rv)) return E_UNEXPECTED;
 
82
 
 
83
    PRUint32 hostingFlags = nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
 
84
    dispSupport->GetHostingFlags(nsnull, &hostingFlags);
 
85
    PRBool allowSafeObjects;
 
86
    if(hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS))
 
87
        allowSafeObjects = PR_TRUE;
 
88
    else
 
89
        allowSafeObjects = PR_FALSE;
 
90
    PRBool allowAnyObjects;
 
91
    if(hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_ALL_OBJECTS))
 
92
        allowAnyObjects = PR_TRUE;
 
93
    else
 
94
        allowAnyObjects = PR_FALSE;
 
95
    if(!allowSafeObjects && !allowAnyObjects)
 
96
        return E_FAIL;
 
97
 
 
98
    PRBool classExists = PR_FALSE;
 
99
    PRBool ok = PR_FALSE;
 
100
    const nsCID & ourCID = XPCDispCLSID2nsCID(aCID);
 
101
    dispSupport->IsClassSafeToHost(ccx, ourCID, PR_FALSE, &classExists, &ok);
 
102
    if(classExists && !ok)
 
103
        return E_FAIL;
 
104
 
 
105
    // Test if the object is scriptable
 
106
    PRBool isScriptable = PR_FALSE;
 
107
    if(!allowAnyObjects)
 
108
    {
 
109
        PRBool classExists = PR_FALSE;
 
110
        dispSupport->IsClassMarkedSafeForScripting(ourCID, &classExists, &isScriptable);
 
111
        if(!classExists)
 
112
            return REGDB_E_CLASSNOTREG;
 
113
    }
 
114
 
 
115
    // Create the object
 
116
    CComPtr<IDispatch> disp;
 
117
    // If createdObject isn't null we need to create the object
 
118
    if (createdObject)
 
119
    {
 
120
        HRESULT hr = disp.CoCreateInstance(aCID);
 
121
        if(FAILED(hr))
 
122
            return hr;
 
123
        // if we don't allow just any object, and it wasn't marked 
 
124
        // safe for scripting then ask the object (MS idea of security)
 
125
        if (!allowAnyObjects && !isScriptable)
 
126
        {
 
127
            dispSupport->IsObjectSafeForScripting(disp, NSID_IDISPATCH, &isScriptable);
 
128
            if(!isScriptable)
 
129
                return E_FAIL;
 
130
        }
 
131
        disp.CopyTo(createdObject);
 
132
    }
 
133
 
 
134
    return S_OK;
 
135
}
 
136
 
 
137
HRESULT XPCDispObject::COMCreateInstance(XPCCallContext & ccx, BSTR className,
 
138
                                         PRBool enforceSecurity,
 
139
                                         IDispatch ** result)
 
140
{
 
141
    NS_ENSURE_ARG_POINTER(result);
 
142
    // Turn the string into a CLSID
 
143
    _bstr_t bstrName(className);
 
144
    CLSID classID = CLSID_NULL;
 
145
    HRESULT hr = CLSIDFromString(bstrName, &classID);
 
146
    if(FAILED(hr))
 
147
        hr = CLSIDFromProgID(bstrName, &classID);
 
148
    if(FAILED(hr) || ::IsEqualCLSID(classID, CLSID_NULL))
 
149
        return hr;
 
150
    
 
151
    // If the caller cares about security do the necessary checks
 
152
    // This results in the object being instantiated, so we'll use
 
153
    // it
 
154
    if(enforceSecurity)
 
155
        return SecurityCheck(ccx, classID, result);
 
156
    
 
157
    CComPtr<IDispatch> disp;
 
158
    hr = disp.CoCreateInstance(classID);
 
159
    if(FAILED(hr))
 
160
        return hr;
 
161
 
 
162
    disp.CopyTo(result);
 
163
 
 
164
    return S_OK;
 
165
}
 
166
 
 
167
// static
 
168
JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
 
169
                               DISPID dispID, CallMode mode, 
 
170
                               XPCDispParams * params,
 
171
                               jsval* retval,
 
172
                               XPCDispInterface::Member * member,
 
173
                               XPCJSRuntime* rt)
 
174
{
 
175
    _variant_t dispResult;
 
176
    jsval val;
 
177
    uintN err;
 
178
    uintN argc = params->GetParamCount();
 
179
    // Figure out what we're doing (getter/setter/method)
 
180
    WORD dispFlags;
 
181
    if(mode == CALL_SETTER)
 
182
    {
 
183
        dispFlags = DISPATCH_PROPERTYPUT;
 
184
    }
 
185
    else if(mode == CALL_GETTER)
 
186
    {
 
187
        dispFlags = DISPATCH_PROPERTYGET;
 
188
    }
 
189
    else
 
190
    {
 
191
        dispFlags = DISPATCH_METHOD;
 
192
    }
 
193
    HRESULT invokeResult;
 
194
    EXCEPINFO exception;
 
195
    // Scope the lock
 
196
    {
 
197
        // avoid deadlock in case the native method blocks somehow
 
198
        AutoJSSuspendRequest req(ccx);  // scoped suspend of request
 
199
        // call IDispatch's invoke
 
200
        invokeResult= disp->Invoke(
 
201
            dispID,                  // IDispatch ID
 
202
            IID_NULL,                // Reserved must be IID_NULL
 
203
            LOCALE_SYSTEM_DEFAULT,   // The locale context, use the system's
 
204
            dispFlags,               // Type of Invoke call
 
205
            params->GetDispParams(), // Parameters
 
206
            &dispResult,             // Where the result is stored
 
207
            &exception,              // Exception information
 
208
            0);                      // Index of an argument error
 
209
    }
 
210
    if(SUCCEEDED(invokeResult))
 
211
    {
 
212
        *retval = JSVAL_VOID;
 
213
        if(mode == CALL_METHOD)
 
214
        {
 
215
            NS_ASSERTION(member, "member must not be null if this is a method");
 
216
            for(PRUint32 index = 0; index < argc; ++index)
 
217
            {
 
218
                const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index);
 
219
                if(paramInfo.IsOut())
 
220
                {
 
221
                    if(!XPCDispConvert::COMToJS(ccx, params->GetParamRef(index), val, err))
 
222
                        return ThrowBadParam(err, index, ccx);
 
223
 
 
224
                    if(paramInfo.IsRetVal())
 
225
                    {
 
226
                        *retval = val;
 
227
                    }
 
228
                    else
 
229
                    {
 
230
                        jsval * argv = ccx.GetArgv();
 
231
                        // Out, in/out parameters must be objects
 
232
                        if(!JSVAL_IS_OBJECT(argv[index]) ||
 
233
                            !OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[index]),
 
234
                                rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val))
 
235
                            return ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, index, ccx);
 
236
                    }
 
237
                }
 
238
            }
 
239
        }
 
240
        if(dispResult.vt != VT_EMPTY)
 
241
        {
 
242
            if(!XPCDispConvert::COMToJS(ccx, dispResult, val, err))
 
243
            {
 
244
                ThrowBadParam(err, 0, ccx);
 
245
            }
 
246
            *retval = val;
 
247
        }
 
248
    }
 
249
    // Set the result and throw the error if one occured
 
250
    ccx.GetXPCContext()->SetLastResult(invokeResult);
 
251
 
 
252
    if(NS_FAILED(invokeResult))
 
253
    {
 
254
        XPCThrower::ThrowCOMError(ccx, invokeResult, NS_ERROR_XPC_COM_ERROR, 
 
255
                                  invokeResult == DISP_E_EXCEPTION ? 
 
256
                                      &exception : nsnull);
 
257
        return JS_FALSE;
 
258
    }
 
259
    return JS_TRUE;
 
260
}
 
261
 
 
262
JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
 
263
{
 
264
    nsresult rv = ccx.CanCallNow();
 
265
    if(NS_FAILED(rv))
 
266
    {
 
267
        // If the security manager is complaining then this is not really an
 
268
        // internal error in xpconnect. So, no reason to botch the assertion.
 
269
        NS_ASSERTION(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO, 
 
270
                     "hmm? CanCallNow failed in XPCDispObject::Invoke. "
 
271
                     "We are finding out about this late!");
 
272
        XPCThrower::Throw(rv, ccx);
 
273
        return JS_FALSE;
 
274
    }
 
275
 
 
276
    // TODO: Remove type cast and change GetIDispatchMember to use the correct type
 
277
    XPCDispInterface::Member* member = NS_REINTERPRET_CAST(XPCDispInterface::Member*,ccx.GetIDispatchMember());
 
278
    XPCJSRuntime* rt = ccx.GetRuntime();
 
279
    XPCContext* xpcc = ccx.GetXPCContext();
 
280
    XPCPerThreadData* tls = ccx.GetThreadData();
 
281
    
 
282
    jsval* argv = ccx.GetArgv();
 
283
    uintN argc = ccx.GetArgc();
 
284
 
 
285
    tls->SetException(nsnull);
 
286
    xpcc->SetLastResult(NS_ERROR_UNEXPECTED);
 
287
 
 
288
    // set up the method index and do the security check if needed
 
289
 
 
290
    PRUint32 secFlag;
 
291
    PRUint32 secAction;
 
292
 
 
293
    switch(mode)
 
294
    {
 
295
        case CALL_METHOD:
 
296
            secFlag   = nsIXPCSecurityManager::HOOK_CALL_METHOD;
 
297
            secAction = nsIXPCSecurityManager::ACCESS_CALL_METHOD;
 
298
            break;
 
299
        case CALL_GETTER:
 
300
            secFlag   = nsIXPCSecurityManager::HOOK_GET_PROPERTY;
 
301
            secAction = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
 
302
            break;
 
303
        case CALL_SETTER:
 
304
            secFlag   = nsIXPCSecurityManager::HOOK_SET_PROPERTY;
 
305
            secAction = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
 
306
            break;
 
307
        default:
 
308
            NS_ASSERTION(0,"bad value");
 
309
            return JS_FALSE;
 
310
    }
 
311
    jsval name = member->GetName();
 
312
 
 
313
    nsIXPCSecurityManager* sm = xpcc->GetAppropriateSecurityManager(secFlag);
 
314
    XPCWrappedNative* wrapper = ccx.GetWrapper();
 
315
    if(sm && NS_FAILED(sm->CanAccess(secAction, &ccx, ccx,
 
316
                                     ccx.GetFlattenedJSObject(),
 
317
                                     wrapper->GetIdentityObject(),
 
318
                                     wrapper->GetClassInfo(), name,
 
319
                                     wrapper->GetSecurityInfoAddr())))
 
320
    {
 
321
        // the security manager vetoed. It should have set an exception.
 
322
        return JS_FALSE;
 
323
    }
 
324
 
 
325
    IDispatch * pObj = NS_REINTERPRET_CAST(IDispatch*,
 
326
                                            ccx.GetTearOff()->GetNative());
 
327
    PRUint32 args = member->GetParamCount();
 
328
    uintN err;
 
329
    // Make sure setter has one argument
 
330
    if(mode == CALL_SETTER)
 
331
        args = 1;
 
332
    // Allow for optional parameters. We'll let COM handle the error if there
 
333
    // are not enough parameters
 
334
    if(argc < args)
 
335
        args = argc;
 
336
    XPCDispParams * params = new XPCDispParams(args);
 
337
    jsval val;
 
338
    // If this is a setter, we just need to convert the first parameter
 
339
    if(mode == CALL_SETTER)
 
340
    {
 
341
        params->SetNamedPropID();
 
342
        if(!XPCDispConvert::JSToCOM(ccx, argv[0], params->GetParamRef(0), err))
 
343
        {
 
344
            delete params;
 
345
            return ThrowBadParam(err, 0, ccx);
 
346
        }
 
347
    }
 
348
    else if(mode != CALL_GETTER)    // This is a function
 
349
    {
 
350
        // Convert the arguments to the function
 
351
        for(PRUint32 index = 0; index < args; ++index)
 
352
        {
 
353
            const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index);
 
354
            if(paramInfo.IsIn())
 
355
            {
 
356
                val = argv[index];
 
357
                if(paramInfo.IsOut())
 
358
                {
 
359
                    if(JSVAL_IS_PRIMITIVE(val) ||
 
360
                        !OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(val),
 
361
                                          rt->GetStringID(XPCJSRuntime::IDX_VALUE),
 
362
                                          &val))
 
363
                    {
 
364
                        delete params;
 
365
                        return ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, index, ccx);
 
366
                    }
 
367
                    paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index));
 
368
                }
 
369
                if(!XPCDispConvert::JSToCOM(ccx, val, params->GetParamRef(index), err, paramInfo.IsOut()))
 
370
                {
 
371
                    delete params;
 
372
                    return ThrowBadParam(err, index, ccx);
 
373
                }
 
374
            }
 
375
            else
 
376
            {
 
377
                paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index));
 
378
            }
 
379
        }
 
380
    }
 
381
    // If this is a parameterized property
 
382
    if(member->IsParameterizedProperty())
 
383
    {
 
384
        // We need to get a parameterized property object to return to JS
 
385
        // NewInstance takes ownership of params
 
386
        if(XPCDispParamPropJSClass::NewInstance(ccx, wrapper,
 
387
                                                member->GetDispID(),
 
388
                                                params, &val))
 
389
        {
 
390
            ccx.SetRetVal(val);
 
391
            if(!JS_IdToValue(ccx, 1, &val))
 
392
            {
 
393
                // This shouldn't fail
 
394
                NS_ERROR("JS_IdToValue failed in XPCDispParamPropJSClass::NewInstance");
 
395
                return JS_FALSE;
 
396
            }
 
397
            JS_SetCallReturnValue2(ccx, val);
 
398
            return JS_TRUE;
 
399
        }
 
400
        // NewInstance would only fail if there was an out of memory problem
 
401
        JS_ReportOutOfMemory(ccx);
 
402
        delete params;
 
403
        return JS_FALSE;
 
404
    }
 
405
    JSBool retval = Dispatch(ccx, pObj, member->GetDispID(), mode, params, &val, member, rt);
 
406
    if(retval && mode == CALL_SETTER)
 
407
    {
 
408
        ccx.SetRetVal(argv[0]);
 
409
    }
 
410
    else
 
411
    {
 
412
        ccx.SetRetVal(val);
 
413
    }
 
414
    delete params;
 
415
    return retval;
 
416
}
 
417
 
 
418
static
 
419
JSBool GetMember(XPCCallContext& ccx, JSObject* funobj, XPCNativeInterface*& iface, XPCDispInterface::Member*& member)
 
420
{
 
421
    // We expect funobj to be a clone, we need the real funobj.
 
422
    JSFunction* fun = (JSFunction*) JS_GetPrivate(ccx, funobj);
 
423
    if(!fun)
 
424
        return JS_FALSE;
 
425
    JSObject* realFunObj = JS_GetFunctionObject(fun);
 
426
    if(!realFunObj)
 
427
        return JS_FALSE;
 
428
    jsval val;
 
429
    if(!JS_GetReservedSlot(ccx, realFunObj, 1, &val))
 
430
        return JS_FALSE;
 
431
    if(!JSVAL_IS_INT(val))
 
432
        return JS_FALSE;
 
433
    iface = NS_REINTERPRET_CAST(XPCNativeInterface*,JSVAL_TO_PRIVATE(val));
 
434
    if(!JS_GetReservedSlot(ccx, realFunObj, 0, &val))
 
435
        return JS_FALSE;
 
436
    if(!JSVAL_IS_INT(val))
 
437
        return JS_FALSE;
 
438
    member = NS_REINTERPRET_CAST(XPCDispInterface::Member*,JSVAL_TO_PRIVATE(val));
 
439
    return JS_TRUE;
 
440
}
 
441
 
 
442
// Handy macro used in callbacks below.
 
443
#define THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper)                         \
 
444
    PR_BEGIN_MACRO                                                           \
 
445
    if(!wrapper)                                                             \
 
446
    {                                                                        \
 
447
        XPCThrower::Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);              \
 
448
        return JS_FALSE;                                                     \
 
449
    }                                                                        \
 
450
    if(!wrapper->IsValid())                                                  \
 
451
    {                                                                        \
 
452
        XPCThrower::Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx);               \
 
453
        return JS_FALSE;                                                     \
 
454
    }                                                                        \
 
455
    PR_END_MACRO
 
456
 
 
457
/**
 
458
 * Callback for functions
 
459
 * This callback is called by JS when a function on a JSObject proxying
 
460
 * for an IDispatch instance
 
461
 * @param cx A pointer to a JS context
 
462
 * @param obj JS object that the parameterized property is on
 
463
 * @param argc Number of arguments in this call
 
464
 * @param argv The parameters passed in if any
 
465
 * @param vp The return value
 
466
 * @return Returns JS_TRUE if the operation succeeded
 
467
 */
 
468
JSBool JS_DLL_CALLBACK
 
469
XPC_IDispatch_CallMethod(JSContext* cx, JSObject* obj, uintN argc,
 
470
                         jsval* argv, jsval* vp)
 
471
{
 
472
    NS_ASSERTION(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION, "bad function");
 
473
    JSObject* funobj = JSVAL_TO_OBJECT(argv[-2]);
 
474
    XPCCallContext ccx(JS_CALLER, cx, obj, funobj, 0, argc, argv, vp);
 
475
    XPCWrappedNative* wrapper = ccx.GetWrapper();
 
476
    THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
477
    ccx.SetArgsAndResultPtr(argc, argv, vp);
 
478
 
 
479
    XPCDispInterface::Member* member;
 
480
    XPCNativeInterface* iface;
 
481
#ifdef DEBUG
 
482
    PRBool ok =
 
483
#endif
 
484
    GetMember(ccx, funobj, iface, member);
 
485
    NS_ASSERTION(ok, "GetMember faild in XPC_IDispatch_CallMethod");
 
486
    ccx.SetIDispatchInfo(iface, member);
 
487
 
 
488
    return XPCDispObject::Invoke(ccx, XPCDispObject::CALL_METHOD);
 
489
}
 
490
 
 
491
/**
 
492
 * Callback for properties
 
493
 * This callback is called by JS when a property is set or retrieved on a 
 
494
 * JSObject proxying for an IDispatch instance
 
495
 * @param cx A pointer to a JS context
 
496
 * @param obj JS object that the parameterized property is on
 
497
 * @param argc Number of arguments in this call
 
498
 * @param argv The parameters passed in if any
 
499
 * @param vp The return value
 
500
 * @return Returns JS_TRUE if the operation succeeded
 
501
 */
 
502
JSBool JS_DLL_CALLBACK
 
503
XPC_IDispatch_GetterSetter(JSContext *cx, JSObject *obj, uintN argc,
 
504
                           jsval *argv, jsval *vp)
 
505
{
 
506
    NS_ASSERTION(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION, "bad function");
 
507
    JSObject* funobj = JSVAL_TO_OBJECT(argv[-2]);
 
508
 
 
509
    XPCCallContext ccx(JS_CALLER, cx, obj, funobj);
 
510
    XPCWrappedNative* wrapper = ccx.GetWrapper();
 
511
    THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
512
 
 
513
    ccx.SetArgsAndResultPtr(argc, argv, vp);
 
514
    XPCDispInterface::Member* member;
 
515
    XPCNativeInterface* iface;
 
516
#ifdef DEBUG
 
517
    PRBool ok =
 
518
#endif
 
519
    GetMember(ccx, funobj, iface, member);
 
520
    NS_ASSERTION(ok, "GetMember faild in XPC_IDispatch_CallMethod");
 
521
 
 
522
    ccx.SetIDispatchInfo(iface, member);
 
523
    return XPCDispObject::Invoke(ccx, argc != 0 ? XPCDispObject::CALL_SETTER : XPCDispObject::CALL_GETTER);
 
524
}