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

« back to all changes in this revision

Viewing changes to mozilla/js/src/xpconnect/src/xpcjsid.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
 *
 
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
 *   John Bandhauer <jband@netscape.com> (original author)
 
26
 *   Pierre Phaneuf <pp@ludusdesign.com>
 
27
 *
 
28
 * Alternatively, the contents of this file may be used under the terms of
 
29
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 
30
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
31
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
32
 * of those above. If you wish to allow use of your version of this file only
 
33
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
34
 * use your version of this file under the terms of the MPL, indicate your
 
35
 * decision by deleting the provisions above and replace them with the notice
 
36
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
37
 * the provisions above, a recipient may use your version of this file under
 
38
 * the terms of any one of the MPL, the GPL or the LGPL.
 
39
 *
 
40
 * ***** END LICENSE BLOCK ***** */
 
41
 
 
42
/* An xpcom implementation of the JavaScript nsIID and nsCID objects. */
 
43
 
 
44
#include "xpcprivate.h"
 
45
 
 
46
/***************************************************************************/
 
47
// nsJSID
 
48
 
 
49
NS_IMPL_THREADSAFE_ISUPPORTS1(nsJSID, nsIJSID)
 
50
 
 
51
char nsJSID::gNoString[] = "";
 
52
 
 
53
nsJSID::nsJSID()
 
54
    : mID(GetInvalidIID()), mNumber(gNoString), mName(gNoString)
 
55
{
 
56
}
 
57
 
 
58
nsJSID::~nsJSID()
 
59
{
 
60
    if(mNumber && mNumber != gNoString)
 
61
        PR_Free(mNumber);
 
62
    if(mName && mName != gNoString)
 
63
        PR_Free(mName);
 
64
}
 
65
 
 
66
void nsJSID::Reset()
 
67
{
 
68
    mID = GetInvalidIID();
 
69
 
 
70
    if(mNumber && mNumber != gNoString)
 
71
        PR_Free(mNumber);
 
72
    if(mName && mName != gNoString)
 
73
        PR_Free(mName);
 
74
 
 
75
    mNumber = mName = nsnull;
 
76
}
 
77
 
 
78
PRBool
 
79
nsJSID::SetName(const char* name)
 
80
{
 
81
    NS_ASSERTION(!mName || mName == gNoString ,"name already set");
 
82
    NS_ASSERTION(name,"null name");
 
83
    int len = strlen(name)+1;
 
84
    mName = (char*)PR_Malloc(len);
 
85
    if(!mName)
 
86
        return PR_FALSE;
 
87
    memcpy(mName, name, len);
 
88
    return PR_TRUE;
 
89
}
 
90
 
 
91
NS_IMETHODIMP
 
92
nsJSID::GetName(char * *aName)
 
93
{
 
94
    if(!aName)
 
95
        return NS_ERROR_NULL_POINTER;
 
96
 
 
97
    if(!NameIsSet())
 
98
        SetNameToNoString();
 
99
    NS_ASSERTION(mName, "name not set");
 
100
    *aName = (char*) nsMemory::Clone(mName, strlen(mName)+1);
 
101
    return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 
102
}
 
103
 
 
104
NS_IMETHODIMP
 
105
nsJSID::GetNumber(char * *aNumber)
 
106
{
 
107
    if(!aNumber)
 
108
        return NS_ERROR_NULL_POINTER;
 
109
 
 
110
    if(!mNumber)
 
111
    {
 
112
        if(!(mNumber = mID.ToString()))
 
113
            mNumber = gNoString;
 
114
    }
 
115
 
 
116
    *aNumber = (char*) nsMemory::Clone(mNumber, strlen(mNumber)+1);
 
117
    return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 
118
}
 
119
 
 
120
NS_IMETHODIMP
 
121
nsJSID::GetId(nsID* *aId)
 
122
{
 
123
    if(!aId)
 
124
        return NS_ERROR_NULL_POINTER;
 
125
 
 
126
    *aId = (nsID*) nsMemory::Clone(&mID, sizeof(nsID));
 
127
    return *aId ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 
128
}
 
129
 
 
130
NS_IMETHODIMP
 
131
nsJSID::GetValid(PRBool *aValid)
 
132
{
 
133
    if(!aValid)
 
134
        return NS_ERROR_NULL_POINTER;
 
135
 
 
136
    *aValid = IsValid();
 
137
    return NS_OK;
 
138
}
 
139
 
 
140
NS_IMETHODIMP
 
141
nsJSID::Equals(nsIJSID *other, PRBool *_retval)
 
142
{
 
143
    if(!_retval)
 
144
        return NS_ERROR_NULL_POINTER;
 
145
 
 
146
    *_retval = PR_FALSE;
 
147
 
 
148
    if(!other || mID.Equals(GetInvalidIID()))
 
149
        return NS_OK;
 
150
 
 
151
    nsID* otherID;
 
152
    if(NS_SUCCEEDED(other->GetId(&otherID)))
 
153
    {
 
154
        *_retval = mID.Equals(*otherID);
 
155
        nsMemory::Free(otherID);
 
156
    }
 
157
    return NS_OK;
 
158
}
 
159
 
 
160
NS_IMETHODIMP
 
