1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla Communicator client code, released
18 : * March 31, 1998.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Netscape Communications Corporation.
22 : * Portions created by the Initial Developer are Copyright (C) 1999
23 : * the Initial Developer. All Rights Reserved.
24 : *
25 : * Contributor(s):
26 : * John Bandhauer <jband@netscape.com> (original author)
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 : /* JavaScript JSClasses and JSOps for our Wrapped Native JS Objects. */
43 :
44 : #include "xpcprivate.h"
45 : #include "XPCWrapper.h"
46 : #include "nsWrapperCacheInlines.h"
47 :
48 : /***************************************************************************/
49 :
50 : // All of the exceptions thrown into JS from this file go through here.
51 : // That makes this a nice place to set a breakpoint.
52 :
53 4 : static JSBool Throw(unsigned errNum, JSContext* cx)
54 : {
55 4 : XPCThrower::Throw(errNum, cx);
56 4 : return false;
57 : }
58 :
59 : // Handy macro used in many callback stub below.
60 :
61 : #define MORPH_SLIM_WRAPPER(cx, obj) \
62 : PR_BEGIN_MACRO \
63 : SLIM_LOG_WILL_MORPH(cx, obj); \
64 : if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj)) \
65 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); \
66 : PR_END_MACRO
67 :
68 : #define THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper) \
69 : PR_BEGIN_MACRO \
70 : if (!wrapper) \
71 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); \
72 : if (!wrapper->IsValid()) \
73 : return Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx); \
74 : PR_END_MACRO
75 :
76 : /***************************************************************************/
77 :
78 : static JSBool
79 18545 : ToStringGuts(XPCCallContext& ccx)
80 : {
81 : char* sz;
82 18545 : XPCWrappedNative* wrapper = ccx.GetWrapper();
83 :
84 18545 : if (wrapper)
85 18545 : sz = wrapper->ToString(ccx, ccx.GetTearOff());
86 : else
87 0 : sz = JS_smprintf("[xpconnect wrapped native prototype]");
88 :
89 18545 : if (!sz) {
90 0 : JS_ReportOutOfMemory(ccx);
91 0 : return false;
92 : }
93 :
94 18545 : JSString* str = JS_NewStringCopyZ(ccx, sz);
95 18545 : JS_smprintf_free(sz);
96 18545 : if (!str)
97 0 : return false;
98 :
99 18545 : ccx.SetRetVal(STRING_TO_JSVAL(str));
100 18545 : return true;
101 : }
102 :
103 : /***************************************************************************/
104 :
105 : static JSBool
106 0 : XPC_WN_Shared_ToString(JSContext *cx, unsigned argc, jsval *vp)
107 : {
108 0 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
109 0 : if (!obj)
110 0 : return false;
111 :
112 0 : if (IS_SLIM_WRAPPER(obj)) {
113 : XPCNativeScriptableInfo *si =
114 0 : GetSlimWrapperProto(obj)->GetScriptableInfo();
115 : #ifdef DEBUG
116 : # define FMT_ADDR " @ 0x%p"
117 : # define FMT_STR(str) str
118 : # define PARAM_ADDR(w) , w
119 : #else
120 : # define FMT_ADDR ""
121 : # define FMT_STR(str)
122 : # define PARAM_ADDR(w)
123 : #endif
124 0 : char *sz = JS_smprintf("[object %s" FMT_ADDR FMT_STR(" (native") FMT_ADDR FMT_STR(")") "]", si->GetJSClass()->name PARAM_ADDR(obj) PARAM_ADDR(xpc_GetJSPrivate(obj)));
125 0 : if (!sz)
126 0 : return false;
127 :
128 0 : JSString* str = JS_NewStringCopyZ(cx, sz);
129 0 : JS_smprintf_free(sz);
130 0 : if (!str)
131 0 : return false;
132 :
133 0 : *vp = STRING_TO_JSVAL(str);
134 :
135 0 : return true;
136 : }
137 :
138 0 : XPCCallContext ccx(JS_CALLER, cx, obj);
139 0 : ccx.SetName(ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_TO_STRING));
140 0 : ccx.SetArgsAndResultPtr(argc, JS_ARGV(cx, vp), vp);
141 0 : return ToStringGuts(ccx);
142 : }
143 :
144 : static JSBool
145 1 : XPC_WN_Shared_ToSource(JSContext *cx, unsigned argc, jsval *vp)
146 : {
147 : static const char empty[] = "({})";
148 1 : JSString *str = JS_NewStringCopyN(cx, empty, sizeof(empty)-1);
149 1 : if (!str)
150 0 : return false;
151 1 : *vp = STRING_TO_JSVAL(str);
152 :
153 1 : return true;
154 : }
155 :
156 : /***************************************************************************/
157 :
158 : // A "double wrapped object" is a user JSObject that has been wrapped as a
159 : // wrappedJS in order to be used by native code and then re-wrapped by a
160 : // wrappedNative wrapper to be used by JS code. One might think of it as:
161 : // wrappedNative(wrappedJS(underlying_JSObject))
162 : // This is done (as opposed to just unwrapping the wrapped JS and automatically
163 : // returning the underlying JSObject) so that JS callers will see what looks
164 : // Like any other xpcom object - and be limited to use its interfaces.
165 : //
166 : // See the comment preceding nsIXPCWrappedJSObjectGetter in nsIXPConnect.idl.
167 :
168 : static JSObject*
169 11996 : GetDoubleWrappedJSObject(XPCCallContext& ccx, XPCWrappedNative* wrapper)
170 : {
171 11996 : JSObject* obj = nsnull;
172 : nsCOMPtr<nsIXPConnectWrappedJS>
173 23992 : underware = do_QueryInterface(wrapper->GetIdentityObject());
174 11996 : if (underware) {
175 11785 : JSObject* mainObj = nsnull;
176 11785 : if (NS_SUCCEEDED(underware->GetJSObject(&mainObj)) && mainObj) {
177 : jsid id = ccx.GetRuntime()->
178 11785 : GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
179 :
180 23570 : JSAutoEnterCompartment ac;
181 11785 : if (!ac.enter(ccx, mainObj))
182 0 : return NULL;
183 :
184 : jsval val;
185 23570 : if (JS_GetPropertyById(ccx, mainObj, id, &val) &&
186 11785 : !JSVAL_IS_PRIMITIVE(val)) {
187 11785 : obj = JSVAL_TO_OBJECT(val);
188 : }
189 : }
190 : }
191 11996 : return obj;
192 : }
193 :
194 : // This is the getter native function we use to handle 'wrappedJSObject' for
195 : // double wrapped JSObjects.
196 :
197 : static JSBool
198 9898 : XPC_WN_DoubleWrappedGetter(JSContext *cx, unsigned argc, jsval *vp)
199 : {
200 9898 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
201 9898 : if (!obj)
202 0 : return false;
203 :
204 9898 : MORPH_SLIM_WRAPPER(cx, obj);
205 19796 : XPCCallContext ccx(JS_CALLER, cx, obj);
206 9898 : XPCWrappedNative* wrapper = ccx.GetWrapper();
207 9898 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
208 :
209 9898 : NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
210 :
211 9898 : JSObject* realObject = GetDoubleWrappedJSObject(ccx, wrapper);
212 9898 : if (!realObject) {
213 : // This is pretty unexpected at this point. The object originally
214 : // responded to this get property call and now gives no object.
215 : // XXX Should this throw something at the caller?
216 0 : *vp = JSVAL_NULL;
217 0 : return true;
218 : }
219 :
220 : // It is a double wrapped object. Figure out if the caller
221 : // is allowed to see it.
222 :
223 : nsIXPCSecurityManager* sm;
224 9898 : XPCContext* xpcc = ccx.GetXPCContext();
225 :
226 9898 : sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_GET_PROPERTY);
227 9898 : if (sm) {
228 19796 : AutoMarkingNativeInterfacePtr iface(ccx);
229 : iface = XPCNativeInterface::
230 9898 : GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCWrappedJSObjectGetter));
231 :
232 9898 : if (iface) {
233 : jsid id = ccx.GetRuntime()->
234 9898 : GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
235 :
236 9898 : ccx.SetCallInfo(iface, iface->GetMemberAt(1), false);
237 9898 : if (NS_FAILED(sm->
238 : CanAccess(nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
239 : &ccx, ccx,
240 : ccx.GetFlattenedJSObject(),
241 : wrapper->GetIdentityObject(),
242 : wrapper->GetClassInfo(), id,
243 : wrapper->GetSecurityInfoAddr()))) {
244 : // The SecurityManager should have set an exception.
245 0 : return false;
246 : }
247 : }
248 : }
249 9898 : *vp = OBJECT_TO_JSVAL(realObject);
250 9898 : return JS_WrapValue(cx, vp);
251 : }
252 :
253 : /***************************************************************************/
254 :
255 : // This is our shared function to define properties on our JSObjects.
256 :
257 : /*
258 : * NOTE:
259 : * We *never* set the tearoff names (e.g. nsIFoo) as JS_ENUMERATE.
260 : * We *never* set toString or toSource as JS_ENUMERATE.
261 : */
262 :
263 : static JSBool
264 2702162 : DefinePropertyIfFound(XPCCallContext& ccx,
265 : JSObject *obj, jsid id,
266 : XPCNativeSet* set,
267 : XPCNativeInterface* iface,
268 : XPCNativeMember* member,
269 : XPCWrappedNativeScope* scope,
270 : JSBool reflectToStringAndToSource,
271 : XPCWrappedNative* wrapperToReflectInterfaceNames,
272 : XPCWrappedNative* wrapperToReflectDoubleWrap,
273 : XPCNativeScriptableInfo* scriptableInfo,
274 : unsigned propFlags,
275 : JSBool* resolved)
276 : {
277 2702162 : XPCJSRuntime* rt = ccx.GetRuntime();
278 : JSBool found;
279 : const char* name;
280 :
281 2702162 : if (set) {
282 2702083 : if (iface)
283 25385 : found = true;
284 : else
285 2676698 : found = set->FindMember(id, &member, &iface);
286 : } else
287 79 : found = (nsnull != (member = iface->FindMember(id)));
288 :
289 2702162 : if (!found) {
290 984846 : if (reflectToStringAndToSource) {
291 : JSNative call;
292 :
293 984846 : if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_STRING)) {
294 0 : call = XPC_WN_Shared_ToString;
295 0 : name = rt->GetStringName(XPCJSRuntime::IDX_TO_STRING);
296 0 : id = rt->GetStringID(XPCJSRuntime::IDX_TO_STRING);
297 984846 : } else if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE)) {
298 1 : call = XPC_WN_Shared_ToSource;
299 1 : name = rt->GetStringName(XPCJSRuntime::IDX_TO_SOURCE);
300 1 : id = rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE);
301 : }
302 :
303 : else
304 984845 : call = nsnull;
305 :
306 984846 : if (call) {
307 1 : JSFunction* fun = JS_NewFunction(ccx, call, 0, 0, obj, name);
308 1 : if (!fun) {
309 0 : JS_ReportOutOfMemory(ccx);
310 0 : return false;
311 : }
312 :
313 2 : AutoResolveName arn(ccx, id);
314 1 : if (resolved)
315 0 : *resolved = true;
316 : return JS_DefinePropertyById(ccx, obj, id,
317 1 : OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)),
318 : nsnull, nsnull,
319 2 : propFlags & ~JSPROP_ENUMERATE);
320 : }
321 : }
322 : // This *might* be a tearoff name that is not yet part of our
323 : // set. Let's lookup the name and see if it is the name of an
324 : // interface. Then we'll see if the object actually *does* this
325 : // interface and add a tearoff as necessary.
326 :
327 984845 : if (wrapperToReflectInterfaceNames) {
328 21528 : JSAutoByteString name;
329 21528 : AutoMarkingNativeInterfacePtr iface2(ccx);
330 : XPCWrappedNativeTearOff* to;
331 : JSObject* jso;
332 10764 : nsresult rv = NS_OK;
333 :
334 21603 : if (JSID_IS_STRING(id) &&
335 5400 : name.encode(ccx, JSID_TO_STRING(id)) &&
336 5400 : (iface2 = XPCNativeInterface::GetNewOrUsed(ccx, name.ptr()), iface2) &&
337 : nsnull != (to = wrapperToReflectInterfaceNames->
338 39 : FindTearOff(ccx, iface2, true, &rv)) &&
339 : nsnull != (jso = to->GetJSObject()))
340 :
341 : {
342 78 : AutoResolveName arn(ccx, id);
343 39 : if (resolved)
344 0 : *resolved = true;
345 : return JS_DefinePropertyById(ccx, obj, id, OBJECT_TO_JSVAL(jso),
346 : nsnull, nsnull,
347 39 : propFlags & ~JSPROP_ENUMERATE);
348 10725 : } else if (NS_FAILED(rv) && rv != NS_ERROR_NO_INTERFACE) {
349 0 : return Throw(rv, ccx);
350 : }
351 : }
352 :
353 : // This *might* be a double wrapped JSObject
354 997629 : if (wrapperToReflectDoubleWrap &&
355 10725 : id == rt->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT) &&
356 2098 : GetDoubleWrappedJSObject(ccx, wrapperToReflectDoubleWrap)) {
357 : // We build and add a getter function.
358 : // A security check is done on a per-get basis.
359 :
360 : JSFunction* fun;
361 :
362 1887 : id = rt->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
363 1887 : name = rt->GetStringName(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
364 :
365 : fun = JS_NewFunction(ccx, XPC_WN_DoubleWrappedGetter,
366 1887 : 0, 0, obj, name);
367 :
368 1887 : if (!fun)
369 0 : return false;
370 :
371 1887 : JSObject* funobj = JS_GetFunctionObject(fun);
372 1887 : if (!funobj)
373 0 : return false;
374 :
375 1887 : propFlags |= JSPROP_GETTER;
376 1887 : propFlags &= ~JSPROP_ENUMERATE;
377 :
378 3774 : AutoResolveName arn(ccx, id);
379 1887 : if (resolved)
380 0 : *resolved = true;
381 : return JS_DefinePropertyById(ccx, obj, id, JSVAL_VOID,
382 : JS_DATA_TO_FUNC_PTR(JSPropertyOp,
383 : funobj),
384 1887 : nsnull, propFlags);
385 : }
386 :
387 982919 : if (resolved)
388 0 : *resolved = false;
389 982919 : return true;
390 : }
391 :
392 1717316 : if (!member) {
393 36 : if (wrapperToReflectInterfaceNames) {
394 : XPCWrappedNativeTearOff* to =
395 21 : wrapperToReflectInterfaceNames->FindTearOff(ccx, iface, true);
396 :
397 21 : if (!to)
398 0 : return false;
399 21 : JSObject* jso = to->GetJSObject();
400 21 : if (!jso)
401 0 : return false;
402 :
403 42 : AutoResolveName arn(ccx, id);
404 21 : if (resolved)
405 0 : *resolved = true;
406 : return JS_DefinePropertyById(ccx, obj, id, OBJECT_TO_JSVAL(jso),
407 : nsnull, nsnull,
408 21 : propFlags & ~JSPROP_ENUMERATE);
409 : }
410 15 : if (resolved)
411 0 : *resolved = false;
412 15 : return true;
413 : }
414 :
415 1717280 : if (member->IsConstant()) {
416 : jsval val;
417 12722 : AutoResolveName arn(ccx, id);
418 6361 : if (resolved)
419 177 : *resolved = true;
420 6361 : return member->GetConstantValue(ccx, iface, &val) &&
421 : JS_DefinePropertyById(ccx, obj, id, val, nsnull, nsnull,
422 6361 : propFlags);
423 : }
424 :
425 3449647 : if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_STRING) ||
426 1707264 : id == rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE) ||
427 : (scriptableInfo &&
428 30439 : scriptableInfo->GetFlags().DontEnumQueryInterface() &&
429 1025 : id == rt->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE)))
430 3760 : propFlags &= ~JSPROP_ENUMERATE;
431 :
432 : jsval funval;
433 1710919 : if (!member->NewFunctionObject(ccx, iface, obj, &funval))
434 0 : return false;
435 :
436 : // protect funobj until it is actually attached
437 3421838 : AUTO_MARK_JSVAL(ccx, funval);
438 :
439 : #ifdef off_DEBUG_jband
440 : {
441 : static int cloneCount = 0;
442 : if (!(++cloneCount%10))
443 : printf("<><><> %d cloned functions created\n", cloneCount);
444 : }
445 : #endif
446 :
447 1710919 : if (member->IsMethod()) {
448 1377710 : AutoResolveName arn(ccx, id);
449 688855 : if (resolved)
450 13509 : *resolved = true;
451 : return JS_DefinePropertyById(ccx, obj, id, funval, nsnull, nsnull,
452 688855 : propFlags);
453 : }
454 :
455 : // else...
456 :
457 1022064 : NS_ASSERTION(member->IsAttribute(), "way broken!");
458 :
459 1022064 : propFlags |= JSPROP_GETTER | JSPROP_SHARED;
460 1022064 : JSObject* funobj = JSVAL_TO_OBJECT(funval);
461 1022064 : JSPropertyOp getter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, funobj);
462 : JSStrictPropertyOp setter;
463 1022064 : if (member->IsWritableAttribute()) {
464 221084 : propFlags |= JSPROP_SETTER;
465 221084 : propFlags &= ~JSPROP_READONLY;
466 221084 : setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, funobj);
467 : } else {
468 800980 : setter = js_GetterOnlyPropertyStub;
469 : }
470 :
471 2044128 : AutoResolveName arn(ccx, id);
472 1022064 : if (resolved)
473 11699 : *resolved = true;
474 :
475 : return JS_DefinePropertyById(ccx, obj, id, JSVAL_VOID, getter, setter,
476 1022064 : propFlags);
477 : }
478 :
479 : /***************************************************************************/
480 : /***************************************************************************/
481 :
482 : static JSBool
483 1547943 : XPC_WN_OnlyIWrite_AddPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
484 : {
485 3095886 : XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, id);
486 1547943 : XPCWrappedNative* wrapper = ccx.GetWrapper();
487 1547943 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
488 :
489 : // Allow only XPConnect to add/set the property
490 1547943 : if (ccx.GetResolveName() == id)
491 1547941 : return true;
492 :
493 2 : return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
494 : }
495 :
496 : static JSBool
497 0 : XPC_WN_OnlyIWrite_SetPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
498 : {
499 0 : return XPC_WN_OnlyIWrite_AddPropertyStub(cx, obj, id, vp);
500 : }
501 :
502 : static JSBool
503 0 : XPC_WN_CannotModifyPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
504 : {
505 0 : return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
506 : }
507 :
508 : static JSBool
509 0 : XPC_WN_CannotModifyStrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
510 : jsval *vp)
511 : {
512 0 : return XPC_WN_CannotModifyPropertyStub(cx, obj, id, vp);
513 : }
514 :
515 : static JSBool
516 49120 : XPC_WN_Shared_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
517 : {
518 49120 : if (type == JSTYPE_OBJECT) {
519 0 : *vp = OBJECT_TO_JSVAL(obj);
520 0 : return true;
521 : }
522 :
523 49120 : MORPH_SLIM_WRAPPER(cx, obj);
524 98240 : XPCCallContext ccx(JS_CALLER, cx, obj);
525 49120 : XPCWrappedNative* wrapper = ccx.GetWrapper();
526 49120 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
527 :
528 49120 : switch (type) {
529 : case JSTYPE_FUNCTION:
530 : {
531 0 : if (!ccx.GetTearOff()) {
532 0 : XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
533 0 : if (si && (si->GetFlags().WantCall() ||
534 0 : si->GetFlags().WantConstruct())) {
535 0 : *vp = OBJECT_TO_JSVAL(obj);
536 0 : return true;
537 : }
538 : }
539 : }
540 0 : return Throw(NS_ERROR_XPC_CANT_CONVERT_WN_TO_FUN, cx);
541 : case JSTYPE_NUMBER:
542 1 : *vp = JS_GetNaNValue(cx);
543 1 : return true;
544 : case JSTYPE_BOOLEAN:
545 0 : *vp = JSVAL_TRUE;
546 0 : return true;
547 : case JSTYPE_VOID:
548 : case JSTYPE_STRING:
549 : {
550 49119 : ccx.SetName(ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_TO_STRING));
551 49119 : ccx.SetArgsAndResultPtr(0, nsnull, vp);
552 :
553 49119 : XPCNativeMember* member = ccx.GetMember();
554 49119 : if (member && member->IsMethod()) {
555 30574 : if (!XPCWrappedNative::CallMethod(ccx))
556 0 : return false;
557 :
558 30574 : if (JSVAL_IS_PRIMITIVE(*vp))
559 30574 : return true;
560 : }
561 :
562 : // else...
563 18545 : return ToStringGuts(ccx);
564 : }
565 : default:
566 0 : NS_ERROR("bad type in conversion");
567 0 : return false;
568 : }
569 : NS_NOTREACHED("huh?");
570 : return false;
571 : }
572 :
573 : static JSBool
574 29 : XPC_WN_Shared_Enumerate(JSContext *cx, JSObject *obj)
575 : {
576 29 : MORPH_SLIM_WRAPPER(cx, obj);
577 58 : XPCCallContext ccx(JS_CALLER, cx, obj);
578 29 : XPCWrappedNative* wrapper = ccx.GetWrapper();
579 29 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
580 :
581 : // Since we aren't going to enumerate tearoff names and the prototype
582 : // handles non-mutated members, we can do this potential short-circuit.
583 29 : if (!wrapper->HasMutatedSet())
584 7 : return true;
585 :
586 22 : XPCNativeSet* set = wrapper->GetSet();
587 22 : XPCNativeSet* protoSet = wrapper->HasProto() ?
588 22 : wrapper->GetProto()->GetSet() : nsnull;
589 :
590 22 : PRUint16 interface_count = set->GetInterfaceCount();
591 22 : XPCNativeInterface** interfaceArray = set->GetInterfaceArray();
592 67 : for (PRUint16 i = 0; i < interface_count; i++) {
593 45 : XPCNativeInterface* iface = interfaceArray[i];
594 45 : PRUint16 member_count = iface->GetMemberCount();
595 256 : for (PRUint16 k = 0; k < member_count; k++) {
596 211 : XPCNativeMember* member = iface->GetMemberAt(k);
597 211 : jsid name = member->GetName();
598 :
599 : // Skip if this member is going to come from the proto.
600 : PRUint16 index;
601 211 : if (protoSet &&
602 0 : protoSet->FindMember(name, nsnull, &index) && index == i)
603 0 : continue;
604 211 : if (!xpc_ForcePropertyResolve(cx, obj, name))
605 0 : return false;
606 : }
607 : }
608 22 : return true;
609 : }
610 :
611 : /***************************************************************************/
612 :
613 : #ifdef DEBUG_slimwrappers
614 : static PRUint32 sFinalizedSlimWrappers;
615 : #endif
616 :
617 : static void
618 1265286 : XPC_WN_NoHelper_Finalize(JSContext *cx, JSObject *obj)
619 : {
620 1265286 : nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
621 1265286 : if (!p)
622 704 : return;
623 :
624 1264582 : if (IS_SLIM_WRAPPER_OBJECT(obj)) {
625 : SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
626 : ++sFinalizedSlimWrappers, obj, p));
627 :
628 : nsWrapperCache* cache;
629 9090 : CallQueryInterface(p, &cache);
630 9090 : cache->ClearWrapper();
631 :
632 9090 : XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
633 9090 : if(rt)
634 9090 : rt->DeferredRelease(p);
635 : else
636 0 : NS_RELEASE(p);
637 9090 : return;
638 : }
639 :
640 1255492 : static_cast<XPCWrappedNative*>(p)->FlatJSObjectFinalized();
641 : }
642 :
643 : static void
644 3176709 : TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
645 : {
646 3176709 : NS_ASSERTION(scope, "bad scope");
647 :
648 : JSObject* obj;
649 :
650 3176709 : obj = scope->GetGlobalJSObject();
651 3176709 : NS_ASSERTION(obj, "bad scope JSObject");
652 3176709 : JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
653 :
654 3176709 : obj = scope->GetPrototypeJSObject();
655 3176709 : if (obj) {
656 3176709 : JS_CALL_OBJECT_TRACER(trc, obj,
657 : "XPCWrappedNativeScope::mPrototypeJSObject");
658 : }
659 3176709 : }
660 :
661 : static void
662 2285144 : TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
663 : {
664 : // NOTE: It might be nice to also do the wrapper->Mark() call here too
665 : // when we are called during the marking phase of JS GC to mark the
666 : // wrapper's and wrapper's proto's interface sets.
667 : //
668 : // We currently do that in the GC callback code. The reason we don't do that
669 : // here is because the bits used in that marking do unpleasant things to the
670 : // member counts in the interface and interface set objects. Those counts
671 : // are used in the DealWithDyingGCThings calls that are part of this JS GC
672 : // marking phase. By doing these calls later during our GC callback we
673 : // avoid that problem. Arguably this could be changed. But it ain't broke.
674 : //
675 : // However, we do need to call the wrapper's TraceJS so that
676 : // it can be sure that its (potentially shared) JSClass is traced. The
677 : // danger is that a live wrapper might not be in a wrapper map and thus
678 : // won't be fully marked in the GC callback. This can happen if there is
679 : // a security exception during wrapper creation or if during wrapper
680 : // creation it is determined that the wrapper is not needed. In those cases
681 : // the wrapper can never actually be used from JS code - so resources like
682 : // the interface set will never be accessed. But the JS engine will still
683 : // need to use the JSClass. So, some marking is required for protection.
684 :
685 2285144 : wrapper->TraceJS(trc);
686 :
687 2285144 : TraceScopeJSObjects(trc, wrapper->GetScope());
688 2285144 : }
689 :
690 : static void
691 2285386 : MarkWrappedNative(JSTracer *trc, JSObject *obj)
692 : {
693 : JSObject *obj2;
694 :
695 : // Pass null for the first JSContext* parameter to skip any security
696 : // checks and to avoid potential state change there.
697 : XPCWrappedNative* wrapper =
698 2285386 : XPCWrappedNative::GetWrappedNativeOfJSObject(nsnull, obj, nsnull, &obj2);
699 :
700 2285386 : if (wrapper) {
701 2285144 : if (wrapper->IsValid())
702 2285144 : TraceForValidWrapper(trc, wrapper);
703 242 : } else if (obj2) {
704 88 : GetSlimWrapperProto(obj2)->TraceJS(trc);
705 : }
706 2285386 : }
707 :
708 : static void
709 2285386 : XPC_WN_NoHelper_Trace(JSTracer *trc, JSObject *obj)
710 : {
711 2285386 : MarkWrappedNative(trc, obj);
712 2285386 : }
713 :
714 : static JSBool
715 1688293 : XPC_WN_NoHelper_Resolve(JSContext *cx, JSObject *obj, jsid id)
716 : {
717 1688293 : MORPH_SLIM_WRAPPER(cx, obj);
718 3376586 : XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, id);
719 1688293 : XPCWrappedNative* wrapper = ccx.GetWrapper();
720 1688293 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
721 :
722 1688293 : XPCNativeSet* set = ccx.GetSet();
723 1688293 : if (!set)
724 0 : return true;
725 :
726 : // Don't resolve properties that are on our prototype.
727 1688293 : if (ccx.GetInterface() && !ccx.GetStaticMemberIsLocal())
728 131593 : return true;
729 :
730 : return DefinePropertyIfFound(ccx, obj, id,
731 : set, nsnull, nsnull, wrapper->GetScope(),
732 : true, wrapper, wrapper, nsnull,
733 : JSPROP_ENUMERATE |
734 : JSPROP_READONLY |
735 1556700 : JSPROP_PERMANENT, nsnull);
736 : }
737 :
738 : nsISupports *
739 1012 : XPC_GetIdentityObject(JSContext *cx, JSObject *obj)
740 : {
741 : XPCWrappedNative *wrapper =
742 1012 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
743 :
744 1012 : return wrapper ? wrapper->GetIdentityObject() : nsnull;
745 : }
746 :
747 : JSBool
748 1473 : XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp)
749 : {
750 1473 : jsval v = *valp;
751 1473 : *bp = false;
752 :
753 : JSObject *obj2;
754 : XPCWrappedNative *wrapper =
755 1473 : XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, nsnull, &obj2);
756 1473 : if (obj2) {
757 0 : *bp = !JSVAL_IS_PRIMITIVE(v) && (JSVAL_TO_OBJECT(v) == obj2);
758 :
759 0 : return true;
760 : }
761 :
762 1473 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
763 :
764 1473 : XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
765 1473 : if (si && si->GetFlags().WantEquality()) {
766 : bool res;
767 0 : nsresult rv = si->GetCallback()->Equality(wrapper, cx, obj, v, &res);
768 0 : if (NS_FAILED(rv))
769 0 : return Throw(rv, cx);
770 0 : *bp = res;
771 1473 : } else if (!JSVAL_IS_PRIMITIVE(v)) {
772 1473 : JSObject *other = JSVAL_TO_OBJECT(v);
773 :
774 : *bp = (obj == other ||
775 506 : XPC_GetIdentityObject(cx, obj) ==
776 1979 : XPC_GetIdentityObject(cx, other));
777 : }
778 :
779 1473 : return true;
780 : }
781 :
782 : static JSObject *
783 0 : XPC_WN_OuterObject(JSContext *cx, JSObject *obj)
784 : {
785 : XPCWrappedNative *wrapper =
786 0 : static_cast<XPCWrappedNative *>(js::GetObjectPrivate(obj));
787 0 : if (!wrapper) {
788 0 : Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
789 :
790 0 : return nsnull;
791 : }
792 :
793 0 : if (!wrapper->IsValid()) {
794 0 : Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx);
795 :
796 0 : return nsnull;
797 : }
798 :
799 0 : XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
800 0 : if (si && si->GetFlags().WantOuterObject()) {
801 : JSObject *newThis;
802 : nsresult rv =
803 0 : si->GetCallback()->OuterObject(wrapper, cx, obj, &newThis);
804 :
805 0 : if (NS_FAILED(rv)) {
806 0 : Throw(rv, cx);
807 :
808 0 : return nsnull;
809 : }
810 :
811 0 : obj = newThis;
812 : }
813 :
814 0 : return obj;
815 : }
816 :
817 : XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
818 : { // base
819 : "XPCWrappedNative_NoHelper", // name;
820 : WRAPPER_SLOTS |
821 : JSCLASS_PRIVATE_IS_NSISUPPORTS, // flags
822 :
823 : /* Mandatory non-null function pointer members. */
824 : XPC_WN_OnlyIWrite_AddPropertyStub, // addProperty
825 : XPC_WN_CannotModifyPropertyStub, // delProperty
826 : JS_PropertyStub, // getProperty
827 : XPC_WN_OnlyIWrite_SetPropertyStub, // setProperty
828 :
829 : XPC_WN_Shared_Enumerate, // enumerate
830 : XPC_WN_NoHelper_Resolve, // resolve
831 : XPC_WN_Shared_Convert, // convert
832 : XPC_WN_NoHelper_Finalize, // finalize
833 :
834 : /* Optionally non-null members start here. */
835 : nsnull, // checkAccess
836 : nsnull, // call
837 : nsnull, // construct
838 : nsnull, // hasInstance
839 : XPC_WN_NoHelper_Trace, // trace
840 :
841 : // ClassExtension
842 : {
843 : XPC_WN_Equality,
844 : nsnull, // outerObject
845 : nsnull, // innerObject
846 : nsnull, // iteratorObject
847 : nsnull, // unused
848 : true, // isWrappedNative
849 : },
850 :
851 : // ObjectOps
852 : {
853 : nsnull, // lookupGeneric
854 : nsnull, // lookupProperty
855 : nsnull, // lookupElement
856 : nsnull, // lookupSpecial
857 : nsnull, // defineGeneric
858 : nsnull, // defineProperty
859 : nsnull, // defineElement
860 : nsnull, // defineSpecial
861 : nsnull, // getGeneric
862 : nsnull, // getProperty
863 : nsnull, // getElement
864 : nsnull, // getElementIfPresent
865 : nsnull, // getSpecial
866 : nsnull, // setGeneric
867 : nsnull, // setProperty
868 : nsnull, // setElement
869 : nsnull, // setSpecial
870 : nsnull, // getGenericAttributes
871 : nsnull, // getAttributes
872 : nsnull, // getElementAttributes
873 : nsnull, // getSpecialAttributes
874 : nsnull, // setGenericAttributes
875 : nsnull, // setAttributes
876 : nsnull, // setElementAttributes
877 : nsnull, // setSpecialAttributes
878 : nsnull, // deleteProperty
879 : nsnull, // deleteElement
880 : nsnull, // deleteSpecial
881 : XPC_WN_JSOp_Enumerate,
882 : XPC_WN_JSOp_TypeOf_Object,
883 : nsnull, // fix
884 : XPC_WN_JSOp_ThisObject,
885 : XPC_WN_JSOp_Clear
886 : }
887 : },
888 : 0 // interfacesBitmap
889 : };
890 :
891 :
892 : /***************************************************************************/
893 :
894 : static JSBool
895 224081 : XPC_WN_MaybeResolvingPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
896 : {
897 224081 : MORPH_SLIM_WRAPPER(cx, obj);
898 448162 : XPCCallContext ccx(JS_CALLER, cx, obj);
899 224081 : XPCWrappedNative* wrapper = ccx.GetWrapper();
900 224081 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
901 :
902 224081 : if (ccx.GetResolvingWrapper() == wrapper)
903 224081 : return true;
904 0 : return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
905 : }
906 :
907 : static JSBool
908 0 : XPC_WN_MaybeResolvingStrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
909 : jsval *vp)
910 : {
911 0 : return XPC_WN_MaybeResolvingPropertyStub(cx, obj, id, vp);
912 : }
913 :
914 : // macro fun!
915 : #define PRE_HELPER_STUB_NO_SLIM \
916 : XPCWrappedNative* wrapper = \
917 : XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj); \
918 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); \
919 : bool retval = true; \
920 : nsresult rv = wrapper->GetScriptableCallback()->
921 :
922 : #define PRE_HELPER_STUB \
923 : XPCWrappedNative* wrapper; \
924 : nsIXPCScriptable* si; \
925 : if (IS_SLIM_WRAPPER(obj)) { \
926 : wrapper = nsnull; \
927 : si = GetSlimWrapperProto(obj)->GetScriptableInfo()->GetCallback(); \
928 : } \
929 : else \
930 : { \
931 : wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); \
932 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); \
933 : si = wrapper->GetScriptableCallback(); \
934 : } \
935 : bool retval = true; \
936 : nsresult rv = si->
937 :
938 : #define POST_HELPER_STUB \
939 : if (NS_FAILED(rv)) \
940 : return Throw(rv, cx); \
941 : return retval;
942 :
943 : static JSBool
944 3 : XPC_WN_Helper_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
945 : {
946 3 : PRE_HELPER_STUB
947 3 : AddProperty(wrapper, cx, obj, id, vp, &retval);
948 3 : POST_HELPER_STUB
949 : }
950 :
951 : static JSBool
952 0 : XPC_WN_Helper_DelProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
953 : {
954 0 : PRE_HELPER_STUB
955 0 : DelProperty(wrapper, cx, obj, id, vp, &retval);
956 0 : POST_HELPER_STUB
957 : }
958 :
959 : static JSBool
960 166762 : XPC_WN_Helper_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
961 : {
962 166762 : PRE_HELPER_STUB
963 166762 : GetProperty(wrapper, cx, obj, id, vp, &retval);
964 166762 : POST_HELPER_STUB
965 : }
966 :
967 : static JSBool
968 115514 : XPC_WN_Helper_SetProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
969 : {
970 115514 : PRE_HELPER_STUB
971 115514 : SetProperty(wrapper, cx, obj, id, vp, &retval);
972 115514 : POST_HELPER_STUB
973 : }
974 :
975 : static JSBool
976 0 : XPC_WN_Helper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
977 : {
978 : SLIM_LOG_WILL_MORPH(cx, obj);
979 0 : PRE_HELPER_STUB_NO_SLIM
980 0 : Convert(wrapper, cx, obj, type, vp, &retval);
981 0 : POST_HELPER_STUB
982 : }
983 :
984 : static JSBool
985 0 : XPC_WN_Helper_CheckAccess(JSContext *cx, JSObject *obj, jsid id,
986 : JSAccessMode mode, jsval *vp)
987 : {
988 0 : PRE_HELPER_STUB
989 0 : CheckAccess(wrapper, cx, obj, id, mode, vp, &retval);
990 0 : POST_HELPER_STUB
991 : }
992 :
993 : static JSBool
994 8354 : XPC_WN_Helper_Call(JSContext *cx, unsigned argc, jsval *vp)
995 : {
996 : // N.B. we want obj to be the callee, not JS_THIS(cx, vp)
997 8354 : JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
998 :
999 : XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, JSID_VOID,
1000 16708 : argc, JS_ARGV(cx, vp), vp);
1001 8354 : if (!ccx.IsValid())
1002 0 : return false;
1003 :
1004 8354 : JS_ASSERT(obj == ccx.GetFlattenedJSObject());
1005 :
1006 : SLIM_LOG_WILL_MORPH(cx, obj);
1007 8354 : PRE_HELPER_STUB_NO_SLIM
1008 8354 : Call(wrapper, cx, obj, argc, JS_ARGV(cx, vp), vp, &retval);
1009 8354 : POST_HELPER_STUB
1010 : }
1011 :
1012 : static JSBool
1013 47565 : XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *vp)
1014 : {
1015 47565 : JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
1016 47565 : if (!obj)
1017 0 : return false;
1018 :
1019 : XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, JSID_VOID,
1020 95130 : argc, JS_ARGV(cx, vp), vp);
1021 47565 : if (!ccx.IsValid())
1022 0 : return false;
1023 :
1024 47565 : JS_ASSERT(obj == ccx.GetFlattenedJSObject());
1025 :
1026 : SLIM_LOG_WILL_MORPH(cx, obj);
1027 47565 : PRE_HELPER_STUB_NO_SLIM
1028 47565 : Construct(wrapper, cx, obj, argc, JS_ARGV(cx, vp), vp, &retval);
1029 47565 : POST_HELPER_STUB
1030 : }
1031 :
1032 : static JSBool
1033 167930 : XPC_WN_Helper_HasInstance(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp)
1034 : {
1035 : SLIM_LOG_WILL_MORPH(cx, obj);
1036 : bool retval2;
1037 167930 : PRE_HELPER_STUB_NO_SLIM
1038 167930 : HasInstance(wrapper, cx, obj, *valp, &retval2, &retval);
1039 167930 : *bp = retval2;
1040 167930 : POST_HELPER_STUB
1041 : }
1042 :
1043 : static void
1044 0 : XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj)
1045 : {
1046 0 : nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
1047 0 : if (IS_SLIM_WRAPPER(obj)) {
1048 : SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
1049 : ++sFinalizedSlimWrappers, obj, p));
1050 :
1051 : nsWrapperCache* cache;
1052 0 : CallQueryInterface(p, &cache);
1053 0 : cache->ClearWrapper();
1054 0 : NS_RELEASE(p);
1055 0 : return;
1056 : }
1057 :
1058 0 : XPCWrappedNative* wrapper = (XPCWrappedNative*)p;
1059 0 : if (!wrapper)
1060 0 : return;
1061 0 : wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
1062 0 : wrapper->FlatJSObjectFinalized();
1063 : }
1064 :
1065 : static JSBool
1066 1538913 : XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
1067 : JSObject **objp)
1068 : {
1069 1538913 : nsresult rv = NS_OK;
1070 1538913 : bool retval = true;
1071 1538913 : JSObject* obj2FromScriptable = nsnull;
1072 1538913 : if (IS_SLIM_WRAPPER(obj)) {
1073 : XPCNativeScriptableInfo *si =
1074 7467 : GetSlimWrapperProto(obj)->GetScriptableInfo();
1075 7467 : if (!si->GetFlags().WantNewResolve())
1076 0 : return retval;
1077 :
1078 7467 : NS_ASSERTION(si->GetFlags().AllowPropModsToPrototype() &&
1079 : !si->GetFlags().AllowPropModsDuringResolve(),
1080 : "We don't support these flags for slim wrappers!");
1081 :
1082 7467 : rv = si->GetCallback()->NewResolve(nsnull, cx, obj, id, flags,
1083 7467 : &obj2FromScriptable, &retval);
1084 7467 : if (NS_FAILED(rv))
1085 0 : return Throw(rv, cx);
1086 :
1087 7467 : if (obj2FromScriptable)
1088 0 : *objp = obj2FromScriptable;
1089 :
1090 7467 : return retval;
1091 : }
1092 :
1093 3062892 : XPCCallContext ccx(JS_CALLER, cx, obj);
1094 1531446 : XPCWrappedNative* wrapper = ccx.GetWrapper();
1095 1531446 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
1096 :
1097 1531446 : jsid old = ccx.SetResolveName(id);
1098 :
1099 1531446 : XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
1100 1531446 : if (si && si->GetFlags().WantNewResolve()) {
1101 : XPCWrappedNative* oldResolvingWrapper;
1102 1385441 : JSBool allowPropMods = si->GetFlags().AllowPropModsDuringResolve();
1103 :
1104 1385441 : if (allowPropMods)
1105 493604 : oldResolvingWrapper = ccx.SetResolvingWrapper(wrapper);
1106 :
1107 1385441 : rv = si->GetCallback()->NewResolve(wrapper, cx, obj, id, flags,
1108 1385441 : &obj2FromScriptable, &retval);
1109 :
1110 1385441 : if (allowPropMods)
1111 493604 : (void)ccx.SetResolvingWrapper(oldResolvingWrapper);
1112 : }
1113 :
1114 1531446 : old = ccx.SetResolveName(old);
1115 1531446 : NS_ASSERTION(old == id, "bad nest");
1116 :
1117 1531446 : if (NS_FAILED(rv)) {
1118 0 : return Throw(rv, cx);
1119 : }
1120 :
1121 1531446 : if (obj2FromScriptable) {
1122 221880 : *objp = obj2FromScriptable;
1123 1309566 : } else if (wrapper->HasMutatedSet()) {
1124 : // We are here if scriptable did not resolve this property and
1125 : // it *might* be in the instance set but not the proto set.
1126 :
1127 26513 : XPCNativeSet* set = wrapper->GetSet();
1128 26513 : XPCNativeSet* protoSet = wrapper->HasProto() ?
1129 26513 : wrapper->GetProto()->GetSet() : nsnull;
1130 : XPCNativeMember* member;
1131 : XPCNativeInterface* iface;
1132 : JSBool IsLocal;
1133 :
1134 26513 : if (set->FindMember(id, &member, &iface, protoSet, &IsLocal) &&
1135 : IsLocal) {
1136 : XPCWrappedNative* oldResolvingWrapper;
1137 :
1138 25385 : XPCNativeScriptableFlags siFlags(0);
1139 25385 : if (si)
1140 25385 : siFlags = si->GetFlags();
1141 :
1142 : unsigned enumFlag =
1143 25385 : siFlags.DontEnumStaticProps() ? 0 : JSPROP_ENUMERATE;
1144 :
1145 : XPCWrappedNative* wrapperForInterfaceNames =
1146 25385 : siFlags.DontReflectInterfaceNames() ? nsnull : wrapper;
1147 :
1148 : JSBool resolved;
1149 25385 : oldResolvingWrapper = ccx.SetResolvingWrapper(wrapper);
1150 : retval = DefinePropertyIfFound(ccx, obj, id,
1151 : set, iface, member,
1152 : wrapper->GetScope(),
1153 : false,
1154 : wrapperForInterfaceNames,
1155 : nsnull, si,
1156 25385 : enumFlag, &resolved);
1157 25385 : (void)ccx.SetResolvingWrapper(oldResolvingWrapper);
1158 25385 : if (retval && resolved)
1159 25385 : *objp = obj;
1160 : }
1161 : }
1162 :
1163 1531446 : return retval;
1164 : }
1165 :
1166 : /***************************************************************************/
1167 :
1168 : /*
1169 : Here are the enumerator cases:
1170 :
1171 : set jsclass enumerate to stub (unless noted otherwise)
1172 :
1173 : if ( helper wants new enumerate )
1174 : if ( DONT_ENUM_STATICS )
1175 : forward to scriptable enumerate
1176 : else
1177 : if ( set not mutated )
1178 : forward to scriptable enumerate
1179 : else
1180 : call shared enumerate
1181 : forward to scriptable enumerate
1182 : else if ( helper wants old enumerate )
1183 : use this JSOp
1184 : if ( DONT_ENUM_STATICS )
1185 : call scriptable enumerate
1186 : call stub
1187 : else
1188 : if ( set not mutated )
1189 : call scriptable enumerate
1190 : call stub
1191 : else
1192 : call shared enumerate
1193 : call scriptable enumerate
1194 : call stub
1195 :
1196 : else //... if ( helper wants NO enumerate )
1197 : if ( DONT_ENUM_STATICS )
1198 : use enumerate stub - don't use this JSOp thing at all
1199 : else
1200 : do shared enumerate - don't use this JSOp thing at all
1201 : */
1202 :
1203 : JSBool
1204 353 : XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
1205 : jsval *statep, jsid *idp)
1206 : {
1207 353 : js::Class *clazz = js::GetObjectClass(obj);
1208 353 : if (!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) {
1209 : // obj must be a prototype object or a wrapper w/o a
1210 : // helper. Short circuit this call to the default
1211 : // implementation.
1212 :
1213 35 : return JS_EnumerateState(cx, obj, enum_op, statep, idp);
1214 : }
1215 :
1216 318 : MORPH_SLIM_WRAPPER(cx, obj);
1217 :
1218 636 : XPCCallContext ccx(JS_CALLER, cx, obj);
1219 318 : XPCWrappedNative* wrapper = ccx.GetWrapper();
1220 318 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
1221 :
1222 318 : XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
1223 318 : if (!si)
1224 0 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
1225 :
1226 318 : bool retval = true;
1227 : nsresult rv;
1228 :
1229 318 : if (si->GetFlags().WantNewEnumerate()) {
1230 80 : if (((enum_op == JSENUMERATE_INIT &&
1231 13 : !si->GetFlags().DontEnumStaticProps()) ||
1232 : enum_op == JSENUMERATE_INIT_ALL) &&
1233 13 : wrapper->HasMutatedSet() &&
1234 13 : !XPC_WN_Shared_Enumerate(cx, obj)) {
1235 0 : *statep = JSVAL_NULL;
1236 0 : return false;
1237 : }
1238 :
1239 : // XXX Might we really need to wrap this call and *also* call
1240 : // js_ObjectOps.enumerate ???
1241 :
1242 41 : rv = si->GetCallback()->
1243 41 : NewEnumerate(wrapper, cx, obj, enum_op, statep, idp, &retval);
1244 :
1245 67 : if ((enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) &&
1246 26 : (NS_FAILED(rv) || !retval)) {
1247 0 : *statep = JSVAL_NULL;
1248 : }
1249 :
1250 41 : if (NS_FAILED(rv))
1251 0 : return Throw(rv, cx);
1252 41 : return retval;
1253 : }
1254 :
1255 277 : if (si->GetFlags().WantEnumerate()) {
1256 0 : if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) {
1257 0 : if ((enum_op == JSENUMERATE_INIT_ALL ||
1258 0 : !si->GetFlags().DontEnumStaticProps()) &&
1259 0 : wrapper->HasMutatedSet() &&
1260 0 : !XPC_WN_Shared_Enumerate(cx, obj)) {
1261 0 : *statep = JSVAL_NULL;
1262 0 : return false;
1263 : }
1264 0 : rv = si->GetCallback()->
1265 0 : Enumerate(wrapper, cx, obj, &retval);
1266 :
1267 0 : if (NS_FAILED(rv) || !retval)
1268 0 : *statep = JSVAL_NULL;
1269 :
1270 0 : if (NS_FAILED(rv))
1271 0 : return Throw(rv, cx);
1272 0 : if (!retval)
1273 0 : return false;
1274 : // Then fall through and call the default implementation...
1275 : }
1276 : }
1277 :
1278 : // else call js_ObjectOps.enumerate...
1279 :
1280 277 : return JS_EnumerateState(cx, obj, enum_op, statep, idp);
1281 : }
1282 :
1283 : JSType
1284 7482 : XPC_WN_JSOp_TypeOf_Object(JSContext *cx, JSObject *obj)
1285 : {
1286 7482 : return JSTYPE_OBJECT;
1287 : }
1288 :
1289 : JSType
1290 0 : XPC_WN_JSOp_TypeOf_Function(JSContext *cx, JSObject *obj)
1291 : {
1292 0 : return JSTYPE_FUNCTION;
1293 : }
1294 :
1295 : void
1296 13218 : XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj)
1297 : {
1298 : // XXX Clear XrayWrappers?
1299 13218 : }
1300 :
1301 : namespace {
1302 :
1303 : NS_STACK_CLASS class AutoPopJSContext
1304 : {
1305 : public:
1306 : AutoPopJSContext(XPCJSContextStack *stack)
1307 : : mCx(nsnull), mStack(stack)
1308 : {
1309 : NS_ASSERTION(stack, "Null stack!");
1310 : }
1311 :
1312 : ~AutoPopJSContext()
1313 : {
1314 : if (mCx)
1315 : mStack->Pop();
1316 : }
1317 :
1318 : void PushIfNotTop(JSContext *cx)
1319 : {
1320 : NS_ASSERTION(cx, "Null context!");
1321 : NS_ASSERTION(!mCx, "This class is only meant to be used once!");
1322 :
1323 : JSContext *cxTop = mStack->Peek();
1324 :
1325 : if (cxTop != cx && mStack->Push(cx))
1326 : mCx = cx;
1327 : }
1328 :
1329 : private:
1330 : JSContext *mCx;
1331 : XPCJSContextStack *mStack;
1332 : };
1333 :
1334 : } // namespace
1335 :
1336 : JSObject*
1337 2478743 : XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj)
1338 : {
1339 : // None of the wrappers we could potentially hand out are threadsafe so
1340 : // just hand out the given object.
1341 2478743 : if (!XPCPerThreadData::IsMainThread(cx))
1342 0 : return obj;
1343 :
1344 2478743 : return JS_ObjectToOuterObject(cx, obj);
1345 : }
1346 :
1347 : /***************************************************************************/
1348 :
1349 : // static
1350 : XPCNativeScriptableInfo*
1351 249788 : XPCNativeScriptableInfo::Construct(XPCCallContext& ccx,
1352 : const XPCNativeScriptableCreateInfo* sci)
1353 : {
1354 249788 : NS_ASSERTION(sci, "bad param");
1355 249788 : NS_ASSERTION(sci->GetCallback(), "bad param");
1356 :
1357 : XPCNativeScriptableInfo* newObj =
1358 499576 : new XPCNativeScriptableInfo(sci->GetCallback());
1359 249788 : if (!newObj)
1360 0 : return nsnull;
1361 :
1362 249788 : char* name = nsnull;
1363 249788 : if (NS_FAILED(sci->GetCallback()->GetClassName(&name)) || !name) {
1364 0 : delete newObj;
1365 0 : return nsnull;
1366 : }
1367 :
1368 : JSBool success;
1369 :
1370 249788 : XPCJSRuntime* rt = ccx.GetRuntime();
1371 249788 : XPCNativeScriptableSharedMap* map = rt->GetNativeScriptableSharedMap();
1372 : { // scoped lock
1373 499576 : XPCAutoLock lock(rt->GetMapLock());
1374 249788 : success = map->GetNewOrUsed(sci->GetFlags(), name,
1375 499576 : sci->GetInterfacesBitmap(), newObj);
1376 : }
1377 :
1378 249788 : if (!success) {
1379 0 : delete newObj;
1380 0 : return nsnull;
1381 : }
1382 :
1383 249788 : return newObj;
1384 : }
1385 :
1386 : void
1387 21231 : XPCNativeScriptableShared::PopulateJSClass()
1388 : {
1389 21231 : NS_ASSERTION(mJSClass.base.name, "bad state!");
1390 :
1391 : mJSClass.base.flags = WRAPPER_SLOTS |
1392 : JSCLASS_PRIVATE_IS_NSISUPPORTS |
1393 21231 : JSCLASS_NEW_RESOLVE;
1394 :
1395 21231 : if (mFlags.IsGlobalObject())
1396 1391 : mJSClass.base.flags |= XPCONNECT_GLOBAL_FLAGS;
1397 :
1398 : JSPropertyOp addProperty;
1399 21231 : if (mFlags.WantAddProperty())
1400 1798 : addProperty = XPC_WN_Helper_AddProperty;
1401 19433 : else if (mFlags.UseJSStubForAddProperty())
1402 2354 : addProperty = JS_PropertyStub;
1403 17079 : else if (mFlags.AllowPropModsDuringResolve())
1404 13978 : addProperty = XPC_WN_MaybeResolvingPropertyStub;
1405 : else
1406 3101 : addProperty = XPC_WN_CannotModifyPropertyStub;
1407 21231 : mJSClass.base.addProperty = addProperty;
1408 :
1409 : JSPropertyOp delProperty;
1410 21231 : if (mFlags.WantDelProperty())
1411 3 : delProperty = XPC_WN_Helper_DelProperty;
1412 21228 : else if (mFlags.UseJSStubForDelProperty())
1413 4149 : delProperty = JS_PropertyStub;
1414 17079 : else if (mFlags.AllowPropModsDuringResolve())
1415 13978 : delProperty = XPC_WN_MaybeResolvingPropertyStub;
1416 : else
1417 3101 : delProperty = XPC_WN_CannotModifyPropertyStub;
1418 21231 : mJSClass.base.delProperty = delProperty;
1419 :
1420 21231 : if (mFlags.WantGetProperty())
1421 2391 : mJSClass.base.getProperty = XPC_WN_Helper_GetProperty;
1422 : else
1423 18840 : mJSClass.base.getProperty = JS_PropertyStub;
1424 :
1425 : JSStrictPropertyOp setProperty;
1426 21231 : if (mFlags.WantSetProperty())
1427 1905 : setProperty = XPC_WN_Helper_SetProperty;
1428 19326 : else if (mFlags.UseJSStubForSetProperty())
1429 4153 : setProperty = JS_StrictPropertyStub;
1430 15173 : else if (mFlags.AllowPropModsDuringResolve())
1431 12072 : setProperty = XPC_WN_MaybeResolvingStrictPropertyStub;
1432 : else
1433 3101 : setProperty = XPC_WN_CannotModifyStrictPropertyStub;
1434 21231 : mJSClass.base.setProperty = setProperty;
1435 :
1436 : // We figure out most of the enumerate strategy at call time.
1437 :
1438 34564 : if (mFlags.WantNewEnumerate() || mFlags.WantEnumerate() ||
1439 13333 : mFlags.DontEnumStaticProps())
1440 10961 : mJSClass.base.enumerate = JS_EnumerateStub;
1441 : else
1442 10270 : mJSClass.base.enumerate = XPC_WN_Shared_Enumerate;
1443 :
1444 : // We have to figure out resolve strategy at call time
1445 21231 : mJSClass.base.resolve = (JSResolveOp) XPC_WN_Helper_NewResolve;
1446 :
1447 21231 : if (mFlags.WantConvert())
1448 0 : mJSClass.base.convert = XPC_WN_Helper_Convert;
1449 : else
1450 21231 : mJSClass.base.convert = XPC_WN_Shared_Convert;
1451 :
1452 21231 : if (mFlags.WantFinalize())
1453 0 : mJSClass.base.finalize = XPC_WN_Helper_Finalize;
1454 : else
1455 21231 : mJSClass.base.finalize = XPC_WN_NoHelper_Finalize;
1456 :
1457 : // We let the rest default to nsnull unless the helper wants them...
1458 21231 : if (mFlags.WantCheckAccess())
1459 2621 : mJSClass.base.checkAccess = XPC_WN_Helper_CheckAccess;
1460 :
1461 : // Note that we *must* set the ObjectOps (even for the cases were it does
1462 : // not do much) because with these dynamically generated JSClasses, the
1463 : // code in XPCWrappedNative::GetWrappedNativeOfJSObject() needs to look
1464 : // for that these callback pointers in order to identify that a given
1465 : // JSObject represents a wrapper.
1466 21231 : js::ObjectOps *ops = &mJSClass.base.ops;
1467 21231 : ops->enumerate = XPC_WN_JSOp_Enumerate;
1468 21231 : ops->clear = XPC_WN_JSOp_Clear;
1469 21231 : ops->thisObject = XPC_WN_JSOp_ThisObject;
1470 :
1471 21231 : if (mFlags.WantCall() || mFlags.WantConstruct()) {
1472 5178 : ops->typeOf = XPC_WN_JSOp_TypeOf_Function;
1473 5178 : if (mFlags.WantCall())
1474 3508 : mJSClass.base.call = XPC_WN_Helper_Call;
1475 5178 : if (mFlags.WantConstruct())
1476 4900 : mJSClass.base.construct = XPC_WN_Helper_Construct;
1477 : } else {
1478 16053 : ops->typeOf = XPC_WN_JSOp_TypeOf_Object;
1479 : }
1480 :
1481 21231 : if (mFlags.UseStubEqualityHook()) {
1482 1370 : NS_ASSERTION(!mFlags.WantEquality(),
1483 : "If you want an Equality callback, you can't use a stub "
1484 : "equality hook");
1485 1370 : mJSClass.base.ext.equality = nsnull;
1486 : } else {
1487 19861 : mJSClass.base.ext.equality = XPC_WN_Equality;
1488 : }
1489 :
1490 21231 : if (mFlags.WantHasInstance())
1491 5415 : mJSClass.base.hasInstance = XPC_WN_Helper_HasInstance;
1492 :
1493 21231 : mJSClass.base.trace = XPC_WN_NoHelper_Trace;
1494 :
1495 21231 : if (mFlags.WantOuterObject())
1496 0 : mJSClass.base.ext.outerObject = XPC_WN_OuterObject;
1497 :
1498 21231 : if (!(mFlags & nsIXPCScriptable::WANT_OUTER_OBJECT))
1499 21231 : mCanBeSlim = true;
1500 :
1501 21231 : mJSClass.base.ext.isWrappedNative = true;
1502 21231 : }
1503 :
1504 : /***************************************************************************/
1505 : /***************************************************************************/
1506 :
1507 : JSBool
1508 4364331 : XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
1509 : {
1510 4364331 : NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
1511 4364331 : JSObject* funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
1512 :
1513 4364331 : JSObject* obj = JS_THIS_OBJECT(cx, vp);
1514 4364331 : if (!obj)
1515 0 : return false;
1516 :
1517 : #ifdef DEBUG_slimwrappers
1518 : {
1519 : JSFunction* fun = funobj->getFunctionPrivate();
1520 : JSString *funid = JS_GetFunctionId(fun);
1521 : JSAutoByteString bytes;
1522 : const char *funname = !funid ? "" : bytes.encode(cx, funid) ? bytes.ptr() : "<error>";
1523 : SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
1524 : }
1525 : #endif
1526 4364331 : if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
1527 0 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
1528 :
1529 8728662 : XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOID, argc, JS_ARGV(cx, vp), vp);
1530 4364331 : XPCWrappedNative* wrapper = ccx.GetWrapper();
1531 4364331 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
1532 :
1533 : XPCNativeInterface* iface;
1534 : XPCNativeMember* member;
1535 :
1536 4364331 : if (!XPCNativeMember::GetCallInfo(ccx, funobj, &iface, &member))
1537 0 : return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
1538 4364331 : ccx.SetCallInfo(iface, member, false);
1539 4364331 : return XPCWrappedNative::CallMethod(ccx);
1540 : }
1541 :
1542 : JSBool
1543 2357439 : XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp)
1544 : {
1545 2357439 : NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
1546 2357439 : JSObject* funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
1547 :
1548 2357439 : JSObject* obj = JS_THIS_OBJECT(cx, vp);
1549 2357439 : if (!obj)
1550 0 : return false;
1551 :
1552 : #ifdef DEBUG_slimwrappers
1553 : {
1554 : const char* funname = nsnull;
1555 : JSAutoByteString bytes;
1556 : if (JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION) {
1557 : JSString *funid = JS_GetFunctionId(funobj->getFunctionPrivate());
1558 : funname = !funid ? "" : bytes.encode(cx, funid) ? bytes.ptr() : "<error>";
1559 : }
1560 : SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
1561 : }
1562 : #endif
1563 2357439 : if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
1564 0 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
1565 :
1566 4714878 : XPCCallContext ccx(JS_CALLER, cx, obj, funobj);
1567 2357439 : XPCWrappedNative* wrapper = ccx.GetWrapper();
1568 2357439 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
1569 :
1570 : XPCNativeInterface* iface;
1571 : XPCNativeMember* member;
1572 :
1573 2357439 : if (!XPCNativeMember::GetCallInfo(ccx, funobj, &iface, &member))
1574 0 : return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
1575 :
1576 2357439 : ccx.SetArgsAndResultPtr(argc, JS_ARGV(cx, vp), vp);
1577 2357439 : if (argc && member->IsWritableAttribute()) {
1578 102335 : ccx.SetCallInfo(iface, member, true);
1579 102335 : JSBool retval = XPCWrappedNative::SetAttribute(ccx);
1580 102335 : if (retval)
1581 102216 : *vp = JS_ARGV(cx, vp)[0];
1582 102335 : return retval;
1583 : }
1584 : // else...
1585 :
1586 2255104 : ccx.SetCallInfo(iface, member, false);
1587 2255104 : return XPCWrappedNative::GetAttribute(ccx);
1588 : }
1589 :
1590 : /***************************************************************************/
1591 :
1592 : static JSBool
1593 4 : XPC_WN_Shared_Proto_Enumerate(JSContext *cx, JSObject *obj)
1594 : {
1595 4 : NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
1596 : js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass ||
1597 : js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
1598 : js::GetObjectClass(obj) == &XPC_WN_NoMods_NoCall_Proto_JSClass,
1599 : "bad proto");
1600 : XPCWrappedNativeProto* self =
1601 4 : (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
1602 4 : if (!self)
1603 0 : return false;
1604 :
1605 4 : if (self->GetScriptableInfo() &&
1606 0 : self->GetScriptableInfo()->GetFlags().DontEnumStaticProps())
1607 0 : return true;
1608 :
1609 4 : XPCNativeSet* set = self->GetSet();
1610 4 : if (!set)
1611 0 : return false;
1612 :
1613 8 : XPCCallContext ccx(JS_CALLER, cx);
1614 4 : if (!ccx.IsValid())
1615 0 : return false;
1616 4 : ccx.SetScopeForNewJSObjects(obj);
1617 :
1618 4 : PRUint16 interface_count = set->GetInterfaceCount();
1619 4 : XPCNativeInterface** interfaceArray = set->GetInterfaceArray();
1620 16 : for (PRUint16 i = 0; i < interface_count; i++) {
1621 12 : XPCNativeInterface* iface = interfaceArray[i];
1622 12 : PRUint16 member_count = iface->GetMemberCount();
1623 :
1624 103 : for (PRUint16 k = 0; k < member_count; k++) {
1625 91 : if (!xpc_ForcePropertyResolve(cx, obj, iface->GetMemberAt(k)->GetName()))
1626 0 : return false;
1627 : }
1628 : }
1629 :
1630 4 : return true;
1631 : }
1632 :
1633 : static void
1634 186868 : XPC_WN_Shared_Proto_Finalize(JSContext *cx, JSObject *obj)
1635 : {
1636 : // This can be null if xpc shutdown has already happened
1637 186868 : XPCWrappedNativeProto* p = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
1638 186868 : if (p)
1639 186781 : p->JSProtoObjectFinalized(cx, obj);
1640 186868 : }
1641 :
1642 : static void
1643 891643 : XPC_WN_Shared_Proto_Trace(JSTracer *trc, JSObject *obj)
1644 : {
1645 : // This can be null if xpc shutdown has already happened
1646 : XPCWrappedNativeProto* p =
1647 891643 : (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
1648 891643 : if (p)
1649 891565 : TraceScopeJSObjects(trc, p->GetScope());
1650 891643 : }
1651 :
1652 : /*****************************************************/
1653 :
1654 : static JSBool
1655 1042 : XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
1656 : {
1657 1042 : NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
1658 : js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass,
1659 : "bad proto");
1660 :
1661 : XPCWrappedNativeProto* self =
1662 1042 : (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
1663 1042 : if (!self)
1664 0 : return false;
1665 :
1666 2084 : XPCCallContext ccx(JS_CALLER, cx);
1667 1042 : if (!ccx.IsValid())
1668 0 : return false;
1669 1042 : ccx.SetScopeForNewJSObjects(obj);
1670 :
1671 1042 : XPCNativeScriptableInfo* si = self->GetScriptableInfo();
1672 1042 : unsigned enumFlag = (si && si->GetFlags().DontEnumStaticProps()) ?
1673 2084 : 0 : JSPROP_ENUMERATE;
1674 :
1675 : return DefinePropertyIfFound(ccx, obj, id,
1676 : self->GetSet(), nsnull, nsnull,
1677 : self->GetScope(),
1678 : true, nsnull, nsnull, si,
1679 1042 : enumFlag, nsnull);
1680 : }
1681 :
1682 : js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass = {
1683 : "XPC_WN_ModsAllowed_WithCall_Proto_JSClass", // name;
1684 : WRAPPER_SLOTS, // flags;
1685 :
1686 : /* Mandatory non-null function pointer members. */
1687 : JS_PropertyStub, // addProperty;
1688 : JS_PropertyStub, // delProperty;
1689 : JS_PropertyStub, // getProperty;
1690 : JS_StrictPropertyStub, // setProperty;
1691 : XPC_WN_Shared_Proto_Enumerate, // enumerate;
1692 : XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
1693 : JS_ConvertStub, // convert;
1694 : XPC_WN_Shared_Proto_Finalize, // finalize;
1695 :
1696 : /* Optionally non-null members start here. */
1697 : nsnull, // checkAccess;
1698 : nsnull, // call;
1699 : nsnull, // construct;
1700 : nsnull, // hasInstance;
1701 : XPC_WN_Shared_Proto_Trace, // trace;
1702 :
1703 : JS_NULL_CLASS_EXT,
1704 : XPC_WN_WithCall_ObjectOps
1705 : };
1706 :
1707 : js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass = {
1708 : "XPC_WN_ModsAllowed_NoCall_Proto_JSClass", // name;
1709 : WRAPPER_SLOTS, // flags;
1710 :
1711 : /* Mandatory non-null function pointer members. */
1712 : JS_PropertyStub, // addProperty;
1713 : JS_PropertyStub, // delProperty;
1714 : JS_PropertyStub, // getProperty;
1715 : JS_StrictPropertyStub, // setProperty;
1716 : XPC_WN_Shared_Proto_Enumerate, // enumerate;
1717 : XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
1718 : JS_ConvertStub, // convert;
1719 : XPC_WN_Shared_Proto_Finalize, // finalize;
1720 :
1721 : /* Optionally non-null members start here. */
1722 : nsnull, // checkAccess;
1723 : nsnull, // call;
1724 : nsnull, // construct;
1725 : nsnull, // hasInstance;
1726 : XPC_WN_Shared_Proto_Trace, // trace;
1727 :
1728 : JS_NULL_CLASS_EXT,
1729 : XPC_WN_NoCall_ObjectOps
1730 : };
1731 :
1732 : /***************************************************************************/
1733 :
1734 : static JSBool
1735 144878 : XPC_WN_OnlyIWrite_Proto_AddPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
1736 : {
1737 144878 : NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
1738 : js::GetObjectClass(obj) == &XPC_WN_NoMods_NoCall_Proto_JSClass,
1739 : "bad proto");
1740 :
1741 : XPCWrappedNativeProto* self =
1742 144878 : (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
1743 144878 : if (!self)
1744 0 : return false;
1745 :
1746 289756 : XPCCallContext ccx(JS_CALLER, cx);
1747 144878 : if (!ccx.IsValid())
1748 0 : return false;
1749 144878 : ccx.SetScopeForNewJSObjects(obj);
1750 :
1751 : // Allow XPConnect to add the property only
1752 144878 : if (ccx.GetResolveName() == id)
1753 144878 : return true;
1754 :
1755 0 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
1756 : }
1757 :
1758 : static JSBool
1759 0 : XPC_WN_OnlyIWrite_Proto_SetPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
1760 : jsval *vp)
1761 : {
1762 0 : return XPC_WN_OnlyIWrite_Proto_AddPropertyStub(cx, obj, id, vp);
1763 : }
1764 :
1765 : static JSBool
1766 1118956 : XPC_WN_NoMods_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
1767 : {
1768 1118956 : NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
1769 : js::GetObjectClass(obj) == &XPC_WN_NoMods_NoCall_Proto_JSClass,
1770 : "bad proto");
1771 :
1772 : XPCWrappedNativeProto* self =
1773 1118956 : (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
1774 1118956 : if (!self)
1775 0 : return false;
1776 :
1777 2237912 : XPCCallContext ccx(JS_CALLER, cx);
1778 1118956 : if (!ccx.IsValid())
1779 0 : return false;
1780 1118956 : ccx.SetScopeForNewJSObjects(obj);
1781 :
1782 1118956 : XPCNativeScriptableInfo* si = self->GetScriptableInfo();
1783 107208 : unsigned enumFlag = (si && si->GetFlags().DontEnumStaticProps()) ?
1784 1226164 : 0 : JSPROP_ENUMERATE;
1785 :
1786 : return DefinePropertyIfFound(ccx, obj, id,
1787 : self->GetSet(), nsnull, nsnull,
1788 : self->GetScope(),
1789 : true, nsnull, nsnull, si,
1790 : JSPROP_READONLY |
1791 : JSPROP_PERMANENT |
1792 1118956 : enumFlag, nsnull);
1793 : }
1794 :
1795 : js::Class XPC_WN_NoMods_WithCall_Proto_JSClass = {
1796 : "XPC_WN_NoMods_WithCall_Proto_JSClass", // name;
1797 : WRAPPER_SLOTS, // flags;
1798 :
1799 : /* Mandatory non-null function pointer members. */
1800 : XPC_WN_OnlyIWrite_Proto_AddPropertyStub, // addProperty;
1801 : XPC_WN_CannotModifyPropertyStub, // delProperty;
1802 : JS_PropertyStub, // getProperty;
1803 : XPC_WN_OnlyIWrite_Proto_SetPropertyStub, // setProperty;
1804 : XPC_WN_Shared_Proto_Enumerate, // enumerate;
1805 : XPC_WN_NoMods_Proto_Resolve, // resolve;
1806 : JS_ConvertStub, // convert;
1807 : XPC_WN_Shared_Proto_Finalize, // finalize;
1808 :
1809 : /* Optionally non-null members start here. */
1810 : nsnull, // checkAccess;
1811 : nsnull, // call;
1812 : nsnull, // construct;
1813 : nsnull, // hasInstance;
1814 : XPC_WN_Shared_Proto_Trace, // trace;
1815 :
1816 : JS_NULL_CLASS_EXT,
1817 : XPC_WN_WithCall_ObjectOps
1818 : };
1819 :
1820 : js::Class XPC_WN_NoMods_NoCall_Proto_JSClass = {
1821 : "XPC_WN_NoMods_NoCall_Proto_JSClass", // name;
1822 : WRAPPER_SLOTS, // flags;
1823 :
1824 : /* Mandatory non-null function pointer members. */
1825 : XPC_WN_OnlyIWrite_Proto_AddPropertyStub, // addProperty;
1826 : XPC_WN_CannotModifyPropertyStub, // delProperty;
1827 : JS_PropertyStub, // getProperty;
1828 : XPC_WN_OnlyIWrite_Proto_SetPropertyStub, // setProperty;
1829 : XPC_WN_Shared_Proto_Enumerate, // enumerate;
1830 : XPC_WN_NoMods_Proto_Resolve, // resolve;
1831 : JS_ConvertStub, // convert;
1832 : XPC_WN_Shared_Proto_Finalize, // finalize;
1833 :
1834 : /* Optionally non-null members start here. */
1835 : nsnull, // checkAccess;
1836 : nsnull, // call;
1837 : nsnull, // construct;
1838 : nsnull, // hasInstance;
1839 : XPC_WN_Shared_Proto_Trace, // trace;
1840 :
1841 : JS_NULL_CLASS_EXT,
1842 : XPC_WN_NoCall_ObjectOps
1843 : };
1844 :
1845 : /***************************************************************************/
1846 :
1847 : static JSBool
1848 0 : XPC_WN_TearOff_Enumerate(JSContext *cx, JSObject *obj)
1849 : {
1850 0 : MORPH_SLIM_WRAPPER(cx, obj);
1851 0 : XPCCallContext ccx(JS_CALLER, cx, obj);
1852 0 : XPCWrappedNative* wrapper = ccx.GetWrapper();
1853 0 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
1854 :
1855 0 : XPCWrappedNativeTearOff* to = ccx.GetTearOff();
1856 : XPCNativeInterface* iface;
1857 :
1858 0 : if (!to || nsnull == (iface = to->GetInterface()))
1859 0 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
1860 :
1861 0 : PRUint16 member_count = iface->GetMemberCount();
1862 0 : for (PRUint16 k = 0; k < member_count; k++) {
1863 0 : if (!xpc_ForcePropertyResolve(cx, obj, iface->GetMemberAt(k)->GetName()))
1864 0 : return false;
1865 : }
1866 :
1867 0 : return true;
1868 : }
1869 :
1870 : static JSBool
1871 79 : XPC_WN_TearOff_Resolve(JSContext *cx, JSObject *obj, jsid id)
1872 : {
1873 79 : MORPH_SLIM_WRAPPER(cx, obj);
1874 158 : XPCCallContext ccx(JS_CALLER, cx, obj);
1875 79 : XPCWrappedNative* wrapper = ccx.GetWrapper();
1876 79 : THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
1877 :
1878 79 : XPCWrappedNativeTearOff* to = ccx.GetTearOff();
1879 : XPCNativeInterface* iface;
1880 :
1881 79 : if (!to || nsnull == (iface = to->GetInterface()))
1882 0 : return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
1883 :
1884 : return DefinePropertyIfFound(ccx, obj, id, nsnull, iface, nsnull,
1885 : wrapper->GetScope(),
1886 : true, nsnull, nsnull, nsnull,
1887 : JSPROP_READONLY |
1888 : JSPROP_PERMANENT |
1889 79 : JSPROP_ENUMERATE, nsnull);
1890 : }
1891 :
1892 : static void
1893 60 : XPC_WN_TearOff_Finalize(JSContext *cx, JSObject *obj)
1894 : {
1895 : XPCWrappedNativeTearOff* p = (XPCWrappedNativeTearOff*)
1896 60 : xpc_GetJSPrivate(obj);
1897 60 : if (!p)
1898 41 : return;
1899 19 : p->JSObjectFinalized();
1900 : }
1901 :
1902 : js::Class XPC_WN_Tearoff_JSClass = {
1903 : "WrappedNative_TearOff", // name;
1904 : WRAPPER_SLOTS, // flags;
1905 :
1906 : XPC_WN_OnlyIWrite_AddPropertyStub, // addProperty;
1907 : XPC_WN_CannotModifyPropertyStub, // delProperty;
1908 : JS_PropertyStub, // getProperty;
1909 : XPC_WN_OnlyIWrite_SetPropertyStub, // setProperty;
1910 : XPC_WN_TearOff_Enumerate, // enumerate;
1911 : XPC_WN_TearOff_Resolve, // resolve;
1912 : XPC_WN_Shared_Convert, // convert;
1913 : XPC_WN_TearOff_Finalize // finalize;
1914 : };
|