161
nsJSID::Initialize(const char *idString)
 
162
{
 
163
    if(!idString)
 
164
        return NS_ERROR_NULL_POINTER;
 
165
 
 
166
    PRBool success = PR_FALSE;
 
167
 
 
168
    if(strlen(idString) && mID.Equals(GetInvalidIID()))
 
169
    {
 
170
        Reset();
 
171
 
 
172
        if(idString[0] == '{')
 
173
        {
 
174
            nsID id;
 
175
            if(id.Parse((char*)idString))
 
176
            {
 
177
                mID = id;
 
178
                success = PR_TRUE;
 
179
            }
 
180
        }
 
181
    }
 
182
    return success ? NS_OK : NS_ERROR_FAILURE;
 
183
}
 
184
 
 
185
PRBool
 
186
nsJSID::InitWithName(const nsID& id, const char *nameString)
 
187
{
 
188
    NS_ASSERTION(nameString, "no name");
 
189
    Reset();
 
190
    mID = id;
 
191
    return SetName(nameString);
 
192
}
 
193
 
 
194
// try to use the name, if no name, then use the number
 
195
NS_IMETHODIMP
 
196
nsJSID::ToString(char **_retval)
 
197
{
 
198
    if(mName != gNoString)
 
199
    {
 
200
        char* str;
 
201
        if(NS_SUCCEEDED(GetName(&str)))
 
202
        {
 
203
            if(mName != gNoString)
 
204
            {
 
205
                *_retval = str;
 
206
                return NS_OK;
 
207
            }
 
208
            else
 
209
                nsMemory::Free(str);
 
210
        }
 
211
    }
 
212
    return GetNumber(_retval);
 
213
}
 
214
 
 
215
const nsID&
 
216
nsJSID::GetInvalidIID() const
 
217
{
 
218
    // {BB1F47B0-D137-11d2-9841-006008962422}
 
219
    static nsID invalid = {0xbb1f47b0, 0xd137, 0x11d2,
 
220
                            {0x98, 0x41, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22}};
 
221
    return invalid;
 
222
}
 
223
 
 
224
//static
 
225
nsJSID*
 
226
nsJSID::NewID(const char* str)
 
227
{
 
228
    if(!str)
 
229
    {
 
230
        NS_ASSERTION(0,"no string");
 
231
        return nsnull;
 
232
    }
 
233
 
 
234
    nsJSID* idObj = new nsJSID();
 
235
    if(idObj)
 
236
    {
 
237
        NS_ADDREF(idObj);
 
238
        if(NS_FAILED(idObj->Initialize(str)))
 
239
            NS_RELEASE(idObj);
 
240
    }
 
241
    return idObj;
 
242
}
 
243
 
 
244
/***************************************************************************/
 
245
// Class object support so that we can share prototypes of wrapper
 
246
 
 
247
// This class exists just so we can have a shared scriptable helper for
 
248
// the nsJSIID class. The instances implement their own helpers. But we
 
249
// needed to be able to indicate to the shared prototypes this single flag:
 
250
// nsIXPCScriptable::DONT_ENUM_STATIC_PROPS. And having a class to do it is
 
251
// the only means we have. Setting this flag on any given instance scriptable
 
252
// helper is not sufficient to convey the information that we don't want
 
253
// static properties enumerated on the shared proto.
 
254
 
 
255
class SharedScriptableHelperForJSIID : public nsIXPCScriptable
 
256
{
 
257
public:
 
258
    NS_DECL_ISUPPORTS
 
259
    NS_DECL_NSIXPCSCRIPTABLE
 
260
    SharedScriptableHelperForJSIID() {}
 
261
};
 
262
 
 
263
NS_INTERFACE_MAP_BEGIN(SharedScriptableHelperForJSIID)
 
264
  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
 
265
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
 
266
NS_INTERFACE_MAP_END_THREADSAFE
 
267
 
 
268
NS_IMPL_THREADSAFE_ADDREF(SharedScriptableHelperForJSIID)
 
269
NS_IMPL_THREADSAFE_RELEASE(SharedScriptableHelperForJSIID)
 
270
 
 
271
// The nsIXPCScriptable map declaration that will generate stubs for us...
 
272
#define XPC_MAP_CLASSNAME           SharedScriptableHelperForJSIID
 
273
#define XPC_MAP_QUOTED_CLASSNAME   "JSIID"
 
274
#define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
 
275
                                    nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
 
276
#include "xpc_map_end.h" /* This will #undef the above */
 
277
 
 
278
static nsIXPCScriptable* gSharedScriptableHelperForJSIID;
 
279
 
 
280
NS_METHOD GetSharedScriptableHelperForJSIID(PRUint32 language,
 
281
                                            nsISupports **helper)
 
282
{
 
283
    if(language == nsIProgrammingLanguage::JAVASCRIPT)
 
284
    {
 
285
        NS_IF_ADDREF(gSharedScriptableHelperForJSIID);
 
286
        *helper = gSharedScriptableHelperForJSIID;
 
287
    }
 
288
    else
 
289
        *helper = nsnull;
 
290
    return NS_OK;
 
291
}
 
292
 
 
293
/******************************************************/
 
294
 
 
295
static JSBool gClassObjectsWereKilled = JS_FALSE;
 
296
static JSBool gClassObjectsWereInited = JS_FALSE;
 
297
 
 
298
NS_DECL_CI_INTERFACE_GETTER(nsJSIID)
 
299
// Can't make this static. http://bugzilla.mozilla.org/show_bug.cgi?id=81436
 
300
nsIClassInfo* NS_CLASSINFO_NAME(nsJSIID);
 
301
static const nsModuleComponentInfo CI_nsJSIID =
 
302
    {"JSIID",
 
303
     {0x26ecb8d0, 0x35c9, 0x11d5, { 0x90, 0xb2, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a }},
 
304
     nsnull, nsnull, nsnull,nsnull, nsnull,
 
305
     NS_CI_INTERFACE_GETTER_NAME(nsJSIID),
 
306
     GetSharedScriptableHelperForJSIID,
 
307
     &NS_CLASSINFO_NAME(nsJSIID), 0};
 
308
 
 
309
NS_DECL_CI_INTERFACE_GETTER(nsJSCID)
 
310
// Can't make this static. http://bugzilla.mozilla.org/show_bug.cgi?id=81436
 
311
nsIClassInfo* NS_CLASSINFO_NAME(nsJSCID);
 
312
static const nsModuleComponentInfo CI_nsJSCID =
 
313
    {"JSCID",
 
314
     {0x9255b5b0, 0x35cf, 0x11d5, { 0x90, 0xb2, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a }},
 
315
     nsnull, nsnull, nsnull,nsnull, nsnull,
 
316
     NS_CI_INTERFACE_GETTER_NAME(nsJSCID), nsnull,
 
317
     &NS_CLASSINFO_NAME(nsJSCID), 0};
 
318
 
 
319
JSBool xpc_InitJSxIDClassObjects()
 
320
{
 
321
    if(gClassObjectsWereKilled)
 
322
        return JS_FALSE;
 
323
    if(gClassObjectsWereInited)
 
324
        return JS_TRUE;
 
325
 
 
326
    nsresult rv = NS_OK;
 
327
 
 
328
    if(!NS_CLASSINFO_NAME(nsJSIID))
 
329
    {
 
330
        nsCOMPtr<nsIGenericFactory> factory;
 
331
        rv = NS_NewGenericFactory(getter_AddRefs(factory), &CI_nsJSIID);
 
332
        if(NS_FAILED(rv))
 
333
            goto return_failure;
 
334
        rv = factory->QueryInterface(NS_GET_IID(nsIClassInfo),
 
335
                                     (void**)&NS_CLASSINFO_NAME(nsJSIID));
 
336
        if(NS_FAILED(rv))
 
337
            goto return_failure;
 
338
    }
 
339
 
 
340
    if(!NS_CLASSINFO_NAME(nsJSCID))
 
341
    {
 
342
        nsCOMPtr<nsIGenericFactory> factory;
 
343
        rv = NS_NewGenericFactory(getter_AddRefs(factory), &CI_nsJSCID);
 
344
        if(NS_FAILED(rv))
 
345
            goto return_failure;
 
346
        rv = factory->QueryInterface(NS_GET_IID(nsIClassInfo),
 
347
                                     (void**)&NS_CLASSINFO_NAME(nsJSCID));
 
348
        if(NS_FAILED(rv))
 
349
            goto return_failure;
 
350
    }
 
351
 
 
352
    gSharedScriptableHelperForJSIID = new SharedScriptableHelperForJSIID();
 
353
    if(!gSharedScriptableHelperForJSIID)
 
354
        goto return_failure;
 
355
    NS_ADDREF(gSharedScriptableHelperForJSIID);
 
356
 
 
357
    gClassObjectsWereInited = JS_TRUE;
 
358
    return JS_TRUE;
 
359
return_failure:
 
360
    return JS_FALSE;
 
361
}
 
362
 
 
363
void xpc_DestroyJSxIDClassObjects()
 
364
{
 
365
    NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSIID));
 
366
    NS_IF_RELEASE(NS_CLASSINFO_NAME(nsJSCID));
 
367
    NS_IF_RELEASE(gSharedScriptableHelperForJSIID);
 
368
 
 
369
    gClassObjectsWereKilled = JS_TRUE;
 
370
}
 
371
 
 
372
/***************************************************************************/
 
373
 
 
374
NS_INTERFACE_MAP_BEGIN(nsJSIID)
 
375
  NS_INTERFACE_MAP_ENTRY(nsIJSID)
 
376
  NS_INTERFACE_MAP_ENTRY(nsIJSIID)
 
377
  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
 
378
#ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
 
379
  NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
 
380
#endif
 
381
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
 
382
  NS_IMPL_QUERY_CLASSINFO(nsJSIID)
 
383
NS_INTERFACE_MAP_END_THREADSAFE
 
384
 
 
385
NS_IMPL_THREADSAFE_ADDREF(nsJSIID)
 
386
NS_IMPL_THREADSAFE_RELEASE(nsJSIID)
 
387
NS_IMPL_CI_INTERFACE_GETTER2(nsJSIID, nsIJSID, nsIJSIID)
 
388
 
 
389
// The nsIXPCScriptable map declaration that will generate stubs for us...
 
390
#define XPC_MAP_CLASSNAME           nsJSIID
 
391
#define XPC_MAP_QUOTED_CLASSNAME   "nsJSIID"
 
392
#define                             XPC_MAP_WANT_NEWRESOLVE
 
393
#define                             XPC_MAP_WANT_ENUMERATE
 
394
#define                             XPC_MAP_WANT_HASINSTANCE
 
395
#define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
 
396
                                    nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
 
397
#include "xpc_map_end.h" /* This will #undef the above */
 
398
 
 
399
 
 
400
nsJSIID::nsJSIID(nsIInterfaceInfo* aInfo)
 
401
    : mInfo(aInfo)
 
402
{
 
403
}
 
404
 
 
405
nsJSIID::~nsJSIID() {}
 
406
 
 
407
// If mInfo is present we use it and ignore mDetails, else we use mDetails.
 
408
 
 
409
NS_IMETHODIMP nsJSIID::GetName(char * *aName)
 
410
{
 
411
    return mInfo->GetName(aName);    
 
412
}
 
413
 
 
414
NS_IMETHODIMP nsJSIID::GetNumber(char * *aNumber)
 
415
{
 
416
    const nsIID* id;
 
417
    mInfo->GetIIDShared(&id);
 
418
    char* str = id->ToString();
 
419
    if(!str)
 
420
        return NS_ERROR_OUT_OF_MEMORY;
 
421
    *aNumber = (char*) nsMemory::Clone(str, strlen(str)+1);
 
422
    PR_Free(str);
 
423
    return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 
424
}        
 
425
 
 
426
NS_IMETHODIMP nsJSIID::GetId(nsID* *aId)
 
427
{
 
428
    return mInfo->GetInterfaceIID((nsIID**)aId);
 
429
}
 
430
 
 
431
NS_IMETHODIMP nsJSIID::GetValid(PRBool *aValid)
 
432
{
 
433
    *aValid = PR_TRUE;
 
434
    return NS_OK;
 
435
}
 
436
 
 
437
NS_IMETHODIMP nsJSIID::Equals(nsIJSID *other, PRBool *_retval)
 
438
{
 
439
    nsID* otherID;
 
440
    if(NS_SUCCEEDED(other->GetId(&otherID)))
 
441
    {
 
442
        mInfo->IsIID((nsIID*)otherID, _retval);
 
443
        nsMemory::Free(otherID);
 
444
    }
 
445
    return NS_OK;
 
446
}
 
447
 
 
448
NS_IMETHODIMP nsJSIID::Initialize(const char *idString)
 
449
{
 
450
    return NS_ERROR_FAILURE;
 
451
}
 
452
 
 
453
NS_IMETHODIMP nsJSIID::ToString(char **_retval)
 
454
{
 
455
    return mInfo->GetName(_retval);    
 
456
}
 
457
 
 
458
// static 
 
459
nsJSIID* 
 
460
nsJSIID::NewID(nsIInterfaceInfo* aInfo)
 
461
{
 
462
    if(!aInfo)
 
463
    {
 
464
        NS_ERROR("no info");
 
465
        return nsnull;
 
466
    }
 
467
 
 
468
    PRBool canScript;
 
469
    if(NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)
 
470
        return nsnull;
 
471
 
 
472
    nsJSIID* idObj = new nsJSIID(aInfo);
 
473
    NS_IF_ADDREF(idObj);
 
474
    return idObj;
 
475
}
 
476
 
 
477
 
 
478
/* PRBool resolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id); */
 
479
NS_IMETHODIMP
 
480
nsJSIID::NewResolve(nsIXPConnectWrappedNative *wrapper,
 
481
                    JSContext * cx, JSObject * obj,
 
482
                    jsval id, PRUint32 flags,
 
483
                    JSObject * *objp, PRBool *_retval)
 
484
{
 
485
    XPCCallContext ccx(JS_CALLER, cx);
 
486
 
 
487
    AutoMarkingNativeInterfacePtr iface(ccx);
 
488
 
 
489
    const nsIID* iid;
 
490
    mInfo->GetIIDShared(&iid);
 
491
 
 
492
    iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
 
493
 
 
494
    if(!iface)
 
495
        return NS_OK;
 
496
 
 
497
    XPCNativeMember* member = iface->FindMember(id);
 
498
    if(member && member->IsConstant())
 
499
    {
 
500
        jsval val;
 
501
        if(!member->GetValue(ccx, iface, &val))
 
502
            return NS_ERROR_OUT_OF_MEMORY;
 
503
 
 
504
        jsid idid;
 
505
        if(!JS_ValueToId(cx, id, &idid))
 
506
            return NS_ERROR_OUT_OF_MEMORY;
 
507
 
 
508
        *objp = obj;
 
509
        *_retval = OBJ_DEFINE_PROPERTY(cx, obj, idid, val,
 
510
                                       nsnull, nsnull,
 
511
                                       JSPROP_ENUMERATE |
 
512
                                       JSPROP_READONLY |
 
513
                                       JSPROP_PERMANENT,
 
514
                                       nsnull);
 
515
    }
 
516
 
 
517
    return NS_OK;
 
518
}
 
519
 
 
520
/* PRBool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */
 
521
NS_IMETHODIMP
 
522
nsJSIID::Enumerate(nsIXPConnectWrappedNative *wrapper,
 
523
                   JSContext * cx, JSObject * obj, PRBool *_retval)
 
524
{
 
525
    // In this case, let's just eagerly resolve...
 
526
 
 
527
    XPCCallContext ccx(JS_CALLER, cx);
 
528
 
 
529
    AutoMarkingNativeInterfacePtr iface(ccx);
 
530
 
 
531
    const nsIID* iid;
 
532
    mInfo->GetIIDShared(&iid);
 
533
 
 
534
    iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
 
535
 
 
536
    if(!iface)
 
537
        return NS_OK;
 
538
 
 
539
    PRUint16 count = iface->GetMemberCount();
 
540
    for(PRUint16 i = 0; i < count; i++)
 
541
    {
 
542
        XPCNativeMember* member = iface->GetMemberAt(i);
 
543
        if(member && member->IsConstant() &&
 
544
           !xpc_ForcePropertyResolve(cx, obj, member->GetName()))
 
545
        {
 
546
            return NS_ERROR_UNEXPECTED;
 
547
        }
 
548
    }
 
549
    return NS_OK;
 
550
}
 
551
 
 
552
/* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
 
553
NS_IMETHODIMP
 
554
nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
 
555
                     JSContext * cx, JSObject * obj,
 
556
                     jsval val, PRBool *bp, PRBool *_retval)
 
557
{
 
558
    *bp = JS_FALSE;
 
559
    nsresult rv = NS_OK;
 
560
 
 
561
    if(!JSVAL_IS_PRIMITIVE(val))
 
562
    {
 
563
        // we have a JSObject
 
564
        JSObject* obj = JSVAL_TO_OBJECT(val);
 
565
 
 
566
        NS_ASSERTION(obj, "when is an object not an object?");
 
567
 
 
568
        // is this really a native xpcom object with a wrapper?
 
569
        XPCWrappedNative* other_wrapper =
 
570
           XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
 
571
 
 
572
        if(!other_wrapper)
 
573
            return NS_OK;
 
574
 
 
575
        const nsIID* iid;
 
576
        mInfo->GetIIDShared(&iid);
 
577
 
 
578
        // We'll trust the interface set of the wrapper if this is known
 
579
        // to be an interface that the objects *expects* to be able to
 
580
        // handle.
 
581
        if(other_wrapper->HasInterfaceNoQI(*iid))
 
582
        {
 
583
            *bp = JS_TRUE;
 
584
            return NS_OK;
 
585
        }
 
586
 
 
587
        // Otherwise, we'll end up Querying the native object to be sure.
 
588
        XPCCallContext ccx(JS_CALLER, cx);
 
589
 
 
590
        AutoMarkingNativeInterfacePtr iface(ccx);
 
591
        iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
 
592
 
 
593
        if(iface && other_wrapper->FindTearOff(ccx, iface))
 
594
            *bp = JS_TRUE;
 
595
    }
 
596
    return rv;
 
597
}
 
598
 
 
599
#ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
 
600
/* string canCreateWrapper (in nsIIDPtr iid); */
 
601
NS_IMETHODIMP
 
602
nsJSIID::CanCreateWrapper(const nsIID * iid, char **_retval)
 
603
{
 
604
    // We let anyone do this...
 
605
    *_retval = xpc_CloneAllAccess();
 
606
    return NS_OK;
 
607
}
 
608
 
 
609
/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
 
610
NS_IMETHODIMP
 
611
nsJSIID::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
 
612
{
 
613
    static const char* allowed[] = {"equals", "toString", nsnull};
 
614
 
 
615
    *_retval = xpc_CheckAccessList(methodName, allowed);
 
616
    return NS_OK;
 
617
}
 
618
 
 
619
/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
 
620
NS_IMETHODIMP
 
621
nsJSIID::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
 
622
{
 
623
    static const char* allowed[] = {"name", "number", "valid", nsnull};
 
624
    *_retval = xpc_CheckAccessList(propertyName, allowed);
 
625
    return NS_OK;
 
626
}
 
627
 
 
628
/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
 
629
NS_IMETHODIMP
 
630
nsJSIID::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
 
631
{
 
632
    // If you have to ask, then the answer is NO
 
633
    *_retval = nsnull;
 
634
    return NS_OK;
 
635
}
 
636
#endif
 
637
 
 
638
/***************************************************************************/
 
639
 
 
640
NS_INTERFACE_MAP_BEGIN(nsJSCID)
 
641
  NS_INTERFACE_MAP_ENTRY(nsIJSID)
 
642
  NS_INTERFACE_MAP_ENTRY(nsIJSCID)
 
643
  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
 
644
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
 
645
  NS_IMPL_QUERY_CLASSINFO(nsJSCID)
 
646
NS_INTERFACE_MAP_END_THREADSAFE
 
647
 
 
648
NS_IMPL_THREADSAFE_ADDREF(nsJSCID)
 
649
NS_IMPL_THREADSAFE_RELEASE(nsJSCID)
 
650
NS_IMPL_CI_INTERFACE_GETTER2(nsJSCID, nsIJSID, nsIJSCID)
 
651
 
 
652
// The nsIXPCScriptable map declaration that will generate stubs for us...
 
653
#define XPC_MAP_CLASSNAME           nsJSCID
 
654
#define XPC_MAP_QUOTED_CLASSNAME   "nsJSCID"
 
655
#define                             XPC_MAP_WANT_CONSTRUCT
 
656
#define                             XPC_MAP_WANT_HASINSTANCE
 
657
#define XPC_MAP_FLAGS               0
 
658
#include "xpc_map_end.h" /* This will #undef the above */
 
659
 
 
660
nsJSCID::nsJSCID()  {}
 
661
nsJSCID::~nsJSCID() {}
 
662
 
 
663
NS_IMETHODIMP nsJSCID::GetName(char * *aName)
 
664
    {ResolveName(); return mDetails.GetName(aName);}
 
665
 
 
666
NS_IMETHODIMP nsJSCID::GetNumber(char * *aNumber)
 
667
    {return mDetails.GetNumber(aNumber);}
 
668
 
 
669
NS_IMETHODIMP nsJSCID::GetId(nsID* *aId)
 
670
    {return mDetails.GetId(aId);}
 
671
 
 
672
NS_IMETHODIMP nsJSCID::GetValid(PRBool *aValid)
 
673
    {return mDetails.GetValid(aValid);}
 
674
 
 
675
NS_IMETHODIMP nsJSCID::Equals(nsIJSID *other, PRBool *_retval)
 
676
    {return mDetails.Equals(other, _retval);}
 
677
 
 
678
NS_IMETHODIMP nsJSCID::Initialize(const char *idString)
 
679
    {return mDetails.Initialize(idString);}
 
680
 
 
681
NS_IMETHODIMP nsJSCID::ToString(char **_retval)
 
682
    {ResolveName(); return mDetails.ToString(_retval);}
 
683
 
 
684
void
 
685
nsJSCID::ResolveName()
 
686
{
 
687
    if(!mDetails.NameIsSet())
 
688
        mDetails.SetNameToNoString();
 
689
}
 
690
 
 
691
//static
 
692
nsJSCID*
 
693
nsJSCID::NewID(const char* str)
 
694
{
 
695
    if(!str)
 
696
    {
 
697
        NS_ASSERTION(0,"no string");
 
698
        return nsnull;
 
699
    }
 
700
 
 
701
    nsJSCID* idObj = new nsJSCID();
 
702
    if(idObj)
 
703
    {
 
704
        PRBool success = PR_FALSE;
 
705
        NS_ADDREF(idObj);
 
706
 
 
707
        if(str[0] == '{')
 
708
        {
 
709
            if(NS_SUCCEEDED(idObj->Initialize(str)))
 
710
                success = PR_TRUE;
 
711
        }
 
712
        else
 
713
        {
 
714
            nsCID cid;
 
715
            if(NS_SUCCEEDED(nsComponentManager::ContractIDToClassID(str, &cid)))
 
716
            {
 
717
                success = idObj->mDetails.InitWithName(cid, str);
 
718
            }
 
719
        }
 
720
        if(!success)
 
721
            NS_RELEASE(idObj);
 
722
    }
 
723
    return idObj;
 
724
}
 
725
 
 
726
 
 
727
/* nsISupports createInstance (); */
 
728
NS_IMETHODIMP
 
729
nsJSCID::CreateInstance(nsISupports **_retval)
 
730
{
 
731
    if(!mDetails.IsValid())
 
732
        return NS_ERROR_XPC_BAD_CID;
 
733
 
 
734
    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
 
735
    if(!xpc)
 
736
        return NS_ERROR_UNEXPECTED;
 
737
 
 
738
    nsCOMPtr<nsIXPCNativeCallContext> ccxp;
 
739
    xpc->GetCurrentNativeCallContext(getter_AddRefs(ccxp));
 
740
    if(!ccxp)
 
741
        return NS_ERROR_UNEXPECTED;
 
742
 
 
743
    PRUint32 argc;
 
744
    jsval * argv;
 
745
    jsval * vp;
 
746
    JSContext* cx;
 
747
    JSObject* obj;
 
748
 
 
749
    ccxp->GetJSContext(&cx);
 
750
    ccxp->GetArgc(&argc);
 
751
    ccxp->GetArgvPtr(&argv);
 
752
    ccxp->GetRetValPtr(&vp);
 
753
 
 
754
    nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
 
755
    ccxp->GetCalleeWrapper(getter_AddRefs(wrapper));
 
756
    wrapper->GetJSObject(&obj);
 
757
 
 
758
    // Do the security check if necessary
 
759
 
 
760
    XPCContext* xpcc = nsXPConnect::GetContext(cx);
 
761
 
 
762
    nsIXPCSecurityManager* sm;
 
763
    sm = xpcc->GetAppropriateSecurityManager(
 
764
                        nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
 
765
    if(sm && NS_FAILED(sm->CanCreateInstance(cx, *mDetails.GetID())))
 
766
    {
 
767
        // the security manager vetoed. It should have set an exception.
 
768
        ccxp->SetExceptionWasThrown(JS_TRUE);
 
769
        return NS_OK;
 
770
    }
 
771
 
 
772
    nsID iid;
 
773
 
 
774
    // If an IID was passed in then use it
 
775
    if(argc)
 
776
    {
 
777
        JSObject* iidobj;
 
778
        jsval val = *argv;
 
779
        nsID* piid = nsnull;
 
780
        if(JSVAL_IS_PRIMITIVE(val) ||
 
781
           !(iidobj = JSVAL_TO_OBJECT(val)) ||
 
782
           !(piid = xpc_JSObjectToID(cx, iidobj)))
 
783
        {
 
784
            return NS_ERROR_XPC_BAD_IID;
 
785
        }
 
786
        iid = *piid;
 
787
        nsMemory::Free(piid);
 
788
    }
 
789
    else
 
790
        iid = NS_GET_IID(nsISupports);
 
791
 
 
792
    nsCOMPtr<nsISupports> inst;
 
793
    nsresult rv;
 
794
 
 
795
    rv = nsComponentManager::CreateInstance(*mDetails.GetID(), nsnull, iid,
 
796
                                            (void**) getter_AddRefs(inst));
 
797
    NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!");
 
798
 
 
799
    if(NS_FAILED(rv) || !inst)
 
800
        return NS_ERROR_XPC_CI_RETURNED_FAILURE;
 
801
 
 
802
    JSObject* instJSObj;
 
803
    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
 
804
    rv = xpc->WrapNative(cx, obj, inst, iid, getter_AddRefs(holder));
 
805
    if(NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
 
806
        return NS_ERROR_XPC_CANT_CREATE_WN;
 
807
 
 
808
    *vp = OBJECT_TO_JSVAL(instJSObj);
 
809
    ccxp->SetReturnValueWasSet(JS_TRUE);
 
810
    return NS_OK;
 
811
}
 
812
 
 
813
/* nsISupports getService (); */
 
814
NS_IMETHODIMP
 
815
nsJSCID::GetService(nsISupports **_retval)
 
816
{
 
817
    if(!mDetails.IsValid())
 
818
        return NS_ERROR_XPC_BAD_CID;
 
819
 
 
820
    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
 
821
    if(!xpc)
 
822
        return NS_ERROR_UNEXPECTED;
 
823
 
 
824
    nsCOMPtr<nsIXPCNativeCallContext> ccxp;
 
825
    xpc->GetCurrentNativeCallContext(getter_AddRefs(ccxp));
 
826
    if(!ccxp)
 
827
        return NS_ERROR_UNEXPECTED;
 
828
 
 
829
    PRUint32 argc;
 
830
    jsval * argv;
 
831
    jsval * vp;
 
832
    JSContext* cx;
 
833
    JSObject* obj;
 
834
 
 
835
    ccxp->GetJSContext(&cx);
 
836
    ccxp->GetArgc(&argc);
 
837
    ccxp->GetArgvPtr(&argv);
 
838
    ccxp->GetRetValPtr(&vp);
 
839
 
 
840
    nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
 
841
    ccxp->GetCalleeWrapper(getter_AddRefs(wrapper));
 
842
    wrapper->GetJSObject(&obj);
 
843
 
 
844
    // Do the security check if necessary
 
845
 
 
846
    XPCContext* xpcc = nsXPConnect::GetContext(cx);
 
847
 
 
848
    nsIXPCSecurityManager* sm;
 
849
    sm = xpcc->GetAppropriateSecurityManager(
 
850
                        nsIXPCSecurityManager::HOOK_GET_SERVICE);
 
851
    if(sm && NS_FAILED(sm->CanCreateInstance(cx, *mDetails.GetID())))
 
852
    {
 
853
        // the security manager vetoed. It should have set an exception.
 
854
        ccxp->SetExceptionWasThrown(JS_TRUE);
 
855
        return NS_OK;
 
856
    }
 
857
 
 
858
    nsID iid;
 
859
 
 
860
    // If an IID was passed in then use it
 
861
    if(argc)
 
862
    {
 
863
        JSObject* iidobj;
 
864
        jsval val = *argv;
 
865
        nsID* piid = nsnull;
 
866
        if(JSVAL_IS_PRIMITIVE(val) ||
 
867
           !(iidobj = JSVAL_TO_OBJECT(val)) ||
 
868
           !(piid = xpc_JSObjectToID(cx, iidobj)))
 
869
        {
 
870
            return NS_ERROR_XPC_BAD_IID;
 
871
        }
 
872
        iid = *piid;
 
873
        nsMemory::Free(piid);
 
874
    }
 
875
    else
 
876
        iid = NS_GET_IID(nsISupports);
 
877
 
 
878
    nsCOMPtr<nsISupports> srvc;
 
879
    nsresult rv;
 
880
 
 
881
    rv = nsServiceManager::GetService(*mDetails.GetID(), iid,
 
882
                                      getter_AddRefs(srvc), nsnull);
 
883
    NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!");
 
884
    if(NS_FAILED(rv) || !srvc)
 
885
        return NS_ERROR_XPC_GS_RETURNED_FAILURE;
 
886
 
 
887
    JSObject* instJSObj;
 
888
    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
 
889
    rv = xpc->WrapNative(cx, obj, srvc, iid, getter_AddRefs(holder));
 
890
    if(NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
 
891
        return NS_ERROR_XPC_CANT_CREATE_WN;
 
892
 
 
893
    *vp = OBJECT_TO_JSVAL(instJSObj);
 
894
    ccxp->SetReturnValueWasSet(JS_TRUE);
 
895
    return NS_OK;
 
896
}
 
897
 
 
898
/* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
 
899
NS_IMETHODIMP
 
900
nsJSCID::Construct(nsIXPConnectWrappedNative *wrapper,
 
901
                   JSContext * cx, JSObject * obj,
 
902
                   PRUint32 argc, jsval * argv, jsval * vp,
 
903
                   PRBool *_retval)
 
904
{
 
905
    XPCJSRuntime* rt = nsXPConnect::GetRuntime();
 
906
    if(!rt)
 
907
        return NS_ERROR_FAILURE;
 
908
 
 
909
    // 'push' a call context and call on it
 
910
    XPCCallContext ccx(JS_CALLER, cx, obj, nsnull,
 
911
                       rt->GetStringJSVal(XPCJSRuntime::IDX_CREATE_INSTANCE),
 
912
                       argc, argv, vp);
 
913
 
 
914
    *_retval = XPCWrappedNative::CallMethod(ccx);
 
915
    return NS_OK;
 
916
}
 
917
 
 
918
/* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
 
919
NS_IMETHODIMP
 
920
nsJSCID::HasInstance(nsIXPConnectWrappedNative *wrapper,
 
921
                     JSContext * cx, JSObject * obj,
 
922
                     jsval val, PRBool *bp, PRBool *_retval)
 
923
{
 
924
    *bp = JS_FALSE;
 
925
    nsresult rv = NS_OK;
 
926
 
 
927
    if(!JSVAL_IS_PRIMITIVE(val))
 
928
    {
 
929
        // we have a JSObject
 
930
        JSObject* obj = JSVAL_TO_OBJECT(val);
 
931
 
 
932
        NS_ASSERTION(obj, "when is an object not an object?");
 
933
 
 
934
        // is this really a native xpcom object with a wrapper?
 
935
        XPCWrappedNative* other_wrapper =
 
936
           XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
 
937
 
 
938
        if(!other_wrapper)
 
939
            return NS_OK;
 
940
 
 
941
        // We consider CID equality to be the thing that matters here.
 
942
        // This is perhaps debatable.
 
943
        nsIClassInfo* ci = other_wrapper->GetClassInfo();
 
944
        if(ci)
 
945
        {
 
946
            nsID cid;
 
947
            if(NS_SUCCEEDED(ci->GetClassIDNoAlloc(&cid)))
 
948
                *bp = cid.Equals(*mDetails.GetID());
 
949
        }
 
950
    }
 
951
    return rv;
 
952
}
 
953
 
 
954
/***************************************************************************/
 
955
// additional utilities...
 
956
 
 
957
JSObject *
 
958
xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID)
 
959
{
 
960
    JSObject *obj = nsnull;
 
961
 
 
962
    char* idString = aID.ToString();
 
963
    if(idString)
 
964
    {
 
965
        nsCOMPtr<nsIJSID> iid =
 
966
            dont_AddRef(NS_STATIC_CAST(nsIJSID*, nsJSID::NewID(idString)));
 
967
        PR_Free(idString);
 
968
        if(iid)
 
969
        {
 
970
            nsXPConnect* xpc = nsXPConnect::GetXPConnect();
 
971
            if(xpc)
 
972
            {
 
973
                nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
 
974
                nsresult rv = xpc->WrapNative(cx, jsobj,
 
975
                                              NS_STATIC_CAST(nsISupports*,iid),
 
976
                                              NS_GET_IID(nsIJSID),
 
977
                                              getter_AddRefs(holder));
 
978
                if(NS_SUCCEEDED(rv) && holder)
 
979
                {
 
980
                    holder->GetJSObject(&obj);
 
981
                }
 
982
            }
 
983
        }
 
984
    }
 
985
    return obj;
 
986
}
 
987
 
 
988
nsID*
 
989
xpc_JSObjectToID(JSContext *cx, JSObject* obj)
 
990
{
 
991
    nsID* id = nsnull;
 
992
    if(!cx || !obj)
 
993
        return nsnull;
 
994
 
 
995
    // NOTE: this call does NOT addref
 
996
    XPCWrappedNative* wrapper =
 
997
        XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
 
998
    if(wrapper &&
 
999
       (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID))  ||
 
1000
        wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
 
1001
        wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID))))
 
1002
    {
 
1003
        ((nsIJSID*)wrapper->GetIdentityObject())->GetId(&id);
 
1004
    }
 
1005
    return id;
 
1006
}
 
1007
 
 
1008
JSBool
 
1009
xpc_JSObjectIsID(JSContext *cx, JSObject* obj)
 
1010
{
 
1011
    NS_ASSERTION(cx && obj, "bad param");
 
1012
    // NOTE: this call does NOT addref
 
1013
    XPCWrappedNative* wrapper =
 
1014
        XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
 
1015
    return wrapper &&
 
1016
           (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID))  ||
 
1017
            wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
 
1018
            wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID)));
 
1019
}
 
1020
 
 
1021