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) 1998
23 : * the Initial Developer. All Rights Reserved.
24 : *
25 : * Contributor(s):
26 : * John Bandhauer <jband@netscape.com> (original author)
27 : * Mike Shaver <shaver@mozilla.org>
28 : * Mark Hammond <MarkH@ActiveState.com>
29 : *
30 : * Alternatively, the contents of this file may be used under the terms of
31 : * either of the GNU General Public License Version 2 or later (the "GPL"),
32 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 : * in which case the provisions of the GPL or the LGPL are applicable instead
34 : * of those above. If you wish to allow use of your version of this file only
35 : * under the terms of either the GPL or the LGPL, and not to allow others to
36 : * use your version of this file under the terms of the MPL, indicate your
37 : * decision by deleting the provisions above and replace them with the notice
38 : * and other provisions required by the GPL or the LGPL. If you do not delete
39 : * the provisions above, a recipient may use your version of this file under
40 : * the terms of any one of the MPL, the GPL or the LGPL.
41 : *
42 : * ***** END LICENSE BLOCK ***** */
43 :
44 : /* All the XPConnect private declarations - only include locally. */
45 :
46 : #ifndef xpcprivate_h___
47 : #define xpcprivate_h___
48 :
49 : #include "mozilla/Assertions.h"
50 : #include "mozilla/Attributes.h"
51 : #include "mozilla/Util.h"
52 :
53 : #include <string.h>
54 : #include <stdlib.h>
55 : #include <stdarg.h>
56 : #include <math.h>
57 : #include "xpcpublic.h"
58 : #include "jsapi.h"
59 : #include "jsdhash.h"
60 : #include "jsprf.h"
61 : #include "prprf.h"
62 : #include "jsdbgapi.h"
63 : #include "jsfriendapi.h"
64 : #include "jsgc.h"
65 : #include "jswrapper.h"
66 : #include "nscore.h"
67 : #include "nsXPCOM.h"
68 : #include "nsAutoPtr.h"
69 : #include "nsCycleCollectionParticipant.h"
70 : #include "nsCycleCollector.h"
71 : #include "nsDebug.h"
72 : #include "nsISupports.h"
73 : #include "nsIServiceManager.h"
74 : #include "nsIClassInfoImpl.h"
75 : #include "nsIComponentManager.h"
76 : #include "nsIComponentRegistrar.h"
77 : #include "nsISupportsPrimitives.h"
78 : #include "nsMemory.h"
79 : #include "nsIXPConnect.h"
80 : #include "nsIInterfaceInfo.h"
81 : #include "nsIInterfaceInfoManager.h"
82 : #include "nsIXPCScriptable.h"
83 : #include "nsIXPCSecurityManager.h"
84 : #include "nsIJSRuntimeService.h"
85 : #include "nsWeakReference.h"
86 : #include "nsCOMPtr.h"
87 : #include "nsXPTCUtils.h"
88 : #include "xptinfo.h"
89 : #include "XPCForwards.h"
90 : #include "XPCLog.h"
91 : #include "xpccomponents.h"
92 : #include "xpcexception.h"
93 : #include "xpcjsid.h"
94 : #include "prlong.h"
95 : #include "prmem.h"
96 : #include "prenv.h"
97 : #include "prclist.h"
98 : #include "nsString.h"
99 : #include "nsReadableUtils.h"
100 : #include "nsXPIDLString.h"
101 : #include "nsAutoJSValHolder.h"
102 : #include "mozilla/GuardObjects.h"
103 : #include "mozilla/ReentrantMonitor.h"
104 : #include "mozilla/Mutex.h"
105 : #include "nsDataHashtable.h"
106 :
107 : #include "nsThreadUtils.h"
108 : #include "nsIJSContextStack.h"
109 : #include "nsIJSEngineTelemetryStats.h"
110 : #include "nsDeque.h"
111 :
112 : #include "nsIConsoleService.h"
113 : #include "nsIScriptError.h"
114 : #include "nsIExceptionService.h"
115 :
116 : #include "nsVariant.h"
117 : #include "nsIPropertyBag.h"
118 : #include "nsIProperty.h"
119 : #include "nsCOMArray.h"
120 : #include "nsTArray.h"
121 : #include "nsBaseHashtable.h"
122 : #include "nsHashKeys.h"
123 : #include "nsWrapperCache.h"
124 : #include "nsStringBuffer.h"
125 :
126 : #include "nsIScriptSecurityManager.h"
127 : #include "nsNetUtil.h"
128 :
129 : #include "nsIXPCScriptNotify.h" // used to notify: ScriptEvaluated
130 :
131 : #include "nsIScriptObjectPrincipal.h"
132 : #include "nsIPrincipal.h"
133 : #include "nsISecurityCheckedComponent.h"
134 :
135 : #include "nsIThreadInternal.h"
136 :
137 : #ifdef XP_WIN
138 : // Nasty MS defines
139 : #ifdef GetClassInfo
140 : #undef GetClassInfo
141 : #endif
142 : #ifdef GetClassName
143 : #undef GetClassName
144 : #endif
145 : #endif /* XP_WIN */
146 :
147 : #include "nsINode.h"
148 :
149 : /***************************************************************************/
150 : // Compile time switches for instrumentation and stuff....
151 :
152 : // Note that one would not normally turn *any* of these on in a non-DEBUG build.
153 :
154 : #if defined(DEBUG_jband) || defined(DEBUG_jst) || defined(DEBUG_dbradley) || defined(DEBUG_shaver_no) || defined(DEBUG_timeless)
155 : #define DEBUG_xpc_hacker
156 : #endif
157 :
158 : #if defined(DEBUG_brendan)
159 : #define DEBUG_XPCNativeWrapper 1
160 : #endif
161 :
162 : #ifdef DEBUG
163 : #define XPC_DETECT_LEADING_UPPERCASE_ACCESS_ERRORS
164 : #endif
165 : #define XPC_CHECK_WRAPPER_THREADSAFETY
166 :
167 : #if defined(DEBUG_xpc_hacker)
168 : #define XPC_DUMP_AT_SHUTDOWN
169 : #define XPC_TRACK_WRAPPER_STATS
170 : #define XPC_TRACK_SCOPE_STATS
171 : #define XPC_TRACK_PROTO_STATS
172 : #define XPC_TRACK_DEFERRED_RELEASES
173 : #define XPC_CHECK_WRAPPERS_AT_SHUTDOWN
174 : #define XPC_REPORT_SHADOWED_WRAPPED_NATIVE_MEMBERS
175 : #define XPC_CHECK_CLASSINFO_CLAIMS
176 : #if defined(DEBUG_jst)
177 : #define XPC_ASSERT_CLASSINFO_CLAIMS
178 : #endif
179 : //#define DEBUG_stats_jband 1
180 : //#define XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING
181 : //#define XPC_REPORT_JSCLASS_FLUSHING
182 : //#define XPC_TRACK_AUTOMARKINGPTR_STATS
183 : #endif
184 :
185 : #if defined(DEBUG_dbaron) || defined(DEBUG_bzbarsky) // only part of DEBUG_xpc_hacker!
186 : #define XPC_DUMP_AT_SHUTDOWN
187 : #endif
188 :
189 : /***************************************************************************/
190 : // conditional forward declarations....
191 :
192 : #ifdef XPC_REPORT_SHADOWED_WRAPPED_NATIVE_MEMBERS
193 : void DEBUG_ReportShadowedMembers(XPCNativeSet* set,
194 : XPCWrappedNative* wrapper,
195 : XPCWrappedNativeProto* proto);
196 : #else
197 : #define DEBUG_ReportShadowedMembers(set, wrapper, proto) ((void)0)
198 : #endif
199 :
200 : #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
201 : void DEBUG_ReportWrapperThreadSafetyError(XPCCallContext& ccx,
202 : const char* msg,
203 : const XPCWrappedNative* wrapper);
204 : void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper);
205 : #else
206 : #define DEBUG_CheckWrapperThreadSafety(w) ((void)0)
207 : #endif
208 :
209 : /***************************************************************************/
210 : // default initial sizes for maps (hashtables)
211 :
212 : #define XPC_CONTEXT_MAP_SIZE 16
213 : #define XPC_JS_MAP_SIZE 64
214 : #define XPC_JS_CLASS_MAP_SIZE 64
215 :
216 : #define XPC_NATIVE_MAP_SIZE 64
217 : #define XPC_NATIVE_PROTO_MAP_SIZE 16
218 : #define XPC_DYING_NATIVE_PROTO_MAP_SIZE 16
219 : #define XPC_DETACHED_NATIVE_PROTO_MAP_SIZE 32
220 : #define XPC_NATIVE_INTERFACE_MAP_SIZE 64
221 : #define XPC_NATIVE_SET_MAP_SIZE 64
222 : #define XPC_NATIVE_JSCLASS_MAP_SIZE 32
223 : #define XPC_THIS_TRANSLATOR_MAP_SIZE 8
224 : #define XPC_NATIVE_WRAPPER_MAP_SIZE 16
225 : #define XPC_WRAPPER_MAP_SIZE 16
226 :
227 : /***************************************************************************/
228 : // data declarations...
229 : extern const char XPC_CONTEXT_STACK_CONTRACTID[];
230 : extern const char XPC_RUNTIME_CONTRACTID[];
231 : extern const char XPC_EXCEPTION_CONTRACTID[];
232 : extern const char XPC_CONSOLE_CONTRACTID[];
233 : extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
234 : extern const char XPC_ID_CONTRACTID[];
235 : extern const char XPC_XPCONNECT_CONTRACTID[];
236 :
237 : namespace xpc {
238 :
239 : class PtrAndPrincipalHashKey : public PLDHashEntryHdr
240 : {
241 : public:
242 : typedef PtrAndPrincipalHashKey *KeyType;
243 : typedef const PtrAndPrincipalHashKey *KeyTypePointer;
244 :
245 3369 : PtrAndPrincipalHashKey(const PtrAndPrincipalHashKey *aKey)
246 : : mPtr(aKey->mPtr), mPrincipal(aKey->mPrincipal),
247 3369 : mSavedHash(aKey->mSavedHash)
248 : {
249 3369 : MOZ_COUNT_CTOR(PtrAndPrincipalHashKey);
250 3369 : }
251 :
252 18564 : PtrAndPrincipalHashKey(nsISupports *aPtr, nsIPrincipal *aPrincipal)
253 18564 : : mPtr(aPtr), mPrincipal(aPrincipal)
254 : {
255 18564 : MOZ_COUNT_CTOR(PtrAndPrincipalHashKey);
256 37128 : nsCOMPtr<nsIURI> uri;
257 18564 : aPrincipal->GetURI(getter_AddRefs(uri));
258 : mSavedHash = uri
259 2828 : ? NS_SecurityHashURI(uri)
260 21392 : : (NS_PTR_TO_UINT32(mPtr.get()) >> 2);
261 18564 : }
262 :
263 21929 : ~PtrAndPrincipalHashKey()
264 21929 : {
265 21929 : MOZ_COUNT_DTOR(PtrAndPrincipalHashKey);
266 21929 : }
267 :
268 58428 : PtrAndPrincipalHashKey* GetKey() const
269 : {
270 58428 : return const_cast<PtrAndPrincipalHashKey*>(this);
271 : }
272 : const PtrAndPrincipalHashKey* GetKeyPointer() const { return this; }
273 :
274 : inline bool KeyEquals(const PtrAndPrincipalHashKey* aKey) const;
275 :
276 : static const PtrAndPrincipalHashKey*
277 25298 : KeyToPointer(PtrAndPrincipalHashKey* aKey) { return aKey; }
278 25298 : static PLDHashNumber HashKey(const PtrAndPrincipalHashKey* aKey)
279 : {
280 25298 : return aKey->mSavedHash;
281 : }
282 :
283 0 : nsISupports* GetPtr()
284 : {
285 0 : return mPtr;
286 : }
287 :
288 : enum { ALLOW_MEMMOVE = true };
289 :
290 : protected:
291 : nsCOMPtr<nsISupports> mPtr;
292 : nsCOMPtr<nsIPrincipal> mPrincipal;
293 :
294 : // During shutdown, when we GC, we need to remove these keys from the hash
295 : // table. However, computing the saved hash, NS_SecurityHashURI calls back
296 : // into XPCOM (which is illegal during shutdown). In order to avoid this,
297 : // we compute the hash up front, so when we're in GC during shutdown, we
298 : // don't have to call into XPCOM.
299 : PLDHashNumber mSavedHash;
300 : };
301 :
302 : }
303 :
304 : // This map is only used on the main thread.
305 : typedef nsDataHashtable<xpc::PtrAndPrincipalHashKey, JSCompartment *> XPCCompartmentMap;
306 :
307 : /***************************************************************************/
308 : // Useful macros...
309 :
310 : #define XPC_STRING_GETTER_BODY(dest, src) \
311 : NS_ENSURE_ARG_POINTER(dest); \
312 : char* result; \
313 : if (src) \
314 : result = (char*) nsMemory::Clone(src, \
315 : sizeof(char)*(strlen(src)+1)); \
316 : else \
317 : result = nsnull; \
318 : *dest = result; \
319 : return (result || !src) ? NS_OK : NS_ERROR_OUT_OF_MEMORY
320 :
321 :
322 : #define WRAPPER_SLOTS (JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | \
323 : JSCLASS_HAS_RESERVED_SLOTS(1))
324 :
325 : #define INVALID_OBJECT ((JSObject *)1)
326 :
327 : /***************************************************************************/
328 : // Auto locking support class...
329 :
330 : // We PROMISE to never screw this up.
331 : #ifdef _MSC_VER
332 : #pragma warning(disable : 4355) // OK to pass "this" in member initializer
333 : #endif
334 :
335 : typedef mozilla::ReentrantMonitor XPCLock;
336 :
337 : static inline void xpc_Wait(XPCLock* lock)
338 : {
339 : NS_ASSERTION(lock, "xpc_Wait called with null lock!");
340 : lock->Wait();
341 : }
342 :
343 14728 : static inline void xpc_NotifyAll(XPCLock* lock)
344 : {
345 14728 : NS_ASSERTION(lock, "xpc_NotifyAll called with null lock!");
346 14728 : lock->NotifyAll();
347 14728 : }
348 :
349 : // This is a cloned subset of nsAutoMonitor. We want the use of a monitor -
350 : // mostly because we need reenterability - but we also want to support passing
351 : // a null monitor in without things blowing up. This is used for wrappers that
352 : // are guaranteed to be used only on one thread. We avoid lock overhead by
353 : // using a null monitor. By changing this class we can avoid having multiplte
354 : // code paths or (conditional) manual calls to PR_{Enter,Exit}Monitor.
355 : //
356 : // Note that xpconnect only makes *one* monitor and *mostly* holds it locked
357 : // only through very small critical sections.
358 :
359 : class NS_STACK_CLASS XPCAutoLock {
360 : public:
361 :
362 1404 : static XPCLock* NewLock(const char* name)
363 1404 : {return new mozilla::ReentrantMonitor(name);}
364 1403 : static void DestroyLock(XPCLock* lock)
365 2806 : {delete lock;}
366 :
367 32759450 : XPCAutoLock(XPCLock* lock MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
368 32759450 : : mLock(lock)
369 : {
370 32759450 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
371 32759450 : if (mLock)
372 16397565 : mLock->Enter();
373 32759450 : }
374 :
375 32759450 : ~XPCAutoLock()
376 32759450 : {
377 32759450 : if (mLock) {
378 16397565 : mLock->Exit();
379 : }
380 32759450 : }
381 :
382 : private:
383 : XPCLock* mLock;
384 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
385 :
386 : // Not meant to be implemented. This makes it a compiler error to
387 : // construct or assign an XPCAutoLock object incorrectly.
388 : XPCAutoLock(void) {}
389 : XPCAutoLock(XPCAutoLock& /*aMon*/) {}
390 : XPCAutoLock& operator =(XPCAutoLock& /*aMon*/) {
391 : return *this;
392 : }
393 :
394 : // Not meant to be implemented. This makes it a compiler error to
395 : // attempt to create an XPCAutoLock object on the heap.
396 : static void* operator new(size_t /*size*/) CPP_THROW_NEW {
397 : return nsnull;
398 : }
399 : static void operator delete(void* /*memory*/) {}
400 : };
401 :
402 : /************************************************/
403 :
404 : class NS_STACK_CLASS XPCAutoUnlock {
405 : public:
406 1522567 : XPCAutoUnlock(XPCLock* lock MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
407 1522567 : : mLock(lock)
408 : {
409 1522567 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
410 1522567 : if (mLock) {
411 348503 : mLock->Exit();
412 : }
413 1522567 : }
414 :
415 1522567 : ~XPCAutoUnlock()
416 1522567 : {
417 1522567 : if (mLock)
418 348503 : mLock->Enter();
419 1522567 : }
420 :
421 : private:
422 : XPCLock* mLock;
423 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
424 :
425 : // Not meant to be implemented. This makes it a compiler error to
426 : // construct or assign an XPCAutoUnlock object incorrectly.
427 : XPCAutoUnlock(void) {}
428 : XPCAutoUnlock(XPCAutoUnlock& /*aMon*/) {}
429 : XPCAutoUnlock& operator =(XPCAutoUnlock& /*aMon*/) {
430 : return *this;
431 : }
432 :
433 : // Not meant to be implemented. This makes it a compiler error to
434 : // attempt to create an XPCAutoUnlock object on the heap.
435 : static void* operator new(size_t /*size*/) CPP_THROW_NEW {
436 : return nsnull;
437 : }
438 : static void operator delete(void* /*memory*/) {}
439 : };
440 :
441 : /***************************************************************************
442 : ****************************************************************************
443 : *
444 : * Core runtime and context classes...
445 : *
446 : ****************************************************************************
447 : ***************************************************************************/
448 :
449 : // We have a general rule internally that getters that return addref'd interface
450 : // pointer generally do so using an 'out' parm. When interface pointers are
451 : // returned as function call result values they are not addref'd. Exceptions
452 : // to this rule are noted explicitly.
453 :
454 : // JSTRACE_XML can recursively hold on to more JSTRACE_XML objects, adding it to
455 : // the cycle collector avoids stack overflow.
456 : inline bool
457 4738826 : AddToCCKind(JSGCTraceKind kind)
458 : {
459 4738826 : return kind == JSTRACE_OBJECT || kind == JSTRACE_XML || kind == JSTRACE_SCRIPT;
460 : }
461 :
462 : class nsXPConnect : public nsIXPConnect,
463 : public nsIThreadObserver,
464 : public nsSupportsWeakReference,
465 : public nsCycleCollectionJSRuntime,
466 : public nsCycleCollectionParticipant,
467 : public nsIJSRuntimeService,
468 : public nsIThreadJSContextStack,
469 : public nsIJSEngineTelemetryStats
470 : {
471 : public:
472 : // all the interface method declarations...
473 : NS_DECL_ISUPPORTS
474 : NS_DECL_NSIXPCONNECT
475 : NS_DECL_NSITHREADOBSERVER
476 : NS_DECL_NSIJSRUNTIMESERVICE
477 : NS_DECL_NSIJSCONTEXTSTACK
478 : NS_DECL_NSITHREADJSCONTEXTSTACK
479 : NS_DECL_NSIJSENGINETELEMETRYSTATS
480 :
481 : // non-interface implementation
482 : public:
483 : // These get non-addref'd pointers
484 : static nsXPConnect* GetXPConnect();
485 321 : static nsXPConnect* FastGetXPConnect() { return gSelf ? gSelf : GetXPConnect(); }
486 : static XPCJSRuntime* GetRuntimeInstance();
487 2504789 : XPCJSRuntime* GetRuntime() {return mRuntime;}
488 :
489 : // Gets addref'd pointer
490 : static nsresult GetInterfaceInfoManager(nsIInterfaceInfoSuperManager** iim,
491 : nsXPConnect* xpc = nsnull);
492 :
493 : static JSBool IsISupportsDescendant(nsIInterfaceInfo* info);
494 :
495 1639069 : nsIXPCSecurityManager* GetDefaultSecurityManager() const
496 : {
497 : // mDefaultSecurityManager is main-thread only.
498 1639069 : if (!NS_IsMainThread()) {
499 0 : return nsnull;
500 : }
501 1639069 : return mDefaultSecurityManager;
502 : }
503 :
504 1636899 : PRUint16 GetDefaultSecurityManagerFlags() const
505 1636899 : {return mDefaultSecurityManagerFlags;}
506 :
507 : // This returns an AddRef'd pointer. It does not do this with an 'out' param
508 : // only because this form is required by the generic module macro:
509 : // NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
510 : static nsXPConnect* GetSingleton();
511 :
512 : // Called by module code in dll startup
513 1404 : static void InitStatics() { gSelf = nsnull; gOnceAliveNowDead = false; }
514 : // Called by module code on dll shutdown.
515 : static void ReleaseXPConnectSingleton();
516 :
517 : virtual ~nsXPConnect();
518 :
519 58912 : JSBool IsShuttingDown() const {return mShuttingDown;}
520 :
521 0 : void EnsureGCBeforeCC() { mNeedGCBeforeCC = true; }
522 14728 : void ClearGCBeforeCC() { mNeedGCBeforeCC = false; }
523 :
524 : nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
525 : nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
526 :
527 : // nsCycleCollectionParticipant
528 : NS_IMETHOD Root(void *p);
529 : NS_IMETHOD Unlink(void *p);
530 : NS_IMETHOD Unroot(void *p);
531 : NS_IMETHOD Traverse(void *p,
532 : nsCycleCollectionTraversalCallback &cb);
533 :
534 : // nsCycleCollectionLanguageRuntime
535 : virtual bool NotifyLeaveMainThread();
536 : virtual void NotifyEnterCycleCollectionThread();
537 : virtual void NotifyLeaveCycleCollectionThread();
538 : virtual void NotifyEnterMainThread();
539 : virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
540 : bool explainExpectedLiveGarbage);
541 : virtual nsresult FinishTraverse();
542 : virtual nsresult FinishCycleCollection();
543 : virtual nsCycleCollectionParticipant *ToParticipant(void *p);
544 : virtual bool NeedCollect();
545 : virtual void Collect(PRUint32 reason, PRUint32 kind);
546 : #ifdef DEBUG_CC
547 : virtual void PrintAllReferencesTo(void *p);
548 : #endif
549 :
550 : XPCCallContext *GetCycleCollectionContext()
551 : {
552 : return mCycleCollectionContext;
553 : }
554 :
555 : unsigned GetOutstandingRequests(JSContext* cx);
556 :
557 : // This returns the singleton nsCycleCollectionParticipant for JSContexts.
558 : static nsCycleCollectionParticipant *JSContextParticipant();
559 :
560 : virtual nsIPrincipal* GetPrincipal(JSObject* obj,
561 : bool allowShortCircuit) const;
562 :
563 : void RecordTraversal(void *p, nsISupports *s);
564 : virtual char* DebugPrintJSStack(bool showArgs,
565 : bool showLocals,
566 : bool showThisProps);
567 :
568 :
569 6434 : static bool ReportAllJSExceptions()
570 : {
571 6434 : return gReportAllJSExceptions > 0;
572 : }
573 :
574 : static void CheckForDebugMode(JSRuntime *rt);
575 :
576 : protected:
577 : nsXPConnect();
578 :
579 : private:
580 : static PRThread* FindMainThread();
581 :
582 : private:
583 : // Singleton instance
584 : static nsXPConnect* gSelf;
585 : static JSBool gOnceAliveNowDead;
586 :
587 : XPCJSRuntime* mRuntime;
588 : nsCOMPtr<nsIInterfaceInfoSuperManager> mInterfaceInfoManager;
589 : nsIXPCSecurityManager* mDefaultSecurityManager;
590 : PRUint16 mDefaultSecurityManagerFlags;
591 : JSBool mShuttingDown;
592 : JSBool mNeedGCBeforeCC;
593 :
594 : // nsIThreadInternal doesn't remember which observers it called
595 : // OnProcessNextEvent on when it gets around to calling AfterProcessNextEvent.
596 : // So if XPConnect gets initialized mid-event (which can happen), we'll get
597 : // an 'after' notification without getting an 'on' notification. If we don't
598 : // watch out for this, we'll do an unmatched |pop| on the context stack.
599 : PRUint16 mEventDepth;
600 : #ifdef DEBUG_CC
601 : PLDHashTable mJSRoots;
602 : #endif
603 : nsAutoPtr<XPCCallContext> mCycleCollectionContext;
604 :
605 : typedef nsBaseHashtable<nsVoidPtrHashKey, nsISupports*, nsISupports*> ScopeSet;
606 : ScopeSet mScopes;
607 : nsCOMPtr<nsIXPCScriptable> mBackstagePass;
608 :
609 : static PRUint32 gReportAllJSExceptions;
610 : static JSBool gDebugMode;
611 : static JSBool gDesiredDebugMode;
612 :
613 : public:
614 : static nsIScriptSecurityManager *gScriptSecurityManager;
615 : };
616 :
617 : /***************************************************************************/
618 :
619 : class XPCRootSetElem
620 : {
621 : public:
622 110263 : XPCRootSetElem()
623 : {
624 : #ifdef DEBUG
625 110263 : mNext = nsnull;
626 110263 : mSelfp = nsnull;
627 : #endif
628 110263 : }
629 :
630 109982 : ~XPCRootSetElem()
631 : {
632 109982 : NS_ASSERTION(!mNext, "Must be unlinked");
633 109982 : NS_ASSERTION(!mSelfp, "Must be unlinked");
634 109982 : }
635 :
636 161048 : inline XPCRootSetElem* GetNextRoot() { return mNext; }
637 : void AddToRootSet(XPCLock *lock, XPCRootSetElem **listHead);
638 : void RemoveFromRootSet(XPCLock *lock);
639 :
640 : private:
641 : XPCRootSetElem *mNext;
642 : XPCRootSetElem **mSelfp;
643 : };
644 :
645 : /***************************************************************************/
646 :
647 : // In the current xpconnect system there can only be one XPCJSRuntime.
648 : // So, xpconnect can only be used on one JSRuntime within the process.
649 :
650 : // no virtuals. no refcounting.
651 : class XPCJSRuntime
652 : {
653 : public:
654 : static XPCJSRuntime* newXPCJSRuntime(nsXPConnect* aXPConnect);
655 :
656 1790145 : JSRuntime* GetJSRuntime() const {return mJSRuntime;}
657 1844435 : nsXPConnect* GetXPConnect() const {return mXPConnect;}
658 : JSContext* GetJSCycleCollectionContext();
659 :
660 335219 : JSObject2WrappedJSMap* GetWrappedJSMap() const
661 335219 : {return mWrappedJSMap;}
662 :
663 223193 : IID2WrappedJSClassMap* GetWrappedJSClassMap() const
664 223193 : {return mWrappedJSClassMap;}
665 :
666 2560804 : IID2NativeInterfaceMap* GetIID2NativeInterfaceMap() const
667 2560804 : {return mIID2NativeInterfaceMap;}
668 :
669 375119 : ClassInfo2NativeSetMap* GetClassInfo2NativeSetMap() const
670 375119 : {return mClassInfo2NativeSetMap;}
671 :
672 1194982 : NativeSetMap* GetNativeSetMap() const
673 1194982 : {return mNativeSetMap;}
674 :
675 9176 : IID2ThisTranslatorMap* GetThisTranslatorMap() const
676 9176 : {return mThisTranslatorMap;}
677 :
678 251192 : XPCNativeScriptableSharedMap* GetNativeScriptableSharedMap() const
679 251192 : {return mNativeScriptableSharedMap;}
680 :
681 188185 : XPCWrappedNativeProtoMap* GetDyingWrappedNativeProtoMap() const
682 188185 : {return mDyingWrappedNativeProtoMap;}
683 :
684 191297 : XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const
685 191297 : {return mDetachedWrappedNativeProtoMap;}
686 :
687 1404 : XPCNativeWrapperMap* GetExplicitNativeWrapperMap() const
688 1404 : {return mExplicitNativeWrapperMap;}
689 :
690 49928 : XPCCompartmentMap& GetCompartmentMap()
691 49928 : {return mCompartmentMap;}
692 :
693 16587562 : XPCLock* GetMapLock() const {return mMapLock;}
694 :
695 : JSBool OnJSContextNew(JSContext* cx);
696 :
697 : JSBool DeferredRelease(nsISupports* obj);
698 :
699 1255492 : JSBool GetDoingFinalization() const {return mDoingFinalization;}
700 :
701 : // Mapping of often used strings to jsid atoms that live 'forever'.
702 : //
703 : // To add a new string: add to this list and to XPCJSRuntime::mStrings
704 : // at the top of xpcjsruntime.cpp
705 : enum {
706 : IDX_CONSTRUCTOR = 0 ,
707 : IDX_TO_STRING ,
708 : IDX_TO_SOURCE ,
709 : IDX_LAST_RESULT ,
710 : IDX_RETURN_CODE ,
711 : IDX_VALUE ,
712 : IDX_QUERY_INTERFACE ,
713 : IDX_COMPONENTS ,
714 : IDX_WRAPPED_JSOBJECT ,
715 : IDX_OBJECT ,
716 : IDX_FUNCTION ,
717 : IDX_PROTOTYPE ,
718 : IDX_CREATE_INSTANCE ,
719 : IDX_ITEM ,
720 : IDX_PROTO ,
721 : IDX_ITERATOR ,
722 : IDX_EXPOSEDPROPS ,
723 : IDX_SCRIPTONLY ,
724 : IDX_BASEURIOBJECT ,
725 : IDX_NODEPRINCIPAL ,
726 : IDX_DOCUMENTURIOBJECT ,
727 : IDX_TOTAL_COUNT // just a count of the above
728 : };
729 :
730 12865156 : jsid GetStringID(unsigned index) const
731 : {
732 12865156 : NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
733 12865156 : return mStrIDs[index];
734 : }
735 : jsval GetStringJSVal(unsigned index) const
736 : {
737 : NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
738 : return mStrJSVals[index];
739 : }
740 1888 : const char* GetStringName(unsigned index) const
741 : {
742 1888 : NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
743 1888 : return mStrings[index];
744 : }
745 :
746 : static void TraceBlackJS(JSTracer* trc, void* data);
747 : static void TraceGrayJS(JSTracer* trc, void* data);
748 : void TraceXPConnectRoots(JSTracer *trc);
749 : void AddXPConnectRoots(nsCycleCollectionTraversalCallback& cb);
750 : void UnmarkSkippableJSHolders();
751 :
752 : static void GCCallback(JSRuntime *rt, JSGCStatus status);
753 : static void FinalizeCallback(JSContext *cx, JSFinalizeStatus status);
754 :
755 : inline void AddVariantRoot(XPCTraceableVariant* variant);
756 : inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
757 : inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
758 :
759 : nsresult AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
760 : nsresult RemoveJSHolder(void* aHolder);
761 :
762 : static void SuspectWrappedNative(XPCWrappedNative *wrapper,
763 : nsCycleCollectionTraversalCallback &cb);
764 :
765 : void DebugDump(PRInt16 depth);
766 :
767 : void SystemIsBeingShutDown();
768 :
769 2007018 : PRThread* GetThreadRunningGC() const {return mThreadRunningGC;}
770 :
771 : ~XPCJSRuntime();
772 :
773 : #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
774 : void DEBUG_AddWrappedNative(nsIXPConnectWrappedNative* wrapper)
775 : {XPCAutoLock lock(GetMapLock());
776 : JSDHashEntryHdr *entry =
777 : JS_DHashTableOperate(DEBUG_WrappedNativeHashtable,
778 : wrapper, JS_DHASH_ADD);
779 : if (entry) ((JSDHashEntryStub *)entry)->key = wrapper;}
780 :
781 : void DEBUG_RemoveWrappedNative(nsIXPConnectWrappedNative* wrapper)
782 : {XPCAutoLock lock(GetMapLock());
783 : JS_DHashTableOperate(DEBUG_WrappedNativeHashtable,
784 : wrapper, JS_DHASH_REMOVE);}
785 : private:
786 : JSDHashTable* DEBUG_WrappedNativeHashtable;
787 : public:
788 : #endif
789 :
790 : void AddGCCallback(JSGCCallback cb);
791 : void RemoveGCCallback(JSGCCallback cb);
792 :
793 : static void ActivityCallback(void *arg, JSBool active);
794 :
795 15475 : bool NewDOMBindingsEnabled()
796 : {
797 15475 : return gNewDOMBindingsEnabled;
798 : }
799 :
800 : size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
801 :
802 : private:
803 : XPCJSRuntime(); // no implementation
804 : XPCJSRuntime(nsXPConnect* aXPConnect);
805 :
806 : // The caller must be holding the GC lock
807 : void RescheduleWatchdog(XPCContext* ccx);
808 :
809 : static void WatchdogMain(void *arg);
810 :
811 : static bool gNewDOMBindingsEnabled;
812 :
813 : static const char* mStrings[IDX_TOTAL_COUNT];
814 : jsid mStrIDs[IDX_TOTAL_COUNT];
815 : jsval mStrJSVals[IDX_TOTAL_COUNT];
816 :
817 : nsXPConnect* mXPConnect;
818 : JSRuntime* mJSRuntime;
819 : JSContext* mJSCycleCollectionContext;
820 : JSObject2WrappedJSMap* mWrappedJSMap;
821 : IID2WrappedJSClassMap* mWrappedJSClassMap;
822 : IID2NativeInterfaceMap* mIID2NativeInterfaceMap;
823 : ClassInfo2NativeSetMap* mClassInfo2NativeSetMap;
824 : NativeSetMap* mNativeSetMap;
825 : IID2ThisTranslatorMap* mThisTranslatorMap;
826 : XPCNativeScriptableSharedMap* mNativeScriptableSharedMap;
827 : XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
828 : XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap;
829 : XPCNativeWrapperMap* mExplicitNativeWrapperMap;
830 : XPCCompartmentMap mCompartmentMap;
831 : XPCLock* mMapLock;
832 : PRThread* mThreadRunningGC;
833 : nsTArray<nsXPCWrappedJS*> mWrappedJSToReleaseArray;
834 : nsTArray<nsISupports*> mNativesToReleaseArray;
835 : JSBool mDoingFinalization;
836 : XPCRootSetElem *mVariantRoots;
837 : XPCRootSetElem *mWrappedJSRoots;
838 : XPCRootSetElem *mObjectHolderRoots;
839 : JSDHashTable mJSHolders;
840 : PRLock *mWatchdogLock;
841 : PRCondVar *mWatchdogWakeup;
842 : PRThread *mWatchdogThread;
843 : nsTArray<JSGCCallback> extraGCCallbacks;
844 : bool mWatchdogHibernating;
845 : PRTime mLastActiveTime; // -1 if active NOW
846 :
847 : friend class AutoLockWatchdog;
848 : };
849 :
850 : /***************************************************************************/
851 : /***************************************************************************/
852 : // XPCContext is mostly a dumb class to hold JSContext specific data and
853 : // maps that let us find wrappers created for the given JSContext.
854 :
855 : // no virtuals
856 : class XPCContext
857 : {
858 : friend class XPCJSRuntime;
859 : public:
860 16067049 : static XPCContext* GetXPCContext(JSContext* aJSContext)
861 : {
862 16067049 : NS_ASSERTION(JS_GetSecondContextPrivate(aJSContext), "should already have XPCContext");
863 16067049 : return static_cast<XPCContext *>(JS_GetSecondContextPrivate(aJSContext));
864 : }
865 :
866 14136287 : XPCJSRuntime* GetRuntime() const {return mRuntime;}
867 94253 : JSContext* GetJSContext() const {return mJSContext;}
868 :
869 : enum LangType {LANG_UNKNOWN, LANG_JS, LANG_NATIVE};
870 :
871 : LangType GetCallingLangType() const
872 : {
873 : return mCallingLangType;
874 : }
875 31749366 : LangType SetCallingLangType(LangType lt)
876 : {
877 31749366 : LangType tmp = mCallingLangType;
878 31749366 : mCallingLangType = lt;
879 31749366 : return tmp;
880 : }
881 15213089 : JSBool CallerTypeIsJavaScript() const
882 : {
883 15213089 : return LANG_JS == mCallingLangType;
884 : }
885 : JSBool CallerTypeIsNative() const
886 : {
887 : return LANG_NATIVE == mCallingLangType;
888 : }
889 8460745 : JSBool CallerTypeIsKnown() const
890 : {
891 8460745 : return LANG_UNKNOWN != mCallingLangType;
892 : }
893 :
894 6889 : nsresult GetException(nsIException** e)
895 : {
896 6889 : NS_IF_ADDREF(mException);
897 6889 : *e = mException;
898 6889 : return NS_OK;
899 : }
900 1225740 : void SetException(nsIException* e)
901 : {
902 1225740 : NS_IF_ADDREF(e);
903 1225740 : NS_IF_RELEASE(mException);
904 1225740 : mException = e;
905 1225740 : }
906 :
907 2 : nsresult GetLastResult() {return mLastResult;}
908 13504660 : void SetLastResult(nsresult rc) {mLastResult = rc;}
909 :
910 6889 : nsresult GetPendingResult() {return mPendingResult;}
911 1225564 : void SetPendingResult(nsresult rc) {mPendingResult = rc;}
912 :
913 1387 : nsIXPCSecurityManager* GetSecurityManager() const
914 1387 : {return mSecurityManager;}
915 1387 : void SetSecurityManager(nsIXPCSecurityManager* aSecurityManager)
916 1387 : {mSecurityManager = aSecurityManager;}
917 :
918 0 : PRUint16 GetSecurityManagerFlags() const
919 0 : {return mSecurityManagerFlags;}
920 1387 : void SetSecurityManagerFlags(PRUint16 f)
921 1387 : {mSecurityManagerFlags = f;}
922 :
923 8460745 : nsIXPCSecurityManager* GetAppropriateSecurityManager(PRUint16 flags) const
924 : {
925 8460745 : NS_ASSERTION(CallerTypeIsKnown(),"missing caller type set somewhere");
926 8460745 : if (!CallerTypeIsJavaScript())
927 597769 : return nsnull;
928 7862976 : if (mSecurityManager) {
929 6226077 : if (flags & mSecurityManagerFlags)
930 6226077 : return mSecurityManager;
931 : } else {
932 : nsIXPCSecurityManager* mgr;
933 1636899 : nsXPConnect* xpc = mRuntime->GetXPConnect();
934 1636899 : mgr = xpc->GetDefaultSecurityManager();
935 1636899 : if (mgr && (flags & xpc->GetDefaultSecurityManagerFlags()))
936 1636899 : return mgr;
937 : }
938 0 : return nsnull;
939 : }
940 :
941 : void DebugDump(PRInt16 depth);
942 15475 : void AddScope(PRCList *scope) { PR_INSERT_AFTER(scope, &mScopes); }
943 1639 : void RemoveScope(PRCList *scope) { PR_REMOVE_LINK(scope); }
944 :
945 : ~XPCContext();
946 :
947 : private:
948 : XPCContext(); // no implementation
949 : XPCContext(XPCJSRuntime* aRuntime, JSContext* aJSContext);
950 :
951 : static XPCContext* newXPCContext(XPCJSRuntime* aRuntime,
952 : JSContext* aJSContext);
953 : private:
954 : XPCJSRuntime* mRuntime;
955 : JSContext* mJSContext;
956 : nsresult mLastResult;
957 : nsresult mPendingResult;
958 : nsIXPCSecurityManager* mSecurityManager;
959 : nsIException* mException;
960 : LangType mCallingLangType;
961 : PRUint16 mSecurityManagerFlags;
962 :
963 : // A linked list of scopes to notify when we are destroyed.
964 : PRCList mScopes;
965 : };
966 :
967 : /***************************************************************************/
968 :
969 : #define NATIVE_CALLER XPCContext::LANG_NATIVE
970 : #define JS_CALLER XPCContext::LANG_JS
971 :
972 : // class to export a JSString as an const nsAString, no refcounting :(
973 : class XPCReadableJSStringWrapper : public nsDependentString
974 241865 : {
975 : public:
976 : typedef nsDependentString::char_traits char_traits;
977 :
978 258385 : XPCReadableJSStringWrapper(const PRUnichar *chars, size_t length) :
979 258385 : nsDependentString(chars, length)
980 258385 : { }
981 :
982 22486 : XPCReadableJSStringWrapper() :
983 22486 : nsDependentString(char_traits::sEmptyBuffer, char_traits::sEmptyBuffer)
984 22486 : { SetIsVoid(true); }
985 :
986 : JSBool init(JSContext* aContext, JSString* str)
987 : {
988 : size_t length;
989 : const jschar* chars = JS_GetStringCharsZAndLength(aContext, str, &length);
990 : if (!chars)
991 : return false;
992 :
993 : NS_ASSERTION(IsEmpty(), "init() on initialized string");
994 : new(static_cast<nsDependentString *>(this)) nsDependentString(chars, length);
995 : return true;
996 : }
997 : };
998 :
999 : // No virtuals
1000 : // XPCCallContext is ALWAYS declared as a local variable in some function;
1001 : // i.e. instance lifetime is always controled by some C++ function returning.
1002 : //
1003 : // These things are created frequently in many places. We *intentionally* do
1004 : // not inialialize all members in order to save on construction overhead.
1005 : // Some constructor pass more valid params than others. We init what must be
1006 : // init'd and leave other members undefined. In debug builds the accessors
1007 : // use a CHECK_STATE macro to track whether or not the object is in a valid
1008 : // state to answer the question a caller might be asking. As long as this
1009 : // class is maintained correctly it can do its job without a bunch of added
1010 : // overhead from useless initializations and non-DEBUG error checking.
1011 : //
1012 : // Note that most accessors are inlined.
1013 :
1014 : class XPCCallContext : public nsAXPCNativeCallContext
1015 : {
1016 : public:
1017 : NS_IMETHOD GetCallee(nsISupports **aResult);
1018 : NS_IMETHOD GetCalleeMethodIndex(PRUint16 *aResult);
1019 : NS_IMETHOD GetCalleeWrapper(nsIXPConnectWrappedNative **aResult);
1020 : NS_IMETHOD GetJSContext(JSContext **aResult);
1021 : NS_IMETHOD GetArgc(PRUint32 *aResult);
1022 : NS_IMETHOD GetArgvPtr(jsval **aResult);
1023 : NS_IMETHOD GetCalleeInterface(nsIInterfaceInfo **aResult);
1024 : NS_IMETHOD GetCalleeClassInfo(nsIClassInfo **aResult);
1025 : NS_IMETHOD GetPreviousCallContext(nsAXPCNativeCallContext **aResult);
1026 : NS_IMETHOD GetLanguage(PRUint16 *aResult);
1027 :
1028 : enum {NO_ARGS = (unsigned) -1};
1029 :
1030 : XPCCallContext(XPCContext::LangType callerLanguage,
1031 : JSContext* cx = nsnull,
1032 : JSObject* obj = nsnull,
1033 : JSObject* funobj = nsnull,
1034 : jsid id = JSID_VOID,
1035 : unsigned argc = NO_ARGS,
1036 : jsval *argv = nsnull,
1037 : jsval *rval = nsnull);
1038 :
1039 : virtual ~XPCCallContext();
1040 :
1041 : inline JSBool IsValid() const ;
1042 :
1043 : inline nsXPConnect* GetXPConnect() const ;
1044 : inline XPCJSRuntime* GetRuntime() const ;
1045 : inline XPCPerThreadData* GetThreadData() const ;
1046 : inline XPCContext* GetXPCContext() const ;
1047 : inline JSContext* GetJSContext() const ;
1048 : inline JSBool GetContextPopRequired() const ;
1049 : inline XPCContext::LangType GetCallerLanguage() const ;
1050 : inline XPCContext::LangType GetPrevCallerLanguage() const ;
1051 : inline XPCCallContext* GetPrevCallContext() const ;
1052 :
1053 : /*
1054 : * The 'scope for new JSObjects' will be the scope for objects created when
1055 : * carrying out a JS/C++ call. This member is only available if HAVE_SCOPE.
1056 : * The object passed to the ccx constructor is used as the scope for new
1057 : * JSObjects. However, this object is also queried for a wrapper, so
1058 : * clients that don't want a wrapper (and thus pass NULL to the ccx
1059 : * constructor) need to manually call SetScopeForNewJSObjects.
1060 : */
1061 : inline JSObject* GetScopeForNewJSObjects() const ;
1062 : inline void SetScopeForNewJSObjects(JSObject *obj) ;
1063 :
1064 : inline JSObject* GetFlattenedJSObject() const ;
1065 : inline nsISupports* GetIdentityObject() const ;
1066 : inline XPCWrappedNative* GetWrapper() const ;
1067 : inline XPCWrappedNativeProto* GetProto() const ;
1068 :
1069 : inline JSBool CanGetTearOff() const ;
1070 : inline XPCWrappedNativeTearOff* GetTearOff() const ;
1071 :
1072 : inline XPCNativeScriptableInfo* GetScriptableInfo() const ;
1073 : inline JSBool CanGetSet() const ;
1074 : inline XPCNativeSet* GetSet() const ;
1075 : inline JSBool CanGetInterface() const ;
1076 : inline XPCNativeInterface* GetInterface() const ;
1077 : inline XPCNativeMember* GetMember() const ;
1078 : inline JSBool HasInterfaceAndMember() const ;
1079 : inline jsid GetName() const ;
1080 : inline JSBool GetStaticMemberIsLocal() const ;
1081 : inline unsigned GetArgc() const ;
1082 : inline jsval* GetArgv() const ;
1083 : inline jsval* GetRetVal() const ;
1084 :
1085 : inline PRUint16 GetMethodIndex() const ;
1086 : inline void SetMethodIndex(PRUint16 index) ;
1087 :
1088 : inline JSBool GetDestroyJSContextInDestructor() const;
1089 : inline void SetDestroyJSContextInDestructor(JSBool b);
1090 :
1091 : inline jsid GetResolveName() const;
1092 : inline jsid SetResolveName(jsid name);
1093 :
1094 : inline XPCWrappedNative* GetResolvingWrapper() const;
1095 : inline XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w);
1096 :
1097 : inline void SetRetVal(jsval val);
1098 :
1099 : void SetName(jsid name);
1100 : void SetArgsAndResultPtr(unsigned argc, jsval *argv, jsval *rval);
1101 : void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
1102 : JSBool isSetter);
1103 :
1104 : nsresult CanCallNow();
1105 :
1106 : void SystemIsBeingShutDown();
1107 :
1108 39810616 : operator JSContext*() const {return GetJSContext();}
1109 :
1110 : XPCReadableJSStringWrapper *NewStringWrapper(const PRUnichar *str, PRUint32 len);
1111 : void DeleteString(nsAString *string);
1112 :
1113 : private:
1114 :
1115 : // no copy ctor or assignment allowed
1116 : XPCCallContext(const XPCCallContext& r); // not implemented
1117 : XPCCallContext& operator= (const XPCCallContext& r); // not implemented
1118 :
1119 : friend class XPCLazyCallContext;
1120 : XPCCallContext(XPCContext::LangType callerLanguage,
1121 : JSContext* cx,
1122 : JSBool callBeginRequest,
1123 : JSObject* obj,
1124 : JSObject* flattenedJSObject,
1125 : XPCWrappedNative* wn,
1126 : XPCWrappedNativeTearOff* tearoff);
1127 :
1128 : enum WrapperInitOptions {
1129 : WRAPPER_PASSED_TO_CONSTRUCTOR,
1130 : INIT_SHOULD_LOOKUP_WRAPPER
1131 : };
1132 :
1133 : void Init(XPCContext::LangType callerLanguage,
1134 : JSBool callBeginRequest,
1135 : JSObject* obj,
1136 : JSObject* funobj,
1137 : WrapperInitOptions wrapperInitOptions,
1138 : jsid name,
1139 : unsigned argc,
1140 : jsval *argv,
1141 : jsval *rval);
1142 :
1143 : private:
1144 : // posible values for mState
1145 : enum State {
1146 : INIT_FAILED,
1147 : SYSTEM_SHUTDOWN,
1148 : HAVE_CONTEXT,
1149 : HAVE_SCOPE,
1150 : HAVE_OBJECT,
1151 : HAVE_NAME,
1152 : HAVE_ARGS,
1153 : READY_TO_CALL,
1154 : CALL_DONE
1155 : };
1156 :
1157 : #ifdef DEBUG
1158 297806288 : inline void CHECK_STATE(int s) const {NS_ASSERTION(mState >= s, "bad state");}
1159 : #else
1160 : #define CHECK_STATE(s) ((void)0)
1161 : #endif
1162 :
1163 : private:
1164 : State mState;
1165 :
1166 : nsXPConnect* mXPC;
1167 :
1168 : XPCPerThreadData* mThreadData;
1169 : XPCContext* mXPCContext;
1170 : JSContext* mJSContext;
1171 : JSBool mContextPopRequired;
1172 : JSBool mDestroyJSContextInDestructor;
1173 :
1174 : XPCContext::LangType mCallerLanguage;
1175 :
1176 : // ctor does not necessarily init the following. BEWARE!
1177 :
1178 : XPCContext::LangType mPrevCallerLanguage;
1179 :
1180 : XPCCallContext* mPrevCallContext;
1181 :
1182 : JSObject* mScopeForNewJSObjects;
1183 : JSObject* mFlattenedJSObject;
1184 : XPCWrappedNative* mWrapper;
1185 : XPCWrappedNativeTearOff* mTearOff;
1186 :
1187 : XPCNativeScriptableInfo* mScriptableInfo;
1188 :
1189 : XPCNativeSet* mSet;
1190 : XPCNativeInterface* mInterface;
1191 : XPCNativeMember* mMember;
1192 :
1193 : jsid mName;
1194 : JSBool mStaticMemberIsLocal;
1195 :
1196 : unsigned mArgc;
1197 : jsval* mArgv;
1198 : jsval* mRetVal;
1199 :
1200 : PRUint16 mMethodIndex;
1201 :
1202 : #define XPCCCX_STRING_CACHE_SIZE 2
1203 :
1204 : // String wrapper entry, holds a string, and a boolean that tells
1205 : // whether the string is in use or not.
1206 : //
1207 : // NB: The string is not stored by value so that we avoid the cost of
1208 : // construction/destruction.
1209 : struct StringWrapperEntry
1210 : {
1211 31749366 : StringWrapperEntry() : mInUse(false) { }
1212 :
1213 : js::AlignedStorage2<XPCReadableJSStringWrapper> mString;
1214 : bool mInUse;
1215 : };
1216 :
1217 : StringWrapperEntry mScratchStrings[XPCCCX_STRING_CACHE_SIZE];
1218 : };
1219 :
1220 : class XPCLazyCallContext
1221 : {
1222 : public:
1223 20940305 : XPCLazyCallContext(XPCCallContext& ccx)
1224 : : mCallBeginRequest(DONT_CALL_BEGINREQUEST),
1225 : mCcx(&ccx),
1226 : mCcxToDestroy(nsnull)
1227 : #ifdef DEBUG
1228 : , mCx(nsnull)
1229 : , mCallerLanguage(JS_CALLER)
1230 : , mObj(nsnull)
1231 : , mFlattenedJSObject(nsnull)
1232 : , mWrapper(nsnull)
1233 20940305 : , mTearOff(nsnull)
1234 : #endif
1235 : {
1236 20940305 : }
1237 142781 : XPCLazyCallContext(XPCContext::LangType callerLanguage, JSContext* cx,
1238 : JSObject* obj = nsnull,
1239 : JSObject* flattenedJSObject = nsnull,
1240 : XPCWrappedNative* wrapper = nsnull,
1241 : XPCWrappedNativeTearOff* tearoff = nsnull)
1242 : : mCallBeginRequest(callerLanguage == NATIVE_CALLER ?
1243 : CALL_BEGINREQUEST : DONT_CALL_BEGINREQUEST),
1244 : mCcx(nsnull),
1245 : mCcxToDestroy(nsnull),
1246 : mCx(cx),
1247 : mCallerLanguage(callerLanguage),
1248 : mObj(obj),
1249 : mFlattenedJSObject(flattenedJSObject),
1250 : mWrapper(wrapper),
1251 142781 : mTearOff(tearoff)
1252 : {
1253 142781 : NS_ASSERTION(cx, "Need a JS context!");
1254 142781 : NS_ASSERTION(callerLanguage == NATIVE_CALLER ||
1255 : callerLanguage == JS_CALLER,
1256 : "Can't deal with unknown caller language!");
1257 : #ifdef DEBUG
1258 142781 : AssertContextIsTopOfStack(cx);
1259 : #endif
1260 142781 : }
1261 21083086 : ~XPCLazyCallContext()
1262 : {
1263 21083086 : if (mCcxToDestroy)
1264 132930 : mCcxToDestroy->~XPCCallContext();
1265 20950156 : else if (mCallBeginRequest == CALLED_BEGINREQUEST)
1266 0 : JS_EndRequest(mCx);
1267 21083086 : }
1268 : void SetWrapper(XPCWrappedNative* wrapper,
1269 : XPCWrappedNativeTearOff* tearoff);
1270 : void SetWrapper(JSObject* flattenedJSObject);
1271 :
1272 25219838 : JSContext *GetJSContext()
1273 : {
1274 25219838 : if (mCcx)
1275 24955205 : return mCcx->GetJSContext();
1276 :
1277 264633 : if (mCallBeginRequest == CALL_BEGINREQUEST) {
1278 103009 : JS_BeginRequest(mCx);
1279 103009 : mCallBeginRequest = CALLED_BEGINREQUEST;
1280 : }
1281 :
1282 264633 : return mCx;
1283 : }
1284 8820036 : JSObject *GetScopeForNewJSObjects() const
1285 : {
1286 8820036 : if (mCcx)
1287 8544038 : return mCcx->GetScopeForNewJSObjects();
1288 :
1289 275998 : return mObj;
1290 : }
1291 648602 : void SetScopeForNewJSObjects(JSObject *obj)
1292 : {
1293 648602 : if (mCcx) {
1294 545593 : mCcx->SetScopeForNewJSObjects(obj);
1295 545593 : return;
1296 : }
1297 103009 : NS_ABORT_IF_FALSE(!mObj, "already set!");
1298 103009 : mObj = obj;
1299 : }
1300 : JSObject *GetFlattenedJSObject() const
1301 : {
1302 : if (mCcx)
1303 : return mCcx->GetFlattenedJSObject();
1304 :
1305 : return mFlattenedJSObject;
1306 : }
1307 5505747 : XPCCallContext &GetXPCCallContext()
1308 : {
1309 5505747 : if (!mCcx) {
1310 : mCcxToDestroy = mCcx =
1311 : new (mData) XPCCallContext(mCallerLanguage, mCx,
1312 : mCallBeginRequest == CALL_BEGINREQUEST,
1313 : mObj,
1314 : mFlattenedJSObject, mWrapper,
1315 132930 : mTearOff);
1316 132930 : if (!mCcx->IsValid()) {
1317 0 : NS_ERROR("This is not supposed to fail!");
1318 : }
1319 : }
1320 :
1321 5505747 : return *mCcx;
1322 : }
1323 :
1324 : private:
1325 : #ifdef DEBUG
1326 : static void AssertContextIsTopOfStack(JSContext* cx);
1327 : #endif
1328 :
1329 : enum {
1330 : DONT_CALL_BEGINREQUEST,
1331 : CALL_BEGINREQUEST,
1332 : CALLED_BEGINREQUEST
1333 : } mCallBeginRequest;
1334 :
1335 : XPCCallContext *mCcx;
1336 : XPCCallContext *mCcxToDestroy;
1337 : JSContext *mCx;
1338 : XPCContext::LangType mCallerLanguage;
1339 : JSObject *mObj;
1340 : JSObject *mFlattenedJSObject;
1341 : XPCWrappedNative *mWrapper;
1342 : XPCWrappedNativeTearOff *mTearOff;
1343 : char mData[sizeof(XPCCallContext)];
1344 : };
1345 :
1346 : /***************************************************************************
1347 : ****************************************************************************
1348 : *
1349 : * Core classes for wrapped native objects for use from JavaScript...
1350 : *
1351 : ****************************************************************************
1352 : ***************************************************************************/
1353 :
1354 : // These are the various JSClasses and callbacks whose use that required
1355 : // visibility from more than one .cpp file.
1356 :
1357 : struct XPCWrappedNativeJSClass;
1358 : extern XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass;
1359 : extern js::Class XPC_WN_NoMods_WithCall_Proto_JSClass;
1360 : extern js::Class XPC_WN_NoMods_NoCall_Proto_JSClass;
1361 : extern js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass;
1362 : extern js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
1363 : extern js::Class XPC_WN_Tearoff_JSClass;
1364 : extern js::Class XPC_WN_NoHelper_Proto_JSClass;
1365 :
1366 : extern JSBool
1367 : XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
1368 :
1369 : extern JSBool
1370 : XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp);
1371 :
1372 : extern JSBool
1373 : XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp);
1374 :
1375 : extern JSBool
1376 : XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
1377 : jsval *statep, jsid *idp);
1378 :
1379 : extern JSType
1380 : XPC_WN_JSOp_TypeOf_Object(JSContext *cx, JSObject *obj);
1381 :
1382 : extern JSType
1383 : XPC_WN_JSOp_TypeOf_Function(JSContext *cx, JSObject *obj);
1384 :
1385 : extern void
1386 : XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj);
1387 :
1388 : extern JSObject*
1389 : XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
1390 :
1391 : // Macros to initialize Object or Function like XPC_WN classes
1392 : #define XPC_WN_WithCall_ObjectOps \
1393 : { \
1394 : nsnull, /* lookupGeneric */ \
1395 : nsnull, /* lookupProperty */ \
1396 : nsnull, /* lookupElement */ \
1397 : nsnull, /* lookupSpecial */ \
1398 : nsnull, /* defineGeneric */ \
1399 : nsnull, /* defineProperty */ \
1400 : nsnull, /* defineElement */ \
1401 : nsnull, /* defineSpecial */ \
1402 : nsnull, /* getGeneric */ \
1403 : nsnull, /* getProperty */ \
1404 : nsnull, /* getElement */ \
1405 : nsnull, /* getElementIfPresent */ \
1406 : nsnull, /* getSpecial */ \
1407 : nsnull, /* setGeneric */ \
1408 : nsnull, /* setProperty */ \
1409 : nsnull, /* setElement */ \
1410 : nsnull, /* setSpecial */ \
1411 : nsnull, /* getGenericAttributes */ \
1412 : nsnull, /* getAttributes */ \
1413 : nsnull, /* getElementAttributes */ \
1414 : nsnull, /* getSpecialAttributes */ \
1415 : nsnull, /* setGenericAttributes */ \
1416 : nsnull, /* setAttributes */ \
1417 : nsnull, /* setElementAttributes */ \
1418 : nsnull, /* setSpecialAttributes */ \
1419 : nsnull, /* deleteProperty */ \
1420 : nsnull, /* deleteElement */ \
1421 : nsnull, /* deleteSpecial */ \
1422 : XPC_WN_JSOp_Enumerate, \
1423 : XPC_WN_JSOp_TypeOf_Function, \
1424 : nsnull, /* fix */ \
1425 : XPC_WN_JSOp_ThisObject, \
1426 : XPC_WN_JSOp_Clear \
1427 : }
1428 :
1429 : #define XPC_WN_NoCall_ObjectOps \
1430 : { \
1431 : nsnull, /* lookupGeneric */ \
1432 : nsnull, /* lookupProperty */ \
1433 : nsnull, /* lookupElement */ \
1434 : nsnull, /* lookupSpecial */ \
1435 : nsnull, /* defineGeneric */ \
1436 : nsnull, /* defineProperty */ \
1437 : nsnull, /* defineElement */ \
1438 : nsnull, /* defineSpecial */ \
1439 : nsnull, /* getGeneric */ \
1440 : nsnull, /* getProperty */ \
1441 : nsnull, /* getElement */ \
1442 : nsnull, /* getElementIfPresent */ \
1443 : nsnull, /* getSpecial */ \
1444 : nsnull, /* setGeneric */ \
1445 : nsnull, /* setProperty */ \
1446 : nsnull, /* setElement */ \
1447 : nsnull, /* setSpecial */ \
1448 : nsnull, /* getGenericAttributes */ \
1449 : nsnull, /* getAttributes */ \
1450 : nsnull, /* getElementAttributes */ \
1451 : nsnull, /* getSpecialAttributes */ \
1452 : nsnull, /* setGenericAttributes */ \
1453 : nsnull, /* setAttributes */ \
1454 : nsnull, /* setElementAttributes */ \
1455 : nsnull, /* setSpecialAttributes */ \
1456 : nsnull, /* deleteProperty */ \
1457 : nsnull, /* deleteElement */ \
1458 : nsnull, /* deleteSpecial */ \
1459 : XPC_WN_JSOp_Enumerate, \
1460 : XPC_WN_JSOp_TypeOf_Object, \
1461 : nsnull, /* fix */ \
1462 : XPC_WN_JSOp_ThisObject, \
1463 : XPC_WN_JSOp_Clear \
1464 : }
1465 :
1466 : // Maybe this macro should check for class->enumerate ==
1467 : // XPC_WN_Shared_Proto_Enumerate or something rather than checking for
1468 : // 4 classes?
1469 6731238 : static inline bool IS_PROTO_CLASS(js::Class *clazz)
1470 : {
1471 : return clazz == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
1472 : clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass ||
1473 : clazz == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
1474 6731238 : clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
1475 : }
1476 :
1477 : /***************************************************************************/
1478 :
1479 : namespace XPCWrapper {
1480 :
1481 : enum WrapperType {
1482 : UNKNOWN = 0,
1483 : NONE = 0,
1484 : XPCNW_IMPLICIT = 1 << 0,
1485 : XPCNW_EXPLICIT = 1 << 1,
1486 : XPCNW = (XPCNW_IMPLICIT | XPCNW_EXPLICIT),
1487 : SJOW = 1 << 2,
1488 : // SJOW must be the last wrapper type that can be returned to chrome.
1489 :
1490 : XOW = 1 << 3,
1491 : COW = 1 << 4,
1492 : SOW = 1 << 5
1493 : };
1494 :
1495 : }
1496 :
1497 : /***************************************************************************/
1498 : // XPCWrappedNativeScope is one-to-one with a JS global object.
1499 :
1500 : class XPCWrappedNativeScope : public PRCList
1501 : {
1502 : public:
1503 :
1504 : static XPCWrappedNativeScope*
1505 : GetNewOrUsed(XPCCallContext& ccx, JSObject* aGlobal, nsISupports* aNative = nsnull);
1506 :
1507 : XPCJSRuntime*
1508 15630829 : GetRuntime() const {return mRuntime;}
1509 :
1510 : Native2WrappedNativeMap*
1511 4518813 : GetWrappedNativeMap() const {return mWrappedNativeMap;}
1512 :
1513 : ClassInfo2WrappedNativeProtoMap*
1514 569855 : GetWrappedNativeProtoMap(JSBool aMainThreadOnly) const
1515 : {return aMainThreadOnly ?
1516 : mMainThreadWrappedNativeProtoMap :
1517 569855 : mWrappedNativeProtoMap;}
1518 :
1519 : nsXPCComponents*
1520 4556 : GetComponents() const {return mComponents;}
1521 :
1522 : JSObject*
1523 4979154 : GetGlobalJSObject() const {return mGlobalJSObject;}
1524 :
1525 : JSObject*
1526 3363691 : GetPrototypeJSObject() const {return mPrototypeJSObject;}
1527 :
1528 : // Getter for the prototype that we use for wrappers that have no
1529 : // helper.
1530 : JSObject*
1531 : GetPrototypeNoHelper(XPCCallContext& ccx);
1532 :
1533 : nsIPrincipal*
1534 1867645 : GetPrincipal() const
1535 : {return mScriptObjectPrincipal ?
1536 1867645 : mScriptObjectPrincipal->GetPrincipal() : nsnull;}
1537 :
1538 : void RemoveWrappedNativeProtos();
1539 :
1540 : static XPCWrappedNativeScope*
1541 : FindInJSObjectScope(JSContext* cx, JSObject* obj,
1542 : JSBool OKIfNotInitialized = false,
1543 : XPCJSRuntime* runtime = nsnull);
1544 :
1545 : static XPCWrappedNativeScope*
1546 129480 : FindInJSObjectScope(XPCCallContext& ccx, JSObject* obj,
1547 : JSBool OKIfNotInitialized = false)
1548 : {
1549 : return FindInJSObjectScope(ccx, obj, OKIfNotInitialized,
1550 129480 : ccx.GetRuntime());
1551 : }
1552 :
1553 : static void
1554 : SystemIsBeingShutDown();
1555 :
1556 : static void
1557 : TraceJS(JSTracer* trc, XPCJSRuntime* rt);
1558 :
1559 : static void
1560 : SuspectAllWrappers(XPCJSRuntime* rt, nsCycleCollectionTraversalCallback &cb);
1561 :
1562 : static void
1563 : FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt);
1564 :
1565 : static void
1566 : FinishedFinalizationPhaseOfGC(JSContext* cx);
1567 :
1568 : static void
1569 : MarkAllWrappedNativesAndProtos();
1570 :
1571 : static nsresult
1572 : ClearAllWrappedNativeSecurityPolicies(XPCCallContext& ccx);
1573 :
1574 : #ifdef DEBUG
1575 : static void
1576 : ASSERT_NoInterfaceSetsAreMarked();
1577 : #endif
1578 :
1579 : static void
1580 : SweepAllWrappedNativeTearOffs();
1581 :
1582 : static void
1583 : DebugDumpAllScopes(PRInt16 depth);
1584 :
1585 : void
1586 : DebugDump(PRInt16 depth);
1587 :
1588 : static size_t
1589 : SizeOfAllScopesIncludingThis(nsMallocSizeOfFun mallocSizeOf);
1590 :
1591 : size_t
1592 : SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
1593 :
1594 : JSBool
1595 : IsValid() const {return mRuntime != nsnull;}
1596 :
1597 : static JSBool
1598 : IsDyingScope(XPCWrappedNativeScope *scope);
1599 :
1600 : void SetComponents(nsXPCComponents* aComponents);
1601 : void SetGlobal(XPCCallContext& ccx, JSObject* aGlobal, nsISupports* aNative);
1602 :
1603 1404 : static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; }
1604 :
1605 94291 : XPCContext *GetContext() { return mContext; }
1606 13835 : void SetContext(XPCContext *xpcc) { mContext = nsnull; }
1607 :
1608 20027 : nsDataHashtable<nsDepCharHashKey, JSObject*>& GetCachedDOMPrototypes()
1609 : {
1610 20027 : return mCachedDOMPrototypes;
1611 : }
1612 :
1613 757498 : static XPCWrappedNativeScope *GetNativeScope(JSObject *obj)
1614 : {
1615 757498 : MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_XPCONNECT_GLOBAL);
1616 :
1617 757498 : const js::Value &v = js::GetObjectSlot(obj, JSCLASS_GLOBAL_SLOT_COUNT);
1618 757498 : return v.isUndefined()
1619 : ? nsnull
1620 757498 : : static_cast<XPCWrappedNativeScope *>(v.toPrivate());
1621 : }
1622 : void TraceDOMPrototypes(JSTracer *trc);
1623 :
1624 0 : JSBool NewDOMBindingsEnabled()
1625 : {
1626 0 : return mNewDOMBindingsEnabled;
1627 : }
1628 :
1629 : protected:
1630 : XPCWrappedNativeScope(XPCCallContext& ccx, JSObject* aGlobal, nsISupports* aNative);
1631 : virtual ~XPCWrappedNativeScope();
1632 :
1633 : static void KillDyingScopes();
1634 :
1635 : XPCWrappedNativeScope(); // not implemented
1636 :
1637 : private:
1638 : static XPCWrappedNativeScope* gScopes;
1639 : static XPCWrappedNativeScope* gDyingScopes;
1640 :
1641 : XPCJSRuntime* mRuntime;
1642 : Native2WrappedNativeMap* mWrappedNativeMap;
1643 : ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap;
1644 : ClassInfo2WrappedNativeProtoMap* mMainThreadWrappedNativeProtoMap;
1645 : nsXPCComponents* mComponents;
1646 : XPCWrappedNativeScope* mNext;
1647 : // The JS global object for this scope. If non-null, this will be the
1648 : // default parent for the XPCWrappedNatives that have us as the scope,
1649 : // unless a PreCreate hook overrides it. Note that this _may_ be null (see
1650 : // constructor).
1651 : js::ObjectPtr mGlobalJSObject;
1652 :
1653 : // Cached value of Object.prototype
1654 : js::ObjectPtr mPrototypeJSObject;
1655 : // Prototype to use for wrappers with no helper.
1656 : JSObject* mPrototypeNoHelper;
1657 :
1658 : XPCContext* mContext;
1659 :
1660 : // The script object principal instance corresponding to our current global
1661 : // JS object.
1662 : // XXXbz what happens if someone calls JS_SetPrivate on mGlobalJSObject.
1663 : // How do we deal? Do we need to? I suspect this isn't worth worrying
1664 : // about, since all of our scope objects are verified as not doing that.
1665 : nsIScriptObjectPrincipal* mScriptObjectPrincipal;
1666 :
1667 : nsDataHashtable<nsDepCharHashKey, JSObject*> mCachedDOMPrototypes;
1668 :
1669 : JSBool mNewDOMBindingsEnabled;
1670 : };
1671 :
1672 : /***************************************************************************/
1673 : // XPCNativeMember represents a single idl declared method, attribute or
1674 : // constant.
1675 :
1676 : // Tight. No virtual methods. Can be bitwise copied (until any resolution done).
1677 :
1678 : class XPCNativeMember
1679 : {
1680 : public:
1681 : static JSBool GetCallInfo(XPCCallContext& ccx,
1682 : JSObject* funobj,
1683 : XPCNativeInterface** pInterface,
1684 : XPCNativeMember** pMember);
1685 :
1686 71547090 : jsid GetName() const {return mName;}
1687 :
1688 10145937 : PRUint16 GetIndex() const {return mIndex;}
1689 :
1690 20080 : JSBool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
1691 : jsval* pval)
1692 20080 : {NS_ASSERTION(IsConstant(),
1693 : "Only call this if you're sure this is a constant!");
1694 20080 : return Resolve(ccx, iface, nsnull, pval);}
1695 :
1696 : JSBool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface,
1697 : JSObject *parent, jsval* pval);
1698 :
1699 3452412 : JSBool IsMethod() const
1700 3452412 : {return 0 != (mFlags & METHOD);}
1701 :
1702 8447680 : JSBool IsConstant() const
1703 8447680 : {return 0 != (mFlags & CONSTANT);}
1704 :
1705 1194789 : JSBool IsAttribute() const
1706 1194789 : {return 0 != (mFlags & GETTER);}
1707 :
1708 1297124 : JSBool IsWritableAttribute() const
1709 1297124 : {return 0 != (mFlags & SETTER_TOO);}
1710 :
1711 172725 : JSBool IsReadOnlyAttribute() const
1712 172725 : {return IsAttribute() && !IsWritableAttribute();}
1713 :
1714 :
1715 1701890 : void SetName(jsid a) {mName = a;}
1716 :
1717 810166 : void SetMethod(PRUint16 index)
1718 810166 : {mFlags = METHOD; mIndex = index;}
1719 :
1720 388193 : void SetConstant(PRUint16 index)
1721 388193 : {mFlags = CONSTANT; mIndex = index;}
1722 :
1723 503531 : void SetReadOnlyAttribute(PRUint16 index)
1724 503531 : {mFlags = GETTER; mIndex = index;}
1725 :
1726 172725 : void SetWritableAttribute()
1727 172725 : {NS_ASSERTION(mFlags == GETTER,"bad"); mFlags = GETTER | SETTER_TOO;}
1728 :
1729 : /* default ctor - leave random contents */
1730 4699200 : XPCNativeMember() {MOZ_COUNT_CTOR(XPCNativeMember);}
1731 4699180 : ~XPCNativeMember() {MOZ_COUNT_DTOR(XPCNativeMember);}
1732 :
1733 : private:
1734 : JSBool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
1735 : JSObject *parent, jsval *vp);
1736 :
1737 : enum {
1738 : METHOD = 0x01,
1739 : CONSTANT = 0x02,
1740 : GETTER = 0x04,
1741 : SETTER_TOO = 0x08
1742 : };
1743 :
1744 : private:
1745 : // our only data...
1746 : jsid mName;
1747 : PRUint16 mIndex;
1748 : PRUint16 mFlags;
1749 : };
1750 :
1751 : /***************************************************************************/
1752 : // XPCNativeInterface represents a single idl declared interface. This is
1753 : // primarily the set of XPCNativeMembers.
1754 :
1755 : // Tight. No virtual methods.
1756 :
1757 : class XPCNativeInterface
1758 : {
1759 : public:
1760 : static XPCNativeInterface* GetNewOrUsed(XPCCallContext& ccx,
1761 : const nsIID* iid);
1762 : static XPCNativeInterface* GetNewOrUsed(XPCCallContext& ccx,
1763 : nsIInterfaceInfo* info);
1764 : static XPCNativeInterface* GetNewOrUsed(XPCCallContext& ccx,
1765 : const char* name);
1766 : static XPCNativeInterface* GetISupports(XPCCallContext& ccx);
1767 :
1768 7461279 : inline nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo.get();}
1769 12426824 : inline jsid GetName() const {return mName;}
1770 :
1771 : inline const nsIID* GetIID() const;
1772 : inline const char* GetNameString() const;
1773 : inline XPCNativeMember* FindMember(jsid name) const;
1774 :
1775 : inline JSBool HasAncestor(const nsIID* iid) const;
1776 :
1777 299148 : PRUint16 GetMemberCount() const
1778 299148 : {NS_ASSERTION(!IsMarked(), "bad"); return mMemberCount;}
1779 10200 : XPCNativeMember* GetMemberAt(PRUint16 i)
1780 10200 : {NS_ASSERTION(i < mMemberCount, "bad index"); return &mMembers[i];}
1781 :
1782 : void DebugDump(PRInt16 depth);
1783 :
1784 : #define XPC_NATIVE_IFACE_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
1785 :
1786 546637 : void Mark() {mMemberCount |= XPC_NATIVE_IFACE_MARK_FLAG;}
1787 275830 : void Unmark() {mMemberCount &= ~XPC_NATIVE_IFACE_MARK_FLAG;}
1788 13817650 : JSBool IsMarked() const
1789 13817650 : {return 0 != (mMemberCount & XPC_NATIVE_IFACE_MARK_FLAG);}
1790 :
1791 : // NOP. This is just here to make the AutoMarkingPtr code compile.
1792 0 : inline void TraceJS(JSTracer* trc) {}
1793 0 : inline void AutoTrace(JSTracer* trc) {}
1794 :
1795 : static void DestroyInstance(XPCNativeInterface* inst);
1796 :
1797 : size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
1798 :
1799 : protected:
1800 : static XPCNativeInterface* NewInstance(XPCCallContext& ccx,
1801 : nsIInterfaceInfo* aInfo);
1802 :
1803 : XPCNativeInterface(); // not implemented
1804 127559 : XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName)
1805 127559 : : mInfo(aInfo), mName(aName), mMemberCount(0)
1806 127559 : {MOZ_COUNT_CTOR(XPCNativeInterface);}
1807 127539 : ~XPCNativeInterface() {MOZ_COUNT_DTOR(XPCNativeInterface);}
1808 :
1809 127559 : void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
1810 :
1811 : XPCNativeInterface(const XPCNativeInterface& r); // not implemented
1812 : XPCNativeInterface& operator= (const XPCNativeInterface& r); // not implemented
1813 :
1814 : private:
1815 : nsCOMPtr<nsIInterfaceInfo> mInfo;
1816 : jsid mName;
1817 : PRUint16 mMemberCount;
1818 : XPCNativeMember mMembers[1]; // always last - object sized for array
1819 : };
1820 :
1821 : /***************************************************************************/
1822 : // XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap.
1823 :
1824 : class XPCNativeSetKey
1825 : {
1826 : public:
1827 1193578 : XPCNativeSetKey(XPCNativeSet* BaseSet = nsnull,
1828 : XPCNativeInterface* Addition = nsnull,
1829 : PRUint16 Position = 0)
1830 : : mIsAKey(IS_A_KEY), mPosition(Position), mBaseSet(BaseSet),
1831 1193578 : mAddition(Addition) {}
1832 1193578 : ~XPCNativeSetKey() {}
1833 :
1834 2372350 : XPCNativeSet* GetBaseSet() const {return mBaseSet;}
1835 2372350 : XPCNativeInterface* GetAddition() const {return mAddition;}
1836 1507862 : PRUint16 GetPosition() const {return mPosition;}
1837 :
1838 : // This is a fun little hack...
1839 : // We build these keys only on the stack. We use them for lookup in
1840 : // NativeSetMap. Becasue we don't want to pay the cost of cloning a key and
1841 : // sticking it into the hashtable, when the XPCNativeSet actually
1842 : // gets added to the table the 'key' in the table is a pointer to the
1843 : // set itself and not this key. Our key compare function expects to get
1844 : // a key and a set. When we do external lookups in the map we pass in one
1845 : // of these keys and our compare function gets passed a key and a set.
1846 : // (see compare_NativeKeyToSet in xpcmaps.cpp). This is all well and good.
1847 : // Except, when the table decides to resize itself. Then it tries to use
1848 : // our compare function with the 'keys' that are in the hashtable (which are
1849 : // really XPCNativeSet objects and not XPCNativeSetKey objects!
1850 : //
1851 : // So, the hack is to have the compare function assume it is getting a
1852 : // XPCNativeSetKey pointer and call this IsAKey method. If that fails then
1853 : // it realises that it really has a XPCNativeSet pointer and deals with that
1854 : // fact. This is safe because we know that both of these classes have no
1855 : // virtual methods and their first data member is a PRUint16. We are
1856 : // confident that XPCNativeSet->mMemberCount will never be 0xffff.
1857 :
1858 2372350 : JSBool IsAKey() const {return mIsAKey == IS_A_KEY;}
1859 :
1860 : enum {IS_A_KEY = 0xffff};
1861 :
1862 : // Allow shallow copy
1863 :
1864 : private:
1865 : PRUint16 mIsAKey; // must be first data member
1866 : PRUint16 mPosition;
1867 : XPCNativeSet* mBaseSet;
1868 : XPCNativeInterface* mAddition;
1869 : };
1870 :
1871 : /***************************************************************************/
1872 : // XPCNativeSet represents an ordered collection of XPCNativeInterface pointers.
1873 :
1874 : class XPCNativeSet
1875 : {
1876 : public:
1877 : static XPCNativeSet* GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid);
1878 : static XPCNativeSet* GetNewOrUsed(XPCCallContext& ccx,
1879 : nsIClassInfo* classInfo);
1880 : static XPCNativeSet* GetNewOrUsed(XPCCallContext& ccx,
1881 : XPCNativeSet* otherSet,
1882 : XPCNativeInterface* newInterface,
1883 : PRUint16 position);
1884 :
1885 : static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
1886 :
1887 : inline JSBool FindMember(jsid name, XPCNativeMember** pMember,
1888 : PRUint16* pInterfaceIndex) const;
1889 :
1890 : inline JSBool FindMember(jsid name, XPCNativeMember** pMember,
1891 : XPCNativeInterface** pInterface) const;
1892 :
1893 : inline JSBool FindMember(jsid name,
1894 : XPCNativeMember** pMember,
1895 : XPCNativeInterface** pInterface,
1896 : XPCNativeSet* protoSet,
1897 : JSBool* pIsLocal) const;
1898 :
1899 : inline JSBool HasInterface(XPCNativeInterface* aInterface) const;
1900 : inline JSBool HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const;
1901 : inline JSBool HasInterfaceWithAncestor(const nsIID* iid) const;
1902 :
1903 : inline XPCNativeInterface* FindInterfaceWithIID(const nsIID& iid) const;
1904 :
1905 : inline XPCNativeInterface* FindNamedInterface(jsid name) const;
1906 :
1907 25631 : PRUint16 GetMemberCount() const {return mMemberCount;}
1908 2585356 : PRUint16 GetInterfaceCount() const
1909 2585356 : {NS_ASSERTION(!IsMarked(), "bad"); return mInterfaceCount;}
1910 762837 : XPCNativeInterface** GetInterfaceArray() {return mInterfaces;}
1911 :
1912 864487 : XPCNativeInterface* GetInterfaceAt(PRUint16 i)
1913 864487 : {NS_ASSERTION(i < mInterfaceCount, "bad index"); return mInterfaces[i];}
1914 :
1915 : inline JSBool MatchesSetUpToInterface(const XPCNativeSet* other,
1916 : XPCNativeInterface* iface) const;
1917 :
1918 : #define XPC_NATIVE_SET_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
1919 :
1920 : inline void Mark();
1921 :
1922 : // NOP. This is just here to make the AutoMarkingPtr code compile.
1923 0 : inline void TraceJS(JSTracer* trc) {}
1924 0 : inline void AutoTrace(JSTracer* trc) {}
1925 :
1926 : private:
1927 221767 : void MarkSelfOnly() {mInterfaceCount |= XPC_NATIVE_SET_MARK_FLAG;}
1928 : public:
1929 221767 : void Unmark() {mInterfaceCount &= ~XPC_NATIVE_SET_MARK_FLAG;}
1930 13565231 : JSBool IsMarked() const
1931 13565231 : {return 0 != (mInterfaceCount & XPC_NATIVE_SET_MARK_FLAG);}
1932 :
1933 : #ifdef DEBUG
1934 : inline void ASSERT_NotMarked();
1935 : #endif
1936 :
1937 : void DebugDump(PRInt16 depth);
1938 :
1939 : static void DestroyInstance(XPCNativeSet* inst);
1940 :
1941 : size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
1942 :
1943 : protected:
1944 : static XPCNativeSet* NewInstance(XPCCallContext& ccx,
1945 : XPCNativeInterface** array,
1946 : PRUint16 count);
1947 : static XPCNativeSet* NewInstanceMutate(XPCNativeSet* otherSet,
1948 : XPCNativeInterface* newInterface,
1949 : PRUint16 position);
1950 192276 : XPCNativeSet() {MOZ_COUNT_CTOR(XPCNativeSet);}
1951 192264 : ~XPCNativeSet() {MOZ_COUNT_DTOR(XPCNativeSet);}
1952 192276 : void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
1953 :
1954 : private:
1955 : PRUint16 mMemberCount;
1956 : PRUint16 mInterfaceCount;
1957 : XPCNativeInterface* mInterfaces[1]; // always last - object sized for array
1958 : };
1959 :
1960 : /***************************************************************************/
1961 : // XPCNativeScriptableFlags is a wrapper class that holds the flags returned
1962 : // from calls to nsIXPCScriptable::GetScriptableFlags(). It has convenience
1963 : // methods to check for particular bitflags. Since we also use this class as
1964 : // a member of the gc'd class XPCNativeScriptableShared, this class holds the
1965 : // bit and exposes the inlined methods to support marking.
1966 :
1967 : #define XPC_WN_SJSFLAGS_MARK_FLAG JS_BIT(31) // only high bit of 32 is set
1968 :
1969 : class XPCNativeScriptableFlags
1970 : {
1971 : private:
1972 : uint32_t mFlags;
1973 :
1974 : public:
1975 :
1976 3178754 : XPCNativeScriptableFlags(uint32_t flags = 0) : mFlags(flags) {}
1977 :
1978 1395727 : uint32_t GetFlags() const {return mFlags & ~XPC_WN_SJSFLAGS_MARK_FLAG;}
1979 : void SetFlags(uint32_t flags) {mFlags = flags;}
1980 :
1981 977921 : operator uint32_t() const {return GetFlags();}
1982 :
1983 30310 : XPCNativeScriptableFlags(const XPCNativeScriptableFlags& r)
1984 30310 : {mFlags = r.GetFlags();}
1985 :
1986 387496 : XPCNativeScriptableFlags& operator= (const XPCNativeScriptableFlags& r)
1987 387496 : {mFlags = r.GetFlags(); return *this;}
1988 :
1989 5526377 : void Mark() {mFlags |= XPC_WN_SJSFLAGS_MARK_FLAG;}
1990 101050 : void Unmark() {mFlags &= ~XPC_WN_SJSFLAGS_MARK_FLAG;}
1991 122164 : JSBool IsMarked() const {return 0 != (mFlags & XPC_WN_SJSFLAGS_MARK_FLAG);}
1992 :
1993 : #ifdef GET_IT
1994 : #undef GET_IT
1995 : #endif
1996 : #define GET_IT(f_) const {return 0 != (mFlags & nsIXPCScriptable:: f_ );}
1997 :
1998 1491909 : JSBool WantPreCreate() GET_IT(WANT_PRECREATE)
1999 276837 : JSBool WantCreate() GET_IT(WANT_CREATE)
2000 276837 : JSBool WantPostCreate() GET_IT(WANT_POSTCREATE)
2001 21231 : JSBool WantAddProperty() GET_IT(WANT_ADDPROPERTY)
2002 21231 : JSBool WantDelProperty() GET_IT(WANT_DELPROPERTY)
2003 21231 : JSBool WantGetProperty() GET_IT(WANT_GETPROPERTY)
2004 21231 : JSBool WantSetProperty() GET_IT(WANT_SETPROPERTY)
2005 16380 : JSBool WantEnumerate() GET_IT(WANT_ENUMERATE)
2006 21549 : JSBool WantNewEnumerate() GET_IT(WANT_NEWENUMERATE)
2007 1538913 : JSBool WantNewResolve() GET_IT(WANT_NEWRESOLVE)
2008 21231 : JSBool WantConvert() GET_IT(WANT_CONVERT)
2009 21231 : JSBool WantFinalize() GET_IT(WANT_FINALIZE)
2010 21231 : JSBool WantCheckAccess() GET_IT(WANT_CHECKACCESS)
2011 41076 : JSBool WantCall() GET_IT(WANT_CALL)
2012 22901 : JSBool WantConstruct() GET_IT(WANT_CONSTRUCT)
2013 21231 : JSBool WantHasInstance() GET_IT(WANT_HASINSTANCE)
2014 2371 : JSBool WantEquality() GET_IT(WANT_EQUALITY)
2015 21231 : JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT)
2016 19433 : JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY)
2017 21228 : JSBool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY)
2018 19326 : JSBool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY)
2019 522303 : JSBool DontEnumStaticProps() GET_IT(DONT_ENUM_STATIC_PROPS)
2020 278777 : JSBool DontEnumQueryInterface() GET_IT(DONT_ENUM_QUERY_INTERFACE)
2021 622802 : JSBool DontAskInstanceForScriptable() GET_IT(DONT_ASK_INSTANCE_FOR_SCRIPTABLE)
2022 587448 : JSBool ClassInfoInterfacesOnly() GET_IT(CLASSINFO_INTERFACES_ONLY)
2023 1851393 : JSBool AllowPropModsDuringResolve() GET_IT(ALLOW_PROP_MODS_DURING_RESOLVE)
2024 257255 : JSBool AllowPropModsToPrototype() GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE)
2025 278786 : JSBool IsGlobalObject() GET_IT(IS_GLOBAL_OBJECT)
2026 25385 : JSBool DontReflectInterfaceNames() GET_IT(DONT_REFLECT_INTERFACE_NAMES)
2027 21231 : JSBool UseStubEqualityHook() GET_IT(USE_STUB_EQUALITY_HOOK)
2028 :
2029 : #undef GET_IT
2030 : };
2031 :
2032 : /***************************************************************************/
2033 :
2034 : // XPCNativeScriptableShared is used to hold the JSClass and the
2035 : // associated scriptable flags for XPCWrappedNatives. These are shared across
2036 : // the runtime and are garbage collected by xpconnect. We *used* to just store
2037 : // this inside the XPCNativeScriptableInfo (usually owned by instances of
2038 : // XPCWrappedNativeProto. This had two problems... It was wasteful, and it
2039 : // was a big problem when wrappers are reparented to different scopes (and
2040 : // thus different protos (the DOM does this).
2041 :
2042 : // We maintain the invariant that every JSClass for which ext.isWrappedNative
2043 : // is true is a contained in an instance of this struct, and can thus be cast
2044 : // to it.
2045 : struct XPCWrappedNativeJSClass
2046 : {
2047 : js::Class base;
2048 : PRUint32 interfacesBitmap;
2049 : };
2050 :
2051 : class XPCNativeScriptableShared
2052 : {
2053 : public:
2054 4990101 : const XPCNativeScriptableFlags& GetFlags() const {return mFlags;}
2055 457114 : PRUint32 GetInterfacesBitmap() const
2056 457114 : {return mJSClass.interfacesBitmap;}
2057 2929964 : JSClass* GetJSClass()
2058 2929964 : {return Jsvalify(&mJSClass.base);}
2059 15155 : JSClass* GetSlimJSClass()
2060 15155 : {if (mCanBeSlim) return GetJSClass(); return nsnull;}
2061 :
2062 271019 : XPCNativeScriptableShared(uint32_t aFlags, char* aName,
2063 : PRUint32 interfacesBitmap)
2064 : : mFlags(aFlags),
2065 271019 : mCanBeSlim(false)
2066 271019 : {memset(&mJSClass, 0, sizeof(mJSClass));
2067 271019 : mJSClass.base.name = aName; // take ownership
2068 271019 : mJSClass.interfacesBitmap = interfacesBitmap;
2069 271019 : MOZ_COUNT_CTOR(XPCNativeScriptableShared);}
2070 :
2071 270902 : ~XPCNativeScriptableShared()
2072 270902 : {if (mJSClass.base.name)nsMemory::Free((void*)mJSClass.base.name);
2073 270902 : MOZ_COUNT_DTOR(XPCNativeScriptableShared);}
2074 :
2075 21231 : char* TransferNameOwnership()
2076 21231 : {char* name=(char*)mJSClass.base.name; mJSClass.base.name = nsnull;
2077 21231 : return name;}
2078 :
2079 : void PopulateJSClass();
2080 :
2081 5526377 : void Mark() {mFlags.Mark();}
2082 101050 : void Unmark() {mFlags.Unmark();}
2083 122164 : JSBool IsMarked() const {return mFlags.IsMarked();}
2084 :
2085 : private:
2086 : XPCNativeScriptableFlags mFlags;
2087 : XPCWrappedNativeJSClass mJSClass;
2088 : JSBool mCanBeSlim;
2089 : };
2090 :
2091 : /***************************************************************************/
2092 : // XPCNativeScriptableInfo is used to hold the nsIXPCScriptable state for a
2093 : // given class or instance.
2094 :
2095 : class XPCNativeScriptableInfo
2096 : {
2097 : public:
2098 : static XPCNativeScriptableInfo*
2099 : Construct(XPCCallContext& ccx, const XPCNativeScriptableCreateInfo* sci);
2100 :
2101 : nsIXPCScriptable*
2102 2041899 : GetCallback() const {return mCallback;}
2103 :
2104 : const XPCNativeScriptableFlags&
2105 4283199 : GetFlags() const {return mShared->GetFlags();}
2106 :
2107 : PRUint32
2108 0 : GetInterfacesBitmap() const {return mShared->GetInterfacesBitmap();}
2109 :
2110 : JSClass*
2111 2207907 : GetJSClass() {return mShared->GetJSClass();}
2112 :
2113 : JSClass*
2114 15155 : GetSlimJSClass() {return mShared->GetSlimJSClass();}
2115 :
2116 : XPCNativeScriptableShared*
2117 0 : GetScriptableShared() {return mShared;}
2118 :
2119 : void
2120 : SetCallback(nsIXPCScriptable* s) {mCallback = s;}
2121 : void
2122 : SetCallback(already_AddRefed<nsIXPCScriptable> s) {mCallback = s;}
2123 :
2124 : void
2125 249788 : SetScriptableShared(XPCNativeScriptableShared* shared) {mShared = shared;}
2126 :
2127 5526377 : void Mark() {
2128 5526377 : if (mShared)
2129 5526377 : mShared->Mark();
2130 5526377 : }
2131 :
2132 0 : void TraceJS(JSTracer *trc) {}
2133 0 : void AutoTrace(JSTracer *trc) {}
2134 :
2135 : protected:
2136 249788 : XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nsnull,
2137 : XPCNativeScriptableShared* shared = nsnull)
2138 249788 : : mCallback(scriptable), mShared(shared)
2139 249788 : {MOZ_COUNT_CTOR(XPCNativeScriptableInfo);}
2140 : public:
2141 249739 : ~XPCNativeScriptableInfo() {MOZ_COUNT_DTOR(XPCNativeScriptableInfo);}
2142 : private:
2143 :
2144 : // disable copy ctor and assignment
2145 : XPCNativeScriptableInfo(const XPCNativeScriptableInfo& r); // not implemented
2146 : XPCNativeScriptableInfo& operator= (const XPCNativeScriptableInfo& r); // not implemented
2147 :
2148 : private:
2149 : nsCOMPtr<nsIXPCScriptable> mCallback;
2150 : XPCNativeScriptableShared* mShared;
2151 : };
2152 :
2153 : /***************************************************************************/
2154 : // XPCNativeScriptableCreateInfo is used in creating new wrapper and protos.
2155 : // it abstracts out the scriptable interface pointer and the flags. After
2156 : // creation these are factored differently using XPCNativeScriptableInfo.
2157 :
2158 : class NS_STACK_CLASS XPCNativeScriptableCreateInfo
2159 2515633 : {
2160 : public:
2161 :
2162 0 : XPCNativeScriptableCreateInfo(const XPCNativeScriptableInfo& si)
2163 0 : : mCallback(si.GetCallback()), mFlags(si.GetFlags()),
2164 0 : mInterfacesBitmap(si.GetInterfacesBitmap()) {}
2165 :
2166 15155 : XPCNativeScriptableCreateInfo(already_AddRefed<nsIXPCScriptable> callback,
2167 : XPCNativeScriptableFlags flags,
2168 : PRUint32 interfacesBitmap)
2169 : : mCallback(callback), mFlags(flags),
2170 15155 : mInterfacesBitmap(interfacesBitmap) {}
2171 :
2172 2500478 : XPCNativeScriptableCreateInfo()
2173 2500478 : : mFlags(0), mInterfacesBitmap(0) {}
2174 :
2175 :
2176 : nsIXPCScriptable*
2177 4074908 : GetCallback() const {return mCallback;}
2178 :
2179 : const XPCNativeScriptableFlags&
2180 3828028 : GetFlags() const {return mFlags;}
2181 :
2182 : PRUint32
2183 249788 : GetInterfacesBitmap() const {return mInterfacesBitmap;}
2184 :
2185 : void
2186 362111 : SetCallback(already_AddRefed<nsIXPCScriptable> callback)
2187 362111 : {mCallback = callback;}
2188 :
2189 : void
2190 362111 : SetFlags(const XPCNativeScriptableFlags& flags) {mFlags = flags;}
2191 :
2192 : void
2193 11682 : SetInterfacesBitmap(PRUint32 interfacesBitmap)
2194 11682 : {mInterfacesBitmap = interfacesBitmap;}
2195 :
2196 : private:
2197 : nsCOMPtr<nsIXPCScriptable> mCallback;
2198 : XPCNativeScriptableFlags mFlags;
2199 : PRUint32 mInterfacesBitmap;
2200 : };
2201 :
2202 : /***********************************************/
2203 : // XPCWrappedNativeProto hold the additional shared wrapper data
2204 : // for XPCWrappedNative whose native objects expose nsIClassInfo.
2205 :
2206 : #define UNKNOWN_OFFSETS ((QITableEntry*)1)
2207 :
2208 : class XPCWrappedNativeProto
2209 : {
2210 : public:
2211 : static XPCWrappedNativeProto*
2212 : GetNewOrUsed(XPCCallContext& ccx,
2213 : XPCWrappedNativeScope* scope,
2214 : nsIClassInfo* classInfo,
2215 : const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
2216 : QITableEntry* offsets = UNKNOWN_OFFSETS,
2217 : bool callPostCreatePrototype = true);
2218 :
2219 : XPCWrappedNativeScope*
2220 8831657 : GetScope() const {return mScope;}
2221 :
2222 : XPCJSRuntime*
2223 5007776 : GetRuntime() const {return mScope->GetRuntime();}
2224 :
2225 : JSObject*
2226 396291 : GetJSProtoObject() const {return mJSProtoObject;}
2227 :
2228 : nsIClassInfo*
2229 2730812 : GetClassInfo() const {return mClassInfo;}
2230 :
2231 : XPCNativeSet*
2232 3059923 : GetSet() const {return mSet;}
2233 :
2234 : XPCNativeScriptableInfo*
2235 1641566 : GetScriptableInfo() {return mScriptableInfo;}
2236 :
2237 : void**
2238 1549264 : GetSecurityInfoAddr() {return &mSecurityInfo;}
2239 :
2240 : uint32_t
2241 : GetClassInfoFlags() const {return mClassInfoFlags;}
2242 :
2243 : QITableEntry*
2244 33559 : GetOffsets()
2245 : {
2246 33559 : return InitedOffsets() ? mOffsets : nsnull;
2247 : }
2248 : QITableEntry*
2249 0 : GetOffsetsMasked()
2250 : {
2251 0 : return mOffsets;
2252 : }
2253 : void
2254 383074 : CacheOffsets(nsISupports* identity)
2255 : {
2256 : static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
2257 :
2258 : #ifdef DEBUG
2259 383074 : if (InitedOffsets() && mOffsets) {
2260 : QITableEntry* offsets;
2261 13260 : identity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
2262 13260 : NS_ASSERTION(offsets == mOffsets,
2263 : "We can't deal with objects that have the same "
2264 : "classinfo but different offset tables.");
2265 : }
2266 : #endif
2267 :
2268 383074 : if (!InitedOffsets()) {
2269 186922 : if (mClassInfoFlags & nsIClassInfo::CONTENT_NODE) {
2270 898 : identity->QueryInterface(kThisPtrOffsetsSID, (void**)&mOffsets);
2271 : } else {
2272 186024 : mOffsets = nsnull;
2273 : }
2274 : }
2275 383074 : }
2276 :
2277 : #ifdef GET_IT
2278 : #undef GET_IT
2279 : #endif
2280 : #define GET_IT(f_) const {return !!(mClassInfoFlags & nsIClassInfo:: f_ );}
2281 :
2282 : JSBool ClassIsSingleton() GET_IT(SINGLETON)
2283 9169773 : JSBool ClassIsThreadSafe() GET_IT(THREADSAFE)
2284 1094151 : JSBool ClassIsMainThreadOnly() GET_IT(MAIN_THREAD_ONLY)
2285 30679 : JSBool ClassIsDOMObject() GET_IT(DOM_OBJECT)
2286 : JSBool ClassIsPluginObject() GET_IT(PLUGIN_OBJECT)
2287 :
2288 : #undef GET_IT
2289 :
2290 5659564 : XPCLock* GetLock() const
2291 5659564 : {return ClassIsThreadSafe() ? GetRuntime()->GetMapLock() : nsnull;}
2292 :
2293 : void SetScriptableInfo(XPCNativeScriptableInfo* si)
2294 : {NS_ASSERTION(!mScriptableInfo, "leak here!"); mScriptableInfo = si;}
2295 :
2296 : bool CallPostCreatePrototype(XPCCallContext& ccx);
2297 : void JSProtoObjectFinalized(JSContext *cx, JSObject *obj);
2298 :
2299 : void SystemIsBeingShutDown();
2300 :
2301 : void DebugDump(PRInt16 depth);
2302 :
2303 1895324 : void TraceJS(JSTracer* trc)
2304 : {
2305 1895324 : if (mJSProtoObject) {
2306 1895324 : JS_CALL_OBJECT_TRACER(trc, mJSProtoObject,
2307 : "XPCWrappedNativeProto::mJSProtoObject");
2308 : }
2309 1895324 : if (mScriptableInfo && JS_IsGCMarkingTracer(trc))
2310 818539 : mScriptableInfo->Mark();
2311 1895324 : }
2312 :
2313 0 : void WriteBarrierPre(JSRuntime* rt)
2314 : {
2315 0 : if (js::IsIncrementalBarrierNeeded(rt) && mJSProtoObject)
2316 0 : mJSProtoObject.writeBarrierPre(rt);
2317 0 : }
2318 :
2319 : // NOP. This is just here to make the AutoMarkingPtr code compile.
2320 0 : inline void AutoTrace(JSTracer* trc) {}
2321 :
2322 : // Yes, we *do* need to mark the mScriptableInfo in both cases.
2323 2728036 : void Mark() const
2324 2728036 : {mSet->Mark();
2325 2728036 : if (mScriptableInfo) mScriptableInfo->Mark();}
2326 :
2327 : #ifdef DEBUG
2328 2728036 : void ASSERT_SetNotMarked() const {mSet->ASSERT_NotMarked();}
2329 : #endif
2330 :
2331 : ~XPCWrappedNativeProto();
2332 :
2333 : protected:
2334 : // disable copy ctor and assignment
2335 : XPCWrappedNativeProto(const XPCWrappedNativeProto& r); // not implemented
2336 : XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r); // not implemented
2337 :
2338 : // hide ctor
2339 : XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
2340 : nsIClassInfo* ClassInfo,
2341 : PRUint32 ClassInfoFlags,
2342 : XPCNativeSet* Set,
2343 : QITableEntry* offsets);
2344 :
2345 : JSBool Init(XPCCallContext& ccx,
2346 : const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
2347 : bool callPostCreatePrototype);
2348 :
2349 : private:
2350 : #if defined(DEBUG_xpc_hacker) || defined(DEBUG)
2351 : static PRInt32 gDEBUG_LiveProtoCount;
2352 : #endif
2353 :
2354 : private:
2355 : bool
2356 799707 : InitedOffsets()
2357 : {
2358 799707 : return mOffsets != UNKNOWN_OFFSETS;
2359 : }
2360 :
2361 : XPCWrappedNativeScope* mScope;
2362 : js::ObjectPtr mJSProtoObject;
2363 : nsCOMPtr<nsIClassInfo> mClassInfo;
2364 : PRUint32 mClassInfoFlags;
2365 : XPCNativeSet* mSet;
2366 : void* mSecurityInfo;
2367 : XPCNativeScriptableInfo* mScriptableInfo;
2368 : QITableEntry* mOffsets;
2369 : };
2370 :
2371 : class xpcObjectHelper;
2372 : extern JSBool ConstructSlimWrapper(XPCCallContext &ccx,
2373 : xpcObjectHelper &aHelper,
2374 : XPCWrappedNativeScope* xpcScope,
2375 : jsval *rval);
2376 : extern JSBool MorphSlimWrapper(JSContext *cx, JSObject *obj);
2377 :
2378 : static inline XPCWrappedNativeProto*
2379 35487 : GetSlimWrapperProto(JSObject *obj)
2380 : {
2381 35487 : const js::Value &v = js::GetReservedSlot(obj, 0);
2382 35487 : return static_cast<XPCWrappedNativeProto*>(v.toPrivate());
2383 : }
2384 :
2385 :
2386 : /***********************************************/
2387 : // XPCWrappedNativeTearOff represents the info needed to make calls to one
2388 : // interface on the underlying native object of a XPCWrappedNative.
2389 :
2390 : class XPCWrappedNativeTearOff
2391 : {
2392 : public:
2393 2252548 : JSBool IsAvailable() const {return mInterface == nsnull;}
2394 : JSBool IsReserved() const {return mInterface == (XPCNativeInterface*)1;}
2395 : JSBool IsValid() const {return !IsAvailable() && !IsReserved();}
2396 1522567 : void SetReserved() {mInterface = (XPCNativeInterface*)1;}
2397 :
2398 17740440 : XPCNativeInterface* GetInterface() const {return mInterface;}
2399 12196185 : nsISupports* GetNative() const {return mNative;}
2400 : JSObject* GetJSObject();
2401 : JSObject* GetJSObjectPreserveColor() const;
2402 5525419 : void SetInterface(XPCNativeInterface* Interface) {mInterface = Interface;}
2403 3043760 : void SetNative(nsISupports* Native) {mNative = Native;}
2404 : void SetJSObject(JSObject* JSObj);
2405 :
2406 60 : void JSObjectFinalized() {SetJSObject(nsnull);}
2407 :
2408 1442283 : XPCWrappedNativeTearOff()
2409 1442283 : : mInterface(nsnull), mNative(nsnull), mJSObject(nsnull) {}
2410 : ~XPCWrappedNativeTearOff();
2411 :
2412 : // NOP. This is just here to make the AutoMarkingPtr code compile.
2413 0 : inline void TraceJS(JSTracer* trc) {}
2414 0 : inline void AutoTrace(JSTracer* trc) {}
2415 :
2416 3877 : void Mark() {mJSObject = (JSObject*)(intptr_t(mJSObject) | 1);}
2417 4092129 : void Unmark() {mJSObject = (JSObject*)(intptr_t(mJSObject) & ~1);}
2418 2564542 : bool IsMarked() const {return !!(intptr_t(mJSObject) & 1);}
2419 :
2420 : private:
2421 : XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) MOZ_DELETE;
2422 : XPCWrappedNativeTearOff& operator= (const XPCWrappedNativeTearOff& r) MOZ_DELETE;
2423 :
2424 : private:
2425 : XPCNativeInterface* mInterface;
2426 : nsISupports* mNative;
2427 : JSObject* mJSObject;
2428 : };
2429 :
2430 : /***********************************************/
2431 : // XPCWrappedNativeTearOffChunk is a collections of XPCWrappedNativeTearOff
2432 : // objects. It lets us allocate a set of XPCWrappedNativeTearOff objects and
2433 : // link the sets - rather than only having the option of linking single
2434 : // XPCWrappedNativeTearOff objects.
2435 : //
2436 : // The value of XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK can be tuned at buildtime
2437 : // to balance between the code of allocations of additional chunks and the waste
2438 : // of space for ununsed XPCWrappedNativeTearOff objects.
2439 :
2440 : #define XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK 1
2441 :
2442 : class XPCWrappedNativeTearOffChunk
2443 : {
2444 : friend class XPCWrappedNative;
2445 : private:
2446 1442283 : XPCWrappedNativeTearOffChunk() : mNextChunk(nsnull) {}
2447 2882938 : ~XPCWrappedNativeTearOffChunk() {delete mNextChunk;}
2448 :
2449 : private:
2450 : XPCWrappedNativeTearOff mTearOffs[XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK];
2451 : XPCWrappedNativeTearOffChunk* mNextChunk;
2452 : };
2453 :
2454 : void *xpc_GetJSPrivate(JSObject *obj);
2455 :
2456 : /***************************************************************************/
2457 : // XPCWrappedNative the wrapper around one instance of a native xpcom object
2458 : // to be used from JavaScript.
2459 :
2460 : class XPCWrappedNative : public nsIXPConnectWrappedNative
2461 : {
2462 : public:
2463 : NS_DECL_ISUPPORTS
2464 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
2465 : NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
2466 : // No need to unlink the JS objects, if the XPCWrappedNative will be cycle
2467 : // collected then its mFlatJSObject will be cycle collected too and
2468 : // finalization of the mFlatJSObject will unlink the js objects (see
2469 : // XPC_WN_NoHelper_Finalize and FlatJSObjectFinalized).
2470 : // We also give XPCWrappedNative empty Root/Unroot methods, to avoid
2471 : // root/unrooting the JS objects from addrefing/releasing the
2472 : // XPCWrappedNative during unlinking, which would make the JS objects
2473 : // uncollectable to the JS GC.
2474 : class NS_CYCLE_COLLECTION_INNERCLASS
2475 : : public nsXPCOMCycleCollectionParticipant
2476 1464 : {
2477 363 : NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(XPCWrappedNative,
2478 : XPCWrappedNative)
2479 322 : NS_IMETHOD Root(void *p) { return NS_OK; }
2480 : NS_IMETHOD Unlink(void *p);
2481 322 : NS_IMETHOD Unroot(void *p) { return NS_OK; }
2482 : };
2483 : NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
2484 0 : NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(XPCWrappedNative)
2485 :
2486 : nsIPrincipal* GetObjectPrincipal() const;
2487 :
2488 : JSBool
2489 46998400 : IsValid() const {return nsnull != mFlatJSObject;}
2490 :
2491 : #define XPC_SCOPE_WORD(s) (intptr_t(s))
2492 : #define XPC_SCOPE_MASK (intptr_t(0x3))
2493 : #define XPC_SCOPE_TAG (intptr_t(0x1))
2494 : #define XPC_WRAPPER_EXPIRED (intptr_t(0x2))
2495 :
2496 : static inline JSBool
2497 105845901 : IsTaggedScope(XPCWrappedNativeScope* s)
2498 105845901 : {return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;}
2499 :
2500 : static inline XPCWrappedNativeScope*
2501 882319 : TagScope(XPCWrappedNativeScope* s)
2502 882319 : {NS_ASSERTION(!IsTaggedScope(s), "bad pointer!");
2503 882319 : return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) | XPC_SCOPE_TAG);}
2504 :
2505 : static inline XPCWrappedNativeScope*
2506 : UnTagScope(XPCWrappedNativeScope* s)
2507 : {return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) & ~XPC_SCOPE_TAG);}
2508 :
2509 : inline JSBool
2510 1270383 : IsWrapperExpired() const
2511 1270383 : {return XPC_SCOPE_WORD(mMaybeScope) & XPC_WRAPPER_EXPIRED;}
2512 :
2513 : JSBool
2514 104963582 : HasProto() const {return !IsTaggedScope(mMaybeScope);}
2515 :
2516 : XPCWrappedNativeProto*
2517 53114223 : GetProto() const
2518 53114223 : {return HasProto() ?
2519 : (XPCWrappedNativeProto*)
2520 53114223 : (XPC_SCOPE_WORD(mMaybeProto) & ~XPC_SCOPE_MASK) : nsnull;}
2521 :
2522 : void SetProto(XPCWrappedNativeProto* p);
2523 :
2524 : XPCWrappedNativeScope*
2525 14471147 : GetScope() const
2526 21097003 : {return GetProto() ? GetProto()->GetScope() :
2527 : (XPCWrappedNativeScope*)
2528 21097003 : (XPC_SCOPE_WORD(mMaybeScope) & ~XPC_SCOPE_MASK);}
2529 :
2530 : nsISupports*
2531 13401020 : GetIdentityObject() const {return mIdentity;}
2532 :
2533 : /**
2534 : * This getter clears the gray bit before handing out the JSObject which
2535 : * means that the object is guaranteed to be kept alive past the next CC.
2536 : */
2537 : JSObject*
2538 16027718 : GetFlatJSObject() const
2539 16027718 : {if (mFlatJSObject != INVALID_OBJECT)
2540 16027718 : xpc_UnmarkGrayObject(mFlatJSObject);
2541 16027718 : return mFlatJSObject;}
2542 :
2543 : /**
2544 : * This getter does not change the color of the JSObject meaning that the
2545 : * object returned is not guaranteed to be kept alive past the next CC.
2546 : *
2547 : * This should only be called if you are certain that the return value won't
2548 : * be passed into a JS API function and that it won't be stored without
2549 : * being rooted (or otherwise signaling the stored value to the CC).
2550 : */
2551 : JSObject*
2552 14891 : GetFlatJSObjectPreserveColor() const {return mFlatJSObject;}
2553 :
2554 : XPCLock*
2555 44089256 : GetLock() const {return IsValid() && HasProto() ?
2556 44089256 : GetProto()->GetLock() : nsnull;}
2557 :
2558 : XPCNativeSet*
2559 11724518 : GetSet() const {XPCAutoLock al(GetLock()); return mSet;}
2560 :
2561 : void
2562 158 : SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;}
2563 :
2564 : private:
2565 : inline void
2566 322 : ExpireWrapper()
2567 : {mMaybeScope = (XPCWrappedNativeScope*)
2568 322 : (XPC_SCOPE_WORD(mMaybeScope) | XPC_WRAPPER_EXPIRED);}
2569 :
2570 : public:
2571 :
2572 : XPCNativeScriptableInfo*
2573 14637652 : GetScriptableInfo() const {return mScriptableInfo;}
2574 :
2575 : nsIXPCScriptable* // call this wrong and you deserve to crash
2576 506128 : GetScriptableCallback() const {return mScriptableInfo->GetCallback();}
2577 :
2578 : void**
2579 7685879 : GetSecurityInfoAddr() {return HasProto() ?
2580 7685879 : GetProto()->GetSecurityInfoAddr() : nsnull;}
2581 :
2582 : nsIClassInfo*
2583 15373878 : GetClassInfo() const {return IsValid() && HasProto() ?
2584 15373878 : GetProto()->GetClassInfo() : nsnull;}
2585 :
2586 : JSBool
2587 1309608 : HasMutatedSet() const {return IsValid() &&
2588 1309608 : (!HasProto() ||
2589 2619216 : GetSet() != GetProto()->GetSet());}
2590 :
2591 : XPCJSRuntime*
2592 5040256 : GetRuntime() const {XPCWrappedNativeScope* scope = GetScope();
2593 5040256 : return scope ? scope->GetRuntime() : nsnull;}
2594 :
2595 : static nsresult
2596 : WrapNewGlobal(XPCCallContext &ccx, xpcObjectHelper &nativeHelper,
2597 : nsIPrincipal *principal, bool initStandardClasses,
2598 : XPCWrappedNative **wrappedGlobal);
2599 :
2600 : static nsresult
2601 : GetNewOrUsed(XPCCallContext& ccx,
2602 : xpcObjectHelper& helper,
2603 : XPCWrappedNativeScope* Scope,
2604 : XPCNativeInterface* Interface,
2605 : XPCWrappedNative** wrapper);
2606 :
2607 : static nsresult
2608 : Morph(XPCCallContext& ccx,
2609 : JSObject* existingJSObject,
2610 : XPCNativeInterface* Interface,
2611 : nsWrapperCache *cache,
2612 : XPCWrappedNative** resultWrapper);
2613 :
2614 : public:
2615 : static nsresult
2616 : GetUsedOnly(XPCCallContext& ccx,
2617 : nsISupports* Object,
2618 : XPCWrappedNativeScope* Scope,
2619 : XPCNativeInterface* Interface,
2620 : XPCWrappedNative** wrapper);
2621 :
2622 : // If pobj2 is not null and *pobj2 is not null after the call then *pobj2
2623 : // points to an object for which IS_SLIM_WRAPPER_OBJECT is true.
2624 : // cx is null when invoked from the marking phase of the GC. In this case
2625 : // fubobj must be null as well.
2626 : static XPCWrappedNative*
2627 : GetWrappedNativeOfJSObject(JSContext* cx, JSObject* obj,
2628 : JSObject* funobj = nsnull,
2629 : JSObject** pobj2 = nsnull,
2630 : XPCWrappedNativeTearOff** pTearOff = nsnull);
2631 : static XPCWrappedNative*
2632 237254 : GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj)
2633 : {
2634 237254 : JSObject *obj2 = nsnull;
2635 : XPCWrappedNative* wrapper =
2636 237254 : GetWrappedNativeOfJSObject(cx, obj, nsnull, &obj2);
2637 237254 : if (wrapper || !obj2)
2638 237254 : return wrapper;
2639 :
2640 0 : NS_ASSERTION(IS_SLIM_WRAPPER(obj2),
2641 : "Hmm, someone changed GetWrappedNativeOfJSObject?");
2642 : SLIM_LOG_WILL_MORPH(cx, obj2);
2643 0 : return MorphSlimWrapper(cx, obj2) ?
2644 0 : (XPCWrappedNative*)xpc_GetJSPrivate(obj2) :
2645 0 : nsnull;
2646 : }
2647 :
2648 : static nsresult
2649 : ReparentWrapperIfFound(XPCCallContext& ccx,
2650 : XPCWrappedNativeScope* aOldScope,
2651 : XPCWrappedNativeScope* aNewScope,
2652 : JSObject* aNewParent,
2653 : nsISupports* aCOMObj,
2654 : XPCWrappedNative** aWrapper);
2655 :
2656 : void FlatJSObjectFinalized();
2657 :
2658 : void SystemIsBeingShutDown();
2659 :
2660 : enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
2661 :
2662 : static JSBool CallMethod(XPCCallContext& ccx,
2663 : CallMode mode = CALL_METHOD);
2664 :
2665 2255104 : static JSBool GetAttribute(XPCCallContext& ccx)
2666 2255104 : {return CallMethod(ccx, CALL_GETTER);}
2667 :
2668 102335 : static JSBool SetAttribute(XPCCallContext& ccx)
2669 102335 : {return CallMethod(ccx, CALL_SETTER);}
2670 :
2671 : inline JSBool HasInterfaceNoQI(const nsIID& iid);
2672 :
2673 : XPCWrappedNativeTearOff* LocateTearOff(XPCCallContext& ccx,
2674 : XPCNativeInterface* aInterface);
2675 : XPCWrappedNativeTearOff* FindTearOff(XPCCallContext& ccx,
2676 : XPCNativeInterface* aInterface,
2677 : JSBool needJSObject = false,
2678 : nsresult* pError = nsnull);
2679 2233014 : void Mark() const
2680 : {
2681 2233014 : mSet->Mark();
2682 2233014 : if (mScriptableInfo) mScriptableInfo->Mark();
2683 2233014 : if (HasProto()) GetProto()->Mark();
2684 2233014 : }
2685 :
2686 : // Yes, we *do* need to mark the mScriptableInfo in both cases.
2687 2285144 : inline void TraceJS(JSTracer* trc)
2688 : {
2689 2285144 : if (mScriptableInfo && JS_IsGCMarkingTracer(trc))
2690 1891490 : mScriptableInfo->Mark();
2691 2285144 : if (HasProto()) GetProto()->TraceJS(trc);
2692 2285144 : JSObject* wrapper = GetWrapperPreserveColor();
2693 2285144 : if (wrapper)
2694 0 : JS_CALL_OBJECT_TRACER(trc, wrapper, "XPCWrappedNative::mWrapper");
2695 4221978 : if (mScriptableInfo &&
2696 1936834 : (mScriptableInfo->GetJSClass()->flags & JSCLASS_XPCONNECT_GLOBAL))
2697 134224 : TraceXPCGlobal(trc, mFlatJSObject);
2698 :
2699 2285144 : }
2700 :
2701 0 : inline void AutoTrace(JSTracer* trc)
2702 : {
2703 : // If this got called, we're being kept alive by someone who really
2704 : // needs us alive and whole. Do not let our mFlatJSObject go away.
2705 : // This is the only time we should be tracing our mFlatJSObject,
2706 : // normally somebody else is doing that. Be careful not to trace the
2707 : // bogus INVALID_OBJECT value we can have during init, though.
2708 0 : if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT) {
2709 0 : JS_CALL_OBJECT_TRACER(trc, mFlatJSObject,
2710 : "XPCWrappedNative::mFlatJSObject");
2711 : }
2712 0 : }
2713 :
2714 : #ifdef DEBUG
2715 2233014 : void ASSERT_SetsNotMarked() const
2716 2233014 : {mSet->ASSERT_NotMarked();
2717 2233014 : if (HasProto()){GetProto()->ASSERT_SetNotMarked();}}
2718 :
2719 : int DEBUG_CountOfTearoffChunks() const
2720 : {int i = 0; const XPCWrappedNativeTearOffChunk* to;
2721 : for (to = &mFirstChunk; to; to = to->mNextChunk) {i++;} return i;}
2722 : #endif
2723 :
2724 : inline void SweepTearOffs();
2725 :
2726 : // Returns a string that shuld be free'd using JS_smprintf_free (or null).
2727 : char* ToString(XPCCallContext& ccx,
2728 : XPCWrappedNativeTearOff* to = nsnull) const;
2729 :
2730 : static void GatherProtoScriptableCreateInfo(nsIClassInfo* classInfo,
2731 : XPCNativeScriptableCreateInfo& sciProto);
2732 :
2733 3852297 : JSBool HasExternalReference() const {return mRefCnt > 1;}
2734 :
2735 1464581 : JSBool NeedsSOW() { return !!(mWrapperWord & NEEDS_SOW); }
2736 0 : void SetNeedsSOW() { mWrapperWord |= NEEDS_SOW; }
2737 : JSBool NeedsCOW() { return !!(mWrapperWord & NEEDS_COW); }
2738 0 : void SetNeedsCOW() { mWrapperWord |= NEEDS_COW; }
2739 363 : JSBool MightHaveExpandoObject() { return !!(mWrapperWord & MIGHT_HAVE_EXPANDO); }
2740 0 : void SetHasExpandoObject() { mWrapperWord |= MIGHT_HAVE_EXPANDO; }
2741 :
2742 2285144 : JSObject* GetWrapperPreserveColor() const
2743 2285144 : {return (JSObject*)(mWrapperWord & (size_t)~(size_t)FLAG_MASK);}
2744 :
2745 0 : JSObject* GetWrapper()
2746 : {
2747 0 : JSObject* wrapper = GetWrapperPreserveColor();
2748 0 : if (wrapper) {
2749 0 : xpc_UnmarkGrayObject(wrapper);
2750 : // Call this to unmark mFlatJSObject.
2751 0 : GetFlatJSObject();
2752 : }
2753 0 : return wrapper;
2754 : }
2755 0 : void SetWrapper(JSObject *obj)
2756 : {
2757 0 : js::IncrementalReferenceBarrier(GetWrapperPreserveColor());
2758 0 : PRWord newval = PRWord(obj) | (mWrapperWord & FLAG_MASK);
2759 0 : mWrapperWord = newval;
2760 0 : }
2761 :
2762 : void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
2763 :
2764 30679 : QITableEntry* GetOffsets()
2765 : {
2766 30679 : if (!HasProto() || !GetProto()->ClassIsDOMObject())
2767 0 : return nsnull;
2768 :
2769 30679 : XPCWrappedNativeProto* proto = GetProto();
2770 30679 : QITableEntry* offsets = proto->GetOffsets();
2771 30679 : if (!offsets) {
2772 : static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
2773 28756 : mIdentity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
2774 : }
2775 30679 : return offsets;
2776 : }
2777 :
2778 : // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
2779 : protected:
2780 : XPCWrappedNative(); // not implemented
2781 :
2782 : // This ctor is used if this object will have a proto.
2783 : XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
2784 : XPCWrappedNativeProto* aProto);
2785 :
2786 : // This ctor is used if this object will NOT have a proto.
2787 : XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
2788 : XPCWrappedNativeScope* aScope,
2789 : XPCNativeSet* aSet);
2790 :
2791 : virtual ~XPCWrappedNative();
2792 : void Destroy();
2793 :
2794 : void UpdateScriptableInfo(XPCNativeScriptableInfo *si);
2795 :
2796 : private:
2797 : enum {
2798 : NEEDS_SOW = JS_BIT(0),
2799 : NEEDS_COW = JS_BIT(1),
2800 : MIGHT_HAVE_EXPANDO = JS_BIT(2),
2801 : FLAG_MASK = JS_BITMASK(3)
2802 : };
2803 :
2804 : private:
2805 :
2806 : JSBool Init(XPCCallContext& ccx, JSObject* parent, const XPCNativeScriptableCreateInfo* sci);
2807 : JSBool Init(XPCCallContext &ccx, JSObject *existingJSObject);
2808 : JSBool FinishInit(XPCCallContext &ccx);
2809 :
2810 : JSBool ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface);
2811 :
2812 : nsresult InitTearOff(XPCCallContext& ccx,
2813 : XPCWrappedNativeTearOff* aTearOff,
2814 : XPCNativeInterface* aInterface,
2815 : JSBool needJSObject);
2816 :
2817 : JSBool InitTearOffJSObject(XPCCallContext& ccx,
2818 : XPCWrappedNativeTearOff* to);
2819 :
2820 : public:
2821 : static const XPCNativeScriptableCreateInfo& GatherScriptableCreateInfo(nsISupports* obj,
2822 : nsIClassInfo* classInfo,
2823 : XPCNativeScriptableCreateInfo& sciProto,
2824 : XPCNativeScriptableCreateInfo& sciWrapper);
2825 :
2826 : private:
2827 : union
2828 : {
2829 : XPCWrappedNativeScope* mMaybeScope;
2830 : XPCWrappedNativeProto* mMaybeProto;
2831 : };
2832 : XPCNativeSet* mSet;
2833 : JSObject* mFlatJSObject;
2834 : XPCNativeScriptableInfo* mScriptableInfo;
2835 : XPCWrappedNativeTearOffChunk mFirstChunk;
2836 : PRWord mWrapperWord;
2837 :
2838 : #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
2839 : public:
2840 : // Don't want to overload _mOwningThread
2841 : PRThread* mThread;
2842 : #endif
2843 : };
2844 :
2845 : /***************************************************************************
2846 : ****************************************************************************
2847 : *
2848 : * Core classes for wrapped JSObject for use from native code...
2849 : *
2850 : ****************************************************************************
2851 : ***************************************************************************/
2852 :
2853 : // this interfaces exists so we can refcount nsXPCWrappedJSClass
2854 : // {2453EBA0-A9B8-11d2-BA64-00805F8A5DD7}
2855 : #define NS_IXPCONNECT_WRAPPED_JS_CLASS_IID \
2856 : { 0x2453eba0, 0xa9b8, 0x11d2, \
2857 : { 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
2858 :
2859 : class nsIXPCWrappedJSClass : public nsISupports
2860 32512 : {
2861 : public:
2862 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
2863 : NS_IMETHOD DebugDump(PRInt16 depth) = 0;
2864 : };
2865 :
2866 : NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPCWrappedJSClass,
2867 : NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
2868 :
2869 : /*************************/
2870 : // nsXPCWrappedJSClass represents the sharable factored out common code and
2871 : // data for nsXPCWrappedJS instances for the same interface type.
2872 :
2873 : class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass
2874 : {
2875 : // all the interface method declarations...
2876 : NS_DECL_ISUPPORTS
2877 : NS_IMETHOD DebugDump(PRInt16 depth);
2878 : public:
2879 :
2880 : static nsresult
2881 : GetNewOrUsed(XPCCallContext& ccx,
2882 : REFNSIID aIID,
2883 : nsXPCWrappedJSClass** clazz);
2884 :
2885 649462 : REFNSIID GetIID() const {return mIID;}
2886 114050 : XPCJSRuntime* GetRuntime() const {return mRuntime;}
2887 554674 : nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
2888 : const char* GetInterfaceName();
2889 :
2890 : static JSBool IsWrappedJS(nsISupports* aPtr);
2891 :
2892 : NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
2893 : void** aInstancePtr);
2894 :
2895 : JSObject* GetRootJSObject(XPCCallContext& ccx, JSObject* aJSObj);
2896 :
2897 : NS_IMETHOD CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
2898 : const XPTMethodDescriptor* info,
2899 : nsXPTCMiniVariant* params);
2900 :
2901 : JSObject* CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
2902 : JSObject* jsobj, REFNSIID aIID);
2903 :
2904 : static nsresult BuildPropertyEnumerator(XPCCallContext& ccx,
2905 : JSObject* aJSObj,
2906 : nsISimpleEnumerator** aEnumerate);
2907 :
2908 : static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
2909 : JSObject* aJSObj,
2910 : const nsAString& aName,
2911 : nsIVariant** aResult);
2912 :
2913 : virtual ~nsXPCWrappedJSClass();
2914 :
2915 : static nsresult CheckForException(XPCCallContext & ccx,
2916 : const char * aPropertyName,
2917 : const char * anInterfaceName,
2918 : bool aForceReport);
2919 : private:
2920 : nsXPCWrappedJSClass(); // not implemented
2921 : nsXPCWrappedJSClass(XPCCallContext& ccx, REFNSIID aIID,
2922 : nsIInterfaceInfo* aInfo);
2923 :
2924 : JSObject* NewOutObject(JSContext* cx, JSObject* scope);
2925 :
2926 1225569 : JSBool IsReflectable(uint16_t i) const
2927 1225569 : {return (JSBool)(mDescriptors[i/32] & (1 << (i%32)));}
2928 183090 : void SetReflectable(uint16_t i, JSBool b)
2929 183090 : {if (b) mDescriptors[i/32] |= (1 << (i%32));
2930 65874 : else mDescriptors[i/32] &= ~(1 << (i%32));}
2931 :
2932 : JSBool GetArraySizeFromParam(JSContext* cx,
2933 : const XPTMethodDescriptor* method,
2934 : const nsXPTParamInfo& param,
2935 : uint16_t methodIndex,
2936 : uint8_t paramIndex,
2937 : nsXPTCMiniVariant* params,
2938 : uint32_t* result);
2939 :
2940 : JSBool GetInterfaceTypeFromParam(JSContext* cx,
2941 : const XPTMethodDescriptor* method,
2942 : const nsXPTParamInfo& param,
2943 : uint16_t methodIndex,
2944 : const nsXPTType& type,
2945 : nsXPTCMiniVariant* params,
2946 : nsID* result);
2947 :
2948 : void CleanupPointerArray(const nsXPTType& datum_type,
2949 : uint32_t array_count,
2950 : void** arrayp);
2951 :
2952 : void CleanupPointerTypeObject(const nsXPTType& type,
2953 : void** pp);
2954 :
2955 : private:
2956 : XPCJSRuntime* mRuntime;
2957 : nsIInterfaceInfo* mInfo;
2958 : char* mName;
2959 : nsIID mIID;
2960 : uint32_t* mDescriptors;
2961 : };
2962 :
2963 : /*************************/
2964 : // nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
2965 : // nsXPCWrappedJS objects are chained together to represent the various
2966 : // interface on the single underlying (possibly aggregate) JSObject.
2967 :
2968 : class nsXPCWrappedJS : protected nsAutoXPTCStub,
2969 : public nsIXPConnectWrappedJS,
2970 : public nsSupportsWeakReference,
2971 : public nsIPropertyBag,
2972 : public XPCRootSetElem
2973 : {
2974 : public:
2975 : NS_DECL_ISUPPORTS
2976 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
2977 : NS_DECL_NSIXPCONNECTWRAPPEDJS
2978 : NS_DECL_NSISUPPORTSWEAKREFERENCE
2979 : NS_DECL_NSIPROPERTYBAG
2980 :
2981 32625 : NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
2982 0 : NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(nsXPCWrappedJS)
2983 :
2984 : NS_IMETHOD CallMethod(PRUint16 methodIndex,
2985 : const XPTMethodDescriptor *info,
2986 : nsXPTCMiniVariant* params);
2987 :
2988 : /*
2989 : * This is rarely called directly. Instead one usually calls
2990 : * XPCConvert::JSObject2NativeInterface which will handles cases where the
2991 : * JS object is already a wrapped native or a DOM object.
2992 : */
2993 :
2994 : static nsresult
2995 : GetNewOrUsed(XPCCallContext& ccx,
2996 : JSObject* aJSObj,
2997 : REFNSIID aIID,
2998 : nsISupports* aOuter,
2999 : nsXPCWrappedJS** wrapper);
3000 :
3001 485518 : nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
3002 :
3003 : /**
3004 : * This getter clears the gray bit before handing out the JSObject which
3005 : * means that the object is guaranteed to be kept alive past the next CC.
3006 : */
3007 3279232 : JSObject* GetJSObject() const {xpc_UnmarkGrayObject(mJSObj);
3008 3279232 : return mJSObj;}
3009 :
3010 : /**
3011 : * This getter does not change the color of the JSObject meaning that the
3012 : * object returned is not guaranteed to be kept alive past the next CC.
3013 : *
3014 : * This should only be called if you are certain that the return value won't
3015 : * be passed into a JS API function and that it won't be stored without
3016 : * being rooted (or otherwise signaling the stored value to the CC).
3017 : */
3018 498800 : JSObject* GetJSObjectPreserveColor() const {return mJSObj;}
3019 :
3020 1986403 : nsXPCWrappedJSClass* GetClass() const {return mClass;}
3021 477652 : REFNSIID GetIID() const {return GetClass()->GetIID();}
3022 13784 : nsXPCWrappedJS* GetRootWrapper() const {return mRoot;}
3023 217151 : nsXPCWrappedJS* GetNextWrapper() const {return mNext;}
3024 :
3025 : nsXPCWrappedJS* Find(REFNSIID aIID);
3026 : nsXPCWrappedJS* FindInherited(REFNSIID aIID);
3027 :
3028 3001382 : JSBool IsValid() const {return mJSObj != nsnull;}
3029 : void SystemIsBeingShutDown(JSRuntime* rt);
3030 :
3031 : // This is used by XPCJSRuntime::GCCallback to find wrappers that no
3032 : // longer root their JSObject and are only still alive because they
3033 : // were being used via nsSupportsWeakReference at the time when their
3034 : // last (outside) reference was released. Wrappers that fit into that
3035 : // category are only deleted when we see that their corresponding JSObject
3036 : // is to be finalized.
3037 218343 : JSBool IsSubjectToFinalization() const {return IsValid() && mRefCnt == 1;}
3038 :
3039 1062 : JSBool IsAggregatedToNative() const {return mRoot->mOuter != nsnull;}
3040 949112 : nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
3041 :
3042 88714 : void SetIsMainThreadOnly() {
3043 88714 : MOZ_ASSERT(mMainThread);
3044 88714 : mMainThreadOnly = true;
3045 88714 : }
3046 88800 : bool IsMainThreadOnly() const {return mMainThreadOnly;}
3047 :
3048 : void TraceJS(JSTracer* trc);
3049 : #ifdef DEBUG
3050 : static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
3051 : #endif
3052 :
3053 : virtual ~nsXPCWrappedJS();
3054 : protected:
3055 : nsXPCWrappedJS(); // not implemented
3056 : nsXPCWrappedJS(XPCCallContext& ccx,
3057 : JSObject* aJSObj,
3058 : nsXPCWrappedJSClass* aClass,
3059 : nsXPCWrappedJS* root,
3060 : nsISupports* aOuter);
3061 :
3062 : void Unlink();
3063 :
3064 : private:
3065 : JSObject* mJSObj;
3066 : nsXPCWrappedJSClass* mClass;
3067 : nsXPCWrappedJS* mRoot;
3068 : nsXPCWrappedJS* mNext;
3069 : nsISupports* mOuter; // only set in root
3070 : bool mMainThread;
3071 : bool mMainThreadOnly;
3072 : };
3073 :
3074 : /***************************************************************************/
3075 :
3076 : class XPCJSObjectHolder : public nsIXPConnectJSObjectHolder,
3077 : public XPCRootSetElem
3078 : {
3079 : public:
3080 : // all the interface method declarations...
3081 : NS_DECL_ISUPPORTS
3082 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
3083 :
3084 : // non-interface implementation
3085 :
3086 : public:
3087 : static XPCJSObjectHolder* newHolder(XPCCallContext& ccx, JSObject* obj);
3088 :
3089 : virtual ~XPCJSObjectHolder();
3090 :
3091 : void TraceJS(JSTracer *trc);
3092 : #ifdef DEBUG
3093 : static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
3094 : #endif
3095 :
3096 : private:
3097 : XPCJSObjectHolder(XPCCallContext& ccx, JSObject* obj);
3098 : XPCJSObjectHolder(); // not implemented
3099 :
3100 : JSObject* mJSObj;
3101 : };
3102 :
3103 : /***************************************************************************
3104 : ****************************************************************************
3105 : *
3106 : * All manner of utility classes follow...
3107 : *
3108 : ****************************************************************************
3109 : ***************************************************************************/
3110 :
3111 : class xpcProperty : public nsIProperty
3112 : {
3113 : public:
3114 : NS_DECL_ISUPPORTS
3115 : NS_DECL_NSIPROPERTY
3116 :
3117 : xpcProperty(const PRUnichar* aName, PRUint32 aNameLen, nsIVariant* aValue);
3118 0 : virtual ~xpcProperty() {}
3119 :
3120 : private:
3121 : nsString mName;
3122 : nsCOMPtr<nsIVariant> mValue;
3123 : };
3124 :
3125 : /***************************************************************************/
3126 : // data conversion
3127 :
3128 : class xpcObjectHelper
3129 2055846 : {
3130 : public:
3131 2020856 : xpcObjectHelper(nsISupports *aObject, nsWrapperCache *aCache = nsnull)
3132 : : mCanonical(nsnull),
3133 : mObject(aObject),
3134 : mCache(aCache),
3135 2020856 : mIsNode(false)
3136 : {
3137 2020856 : if (!mCache) {
3138 2020854 : if (aObject)
3139 2020854 : CallQueryInterface(aObject, &mCache);
3140 : else
3141 0 : mCache = nsnull;
3142 : }
3143 2020856 : }
3144 :
3145 3252494 : nsISupports* Object()
3146 : {
3147 3252494 : return mObject;
3148 : }
3149 :
3150 2081389 : nsISupports* GetCanonical()
3151 : {
3152 2081389 : if (!mCanonical) {
3153 2022978 : mCanonicalStrong = do_QueryInterface(mObject);
3154 2022978 : mCanonical = mCanonicalStrong;
3155 : }
3156 2081389 : return mCanonical;
3157 : }
3158 :
3159 1265393 : already_AddRefed<nsISupports> forgetCanonical()
3160 : {
3161 1265393 : NS_ASSERTION(mCanonical, "Huh, no canonical to forget?");
3162 :
3163 1265393 : if (!mCanonicalStrong)
3164 12204 : mCanonicalStrong = mCanonical;
3165 1265393 : mCanonical = nsnull;
3166 1265393 : return mCanonicalStrong.forget();
3167 : }
3168 :
3169 1263456 : nsIClassInfo *GetClassInfo()
3170 : {
3171 1263456 : if (mXPCClassInfo)
3172 4607 : return mXPCClassInfo;
3173 1258849 : if (!mClassInfo)
3174 1245632 : mClassInfo = do_QueryInterface(mObject);
3175 1258849 : return mClassInfo;
3176 : }
3177 61350 : nsXPCClassInfo *GetXPCClassInfo()
3178 : {
3179 61350 : if (!mXPCClassInfo) {
3180 46195 : if (mIsNode)
3181 14959 : mXPCClassInfo = static_cast<nsINode*>(GetCanonical())->GetClassInfo();
3182 : else
3183 31236 : CallQueryInterface(mObject, getter_AddRefs(mXPCClassInfo));
3184 : }
3185 61350 : return mXPCClassInfo;
3186 : }
3187 :
3188 15155 : already_AddRefed<nsXPCClassInfo> forgetXPCClassInfo()
3189 : {
3190 15155 : GetXPCClassInfo();
3191 :
3192 15155 : return mXPCClassInfo.forget();
3193 : }
3194 :
3195 : // We assert that we can reach an nsIXPCScriptable somehow.
3196 26434 : PRUint32 GetScriptableFlags()
3197 : {
3198 : // Try getting an nsXPCClassInfo - this handles DOM scriptable helpers.
3199 52868 : nsCOMPtr<nsIXPCScriptable> sinfo = GetXPCClassInfo();
3200 :
3201 : // If that didn't work, try just QI-ing. This handles BackstagePass.
3202 26434 : if (!sinfo)
3203 26434 : sinfo = do_QueryInterface(GetCanonical());
3204 :
3205 : // We should have something by now.
3206 26434 : MOZ_ASSERT(sinfo);
3207 :
3208 : // Grab the flags. This should not fail.
3209 : PRUint32 flags;
3210 52868 : mozilla::DebugOnly<nsresult> rv = sinfo->GetScriptableFlags(&flags);
3211 26434 : MOZ_ASSERT(NS_SUCCEEDED(rv));
3212 :
3213 26434 : return flags;
3214 : }
3215 :
3216 4075761 : nsWrapperCache *GetWrapperCache()
3217 : {
3218 4075761 : return mCache;
3219 : }
3220 :
3221 : protected:
3222 34990 : xpcObjectHelper(nsISupports *aObject, nsISupports *aCanonical,
3223 : nsWrapperCache *aCache, bool aIsNode)
3224 : : mCanonical(aCanonical),
3225 : mObject(aObject),
3226 : mCache(aCache),
3227 34990 : mIsNode(aIsNode)
3228 : {
3229 34990 : if (!mCache && aObject)
3230 16696 : CallQueryInterface(aObject, &mCache);
3231 34990 : }
3232 :
3233 : nsCOMPtr<nsISupports> mCanonicalStrong;
3234 : nsISupports* mCanonical;
3235 :
3236 : private:
3237 : xpcObjectHelper(xpcObjectHelper& aOther);
3238 :
3239 : nsISupports* mObject;
3240 : nsWrapperCache* mCache;
3241 : nsCOMPtr<nsIClassInfo> mClassInfo;
3242 : nsRefPtr<nsXPCClassInfo> mXPCClassInfo;
3243 : bool mIsNode;
3244 : };
3245 :
3246 : // class here just for static methods
3247 : class XPCConvert
3248 : {
3249 : public:
3250 : static JSBool IsMethodReflectable(const XPTMethodDescriptor& info);
3251 :
3252 : /**
3253 : * Convert a native object into a jsval.
3254 : *
3255 : * @param ccx the context for the whole procedure
3256 : * @param d [out] the resulting jsval
3257 : * @param s the native object we're working with
3258 : * @param type the type of object that s is
3259 : * @param iid the interface of s that we want
3260 : * @param scope the default scope to put on the new JSObject's parent
3261 : * chain
3262 : * @param pErr [out] relevant error code, if any.
3263 : */
3264 20351834 : static JSBool NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s,
3265 : const nsXPTType& type, const nsID* iid,
3266 : nsresult* pErr)
3267 : {
3268 40703668 : XPCLazyCallContext lccx(ccx);
3269 20351834 : return NativeData2JS(lccx, d, s, type, iid, pErr);
3270 : }
3271 : static JSBool NativeData2JS(XPCLazyCallContext& lccx, jsval* d,
3272 : const void* s, const nsXPTType& type,
3273 : const nsID* iid, nsresult* pErr);
3274 :
3275 : static JSBool JSData2Native(XPCCallContext& ccx, void* d, jsval s,
3276 : const nsXPTType& type,
3277 : JSBool useAllocator, const nsID* iid,
3278 : nsresult* pErr);
3279 :
3280 : /**
3281 : * Convert a native nsISupports into a JSObject.
3282 : *
3283 : * @param ccx the context for the whole procedure
3284 : * @param dest [out] the resulting JSObject
3285 : * @param src the native object we're working with
3286 : * @param iid the interface of src that we want (may be null)
3287 : * @param Interface the interface of src that we want
3288 : * @param cache the wrapper cache for src (may be null, in which case src
3289 : * will be QI'ed to get the cache)
3290 : * @param allowNativeWrapper if true, this method may wrap the resulting
3291 : * JSObject in an XPCNativeWrapper and return that, as needed.
3292 : * @param pErr [out] relevant error code, if any.
3293 : * @param src_is_identity optional performance hint. Set to true only
3294 : * if src is the identity pointer.
3295 : */
3296 3965 : static JSBool NativeInterface2JSObject(XPCCallContext& ccx,
3297 : jsval* d,
3298 : nsIXPConnectJSObjectHolder** dest,
3299 : xpcObjectHelper& aHelper,
3300 : const nsID* iid,
3301 : XPCNativeInterface** Interface,
3302 : bool allowNativeWrapper,
3303 : nsresult* pErr)
3304 : {
3305 7930 : XPCLazyCallContext lccx(ccx);
3306 : return NativeInterface2JSObject(lccx, d, dest, aHelper, iid, Interface,
3307 3965 : allowNativeWrapper, pErr);
3308 : }
3309 : static JSBool NativeInterface2JSObject(XPCLazyCallContext& lccx,
3310 : jsval* d,
3311 : nsIXPConnectJSObjectHolder** dest,
3312 : xpcObjectHelper& aHelper,
3313 : const nsID* iid,
3314 : XPCNativeInterface** Interface,
3315 : bool allowNativeWrapper,
3316 : nsresult* pErr);
3317 :
3318 : static JSBool GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
3319 : void** dest, JSObject* src,
3320 : const nsID* iid,
3321 : nsresult* pErr);
3322 : static JSBool JSObject2NativeInterface(XPCCallContext& ccx,
3323 : void** dest, JSObject* src,
3324 : const nsID* iid,
3325 : nsISupports* aOuter,
3326 : nsresult* pErr);
3327 : static JSBool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
3328 :
3329 : /**
3330 : * Convert a native array into a jsval.
3331 : *
3332 : * @param ccx the context for the whole procedure
3333 : * @param d [out] the resulting jsval
3334 : * @param s the native array we're working with
3335 : * @param type the type of objects in the array
3336 : * @param iid the interface of each object in the array that we want
3337 : * @param count the number of items in the array
3338 : * @param scope the default scope to put on the new JSObjects' parent chain
3339 : * @param pErr [out] relevant error code, if any.
3340 : */
3341 : static JSBool NativeArray2JS(XPCLazyCallContext& ccx,
3342 : jsval* d, const void** s,
3343 : const nsXPTType& type, const nsID* iid,
3344 : uint32_t count, nsresult* pErr);
3345 :
3346 : static JSBool JSArray2Native(XPCCallContext& ccx, void** d, jsval s,
3347 : uint32_t count, const nsXPTType& type,
3348 : const nsID* iid, nsresult* pErr);
3349 :
3350 : static JSBool JSTypedArray2Native(XPCCallContext& ccx,
3351 : void** d,
3352 : JSObject* jsarray,
3353 : uint32_t count,
3354 : const nsXPTType& type,
3355 : nsresult* pErr);
3356 :
3357 : static JSBool NativeStringWithSize2JS(JSContext* cx,
3358 : jsval* d, const void* s,
3359 : const nsXPTType& type,
3360 : uint32_t count,
3361 : nsresult* pErr);
3362 :
3363 : static JSBool JSStringWithSize2Native(XPCCallContext& ccx, void* d, jsval s,
3364 : uint32_t count, const nsXPTType& type,
3365 : unsigned* pErr);
3366 :
3367 : static nsresult JSValToXPCException(XPCCallContext& ccx,
3368 : jsval s,
3369 : const char* ifaceName,
3370 : const char* methodName,
3371 : nsIException** exception);
3372 :
3373 : static nsresult JSErrorToXPCException(XPCCallContext& ccx,
3374 : const char* message,
3375 : const char* ifaceName,
3376 : const char* methodName,
3377 : const JSErrorReport* report,
3378 : nsIException** exception);
3379 :
3380 : static nsresult ConstructException(nsresult rv, const char* message,
3381 : const char* ifaceName,
3382 : const char* methodName,
3383 : nsISupports* data,
3384 : nsIException** exception,
3385 : JSContext* cx,
3386 : jsval *jsExceptionPtr);
3387 :
3388 : private:
3389 : XPCConvert(); // not implemented
3390 :
3391 : };
3392 :
3393 : /***************************************************************************/
3394 :
3395 : // readable string conversions, static methods only
3396 : class XPCStringConvert
3397 : {
3398 : public:
3399 :
3400 : // If the string shares the readable's buffer, that buffer will
3401 : // get assigned to *sharedBuffer. Otherwise null will be
3402 : // assigned.
3403 : static jsval ReadableToJSVal(JSContext *cx, const nsAString &readable,
3404 : nsStringBuffer** sharedBuffer);
3405 :
3406 : private:
3407 : XPCStringConvert(); // not implemented
3408 : };
3409 :
3410 : /***************************************************************************/
3411 : // code for throwing exceptions into JS
3412 :
3413 : class XPCThrower
3414 : {
3415 : public:
3416 : static void Throw(nsresult rv, JSContext* cx);
3417 : static void Throw(nsresult rv, XPCCallContext& ccx);
3418 : static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
3419 : static void ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx);
3420 : static JSBool SetVerbosity(JSBool state)
3421 : {JSBool old = sVerbose; sVerbose = state; return old;}
3422 :
3423 : static void BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz);
3424 : static JSBool CheckForPendingException(nsresult result, JSContext *cx);
3425 :
3426 : private:
3427 : static void Verbosify(XPCCallContext& ccx,
3428 : char** psz, bool own);
3429 :
3430 : static JSBool ThrowExceptionObject(JSContext* cx, nsIException* e);
3431 :
3432 : private:
3433 : static JSBool sVerbose;
3434 : };
3435 :
3436 :
3437 : /***************************************************************************/
3438 :
3439 : class XPCJSStack
3440 : {
3441 : public:
3442 : static nsresult
3443 : CreateStack(JSContext* cx, nsIStackFrame** stack);
3444 :
3445 : static nsresult
3446 : CreateStackFrameLocation(PRUint32 aLanguage,
3447 : const char* aFilename,
3448 : const char* aFunctionName,
3449 : PRInt32 aLineNumber,
3450 : nsIStackFrame* aCaller,
3451 : nsIStackFrame** stack);
3452 : private:
3453 : XPCJSStack(); // not implemented
3454 : };
3455 :
3456 : /***************************************************************************/
3457 :
3458 : class nsXPCException :
3459 : public nsIXPCException
3460 : {
3461 : public:
3462 108 : NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCEXCEPTION_CID)
3463 :
3464 : NS_DECL_ISUPPORTS
3465 : NS_DECL_NSIEXCEPTION
3466 : NS_DECL_NSIXPCEXCEPTION
3467 :
3468 : static nsresult NewException(const char *aMessage,
3469 : nsresult aResult,
3470 : nsIStackFrame *aLocation,
3471 : nsISupports *aData,
3472 : nsIException** exception);
3473 :
3474 : static JSBool NameAndFormatForNSResult(nsresult rv,
3475 : const char** name,
3476 : const char** format);
3477 :
3478 : static void* IterateNSResults(nsresult* rv,
3479 : const char** name,
3480 : const char** format,
3481 : void** iterp);
3482 :
3483 : static PRUint32 GetNSResultCount();
3484 :
3485 : nsXPCException();
3486 : virtual ~nsXPCException();
3487 :
3488 1404 : static void InitStatics() { sEverMadeOneFromFactory = false; }
3489 :
3490 : protected:
3491 : void Reset();
3492 : private:
3493 : char* mMessage;
3494 : nsresult mResult;
3495 : char* mName;
3496 : nsIStackFrame* mLocation;
3497 : nsISupports* mData;
3498 : char* mFilename;
3499 : int mLineNumber;
3500 : nsIException* mInner;
3501 : bool mInitialized;
3502 :
3503 : nsAutoJSValHolder mThrownJSVal;
3504 :
3505 : static JSBool sEverMadeOneFromFactory;
3506 : };
3507 :
3508 : /***************************************************************************/
3509 : /*
3510 : * nsJSID implements nsIJSID. It is also used by nsJSIID and nsJSCID as a
3511 : * member (as a hidden implementaion detail) to which they delegate many calls.
3512 : */
3513 :
3514 : // Initialization is done on demand, and calling the destructor below is always
3515 : // safe.
3516 : extern void xpc_DestroyJSxIDClassObjects();
3517 :
3518 : class nsJSID : public nsIJSID
3519 : {
3520 : public:
3521 3257 : NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID)
3522 :
3523 : NS_DECL_ISUPPORTS
3524 : NS_DECL_NSIJSID
3525 :
3526 : bool InitWithName(const nsID& id, const char *nameString);
3527 : bool SetName(const char* name);
3528 0 : void SetNameToNoString()
3529 0 : {NS_ASSERTION(!mName, "name already set"); mName = gNoString;}
3530 364 : bool NameIsSet() const {return nsnull != mName;}
3531 339742 : const nsID& ID() const {return mID;}
3532 169176 : bool IsValid() const {return !mID.Equals(GetInvalidIID());}
3533 :
3534 : static nsJSID* NewID(const char* str);
3535 : static nsJSID* NewID(const nsID& id);
3536 :
3537 : nsJSID();
3538 : virtual ~nsJSID();
3539 : protected:
3540 :
3541 : void Reset();
3542 : const nsID& GetInvalidIID() const;
3543 :
3544 : protected:
3545 : static char gNoString[];
3546 : nsID mID;
3547 : char* mNumber;
3548 : char* mName;
3549 : };
3550 :
3551 : // nsJSIID
3552 :
3553 : class nsJSIID : public nsIJSIID,
3554 : public nsIXPCScriptable,
3555 : public nsISecurityCheckedComponent
3556 : {
3557 : public:
3558 : NS_DECL_ISUPPORTS
3559 :
3560 : // we manually delagate these to nsJSID
3561 : NS_DECL_NSIJSID
3562 :
3563 : // we implement the rest...
3564 : NS_DECL_NSIJSIID
3565 : NS_DECL_NSIXPCSCRIPTABLE
3566 : NS_DECL_NSISECURITYCHECKEDCOMPONENT
3567 :
3568 : static nsJSIID* NewID(nsIInterfaceInfo* aInfo);
3569 :
3570 : nsJSIID(nsIInterfaceInfo* aInfo);
3571 : nsJSIID(); // not implemented
3572 : virtual ~nsJSIID();
3573 :
3574 : private:
3575 : nsCOMPtr<nsIInterfaceInfo> mInfo;
3576 : };
3577 :
3578 : // nsJSCID
3579 :
3580 : class nsJSCID : public nsIJSCID, public nsIXPCScriptable
3581 : {
3582 : public:
3583 : NS_DECL_ISUPPORTS
3584 :
3585 : // we manually delagate these to nsJSID
3586 : NS_DECL_NSIJSID
3587 :
3588 : // we implement the rest...
3589 : NS_DECL_NSIJSCID
3590 : NS_DECL_NSIXPCSCRIPTABLE
3591 :
3592 : static nsJSCID* NewID(const char* str);
3593 :
3594 : nsJSCID();
3595 : virtual ~nsJSCID();
3596 :
3597 : private:
3598 : void ResolveName();
3599 :
3600 : private:
3601 : nsJSID mDetails;
3602 : };
3603 :
3604 :
3605 : /***************************************************************************/
3606 : // XPCJSContextStack is not actually an xpcom object, but xpcom calls are
3607 : // delegated to it as an implementation detail.
3608 435334 : struct XPCJSContextInfo {
3609 435334 : XPCJSContextInfo(JSContext* aCx) :
3610 : cx(aCx),
3611 : savedFrameChain(false),
3612 435334 : suspendDepth(0)
3613 435334 : {}
3614 : JSContext* cx;
3615 :
3616 : // Whether the frame chain was saved
3617 : bool savedFrameChain;
3618 :
3619 : // Greater than 0 if a request was suspended.
3620 : unsigned suspendDepth;
3621 : };
3622 :
3623 : class XPCJSContextStack
3624 : {
3625 : public:
3626 1407 : XPCJSContextStack()
3627 : : mSafeJSContext(NULL)
3628 1407 : , mOwnSafeJSContext(NULL)
3629 1407 : { }
3630 :
3631 : virtual ~XPCJSContextStack();
3632 :
3633 0 : uint32_t Count()
3634 : {
3635 0 : return mStack.Length();
3636 : }
3637 :
3638 18658805 : JSContext *Peek()
3639 : {
3640 18658805 : return mStack.IsEmpty() ? NULL : mStack[mStack.Length() - 1].cx;
3641 : }
3642 :
3643 : JSContext *Pop();
3644 : bool Push(JSContext *cx);
3645 : JSContext *GetSafeJSContext();
3646 :
3647 : #ifdef DEBUG
3648 : bool DEBUG_StackHasJSContext(JSContext *cx);
3649 : #endif
3650 :
3651 0 : const InfallibleTArray<XPCJSContextInfo>* GetStack()
3652 0 : { return &mStack; }
3653 :
3654 : private:
3655 : AutoInfallibleTArray<XPCJSContextInfo, 16> mStack;
3656 : JSContext* mSafeJSContext;
3657 : JSContext* mOwnSafeJSContext;
3658 : };
3659 :
3660 : /***************************************************************************/
3661 :
3662 : #define NS_XPC_JSCONTEXT_STACK_ITERATOR_CID \
3663 : { 0x05bae29d, 0x8aef, 0x486d, \
3664 : { 0x84, 0xaa, 0x53, 0xf4, 0x8f, 0x14, 0x68, 0x11 } }
3665 :
3666 : class nsXPCJSContextStackIterator : public nsIJSContextStackIterator
3667 0 : {
3668 : public:
3669 : NS_DECL_ISUPPORTS
3670 : NS_DECL_NSIJSCONTEXTSTACKITERATOR
3671 :
3672 : private:
3673 : const InfallibleTArray<XPCJSContextInfo> *mStack;
3674 : PRUint32 mPosition;
3675 : };
3676 :
3677 : /**************************************************************/
3678 : // All of our thread local storage.
3679 :
3680 : class XPCPerThreadData
3681 : {
3682 : typedef mozilla::Mutex Mutex;
3683 :
3684 : public:
3685 : // Get the instance of this object for the current thread
3686 19440155 : static inline XPCPerThreadData* GetData(JSContext *cx)
3687 : {
3688 : // Do a release-mode assert that we're not doing anything significant in
3689 : // XPConnect off the main thread. If you're an extension developer hitting
3690 : // this, you need to change your code. See bug 716167.
3691 19440155 : if (!NS_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
3692 0 : MOZ_Assert("NS_IsMainThread()", __FILE__, __LINE__);
3693 :
3694 19440155 : if (cx) {
3695 14345909 : if (js::GetOwnerThread(cx) == sMainJSThread)
3696 14344501 : return sMainThreadData;
3697 5094246 : } else if (sMainThreadData && sMainThreadData->mThread == PR_GetCurrentThread()) {
3698 5092842 : return sMainThreadData;
3699 : }
3700 :
3701 2812 : return GetDataImpl(cx);
3702 : }
3703 :
3704 : static void CleanupAllThreads();
3705 :
3706 : ~XPCPerThreadData();
3707 :
3708 38278 : nsresult GetException(nsIException** aException)
3709 : {
3710 38278 : if (EnsureExceptionManager())
3711 38278 : return mExceptionManager->GetCurrentException(aException);
3712 :
3713 0 : NS_IF_ADDREF(mException);
3714 0 : *aException = mException;
3715 0 : return NS_OK;
3716 : }
3717 :
3718 9203732 : nsresult SetException(nsIException* aException)
3719 : {
3720 9203732 : if (EnsureExceptionManager())
3721 9203732 : return mExceptionManager->SetCurrentException(aException);
3722 :
3723 0 : NS_IF_ADDREF(aException);
3724 0 : NS_IF_RELEASE(mException);
3725 0 : mException = aException;
3726 0 : return NS_OK;
3727 : }
3728 :
3729 38074 : nsIExceptionManager* GetExceptionManager()
3730 : {
3731 38074 : if (EnsureExceptionManager())
3732 38074 : return mExceptionManager;
3733 0 : return nsnull;
3734 : }
3735 :
3736 9280084 : JSBool EnsureExceptionManager()
3737 : {
3738 9280084 : if (mExceptionManager)
3739 9278693 : return true;
3740 :
3741 1391 : if (mExceptionManagerNotAvailable)
3742 0 : return false;
3743 :
3744 : nsCOMPtr<nsIExceptionService> xs =
3745 2782 : do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
3746 1391 : if (xs)
3747 1391 : xs->GetCurrentExceptionManager(&mExceptionManager);
3748 1391 : if (mExceptionManager)
3749 1391 : return true;
3750 :
3751 0 : mExceptionManagerNotAvailable = true;
3752 0 : return false;
3753 : }
3754 :
3755 19339368 : XPCJSContextStack* GetJSContextStack() {return mJSContextStack;}
3756 :
3757 235739 : XPCCallContext* GetCallContext() const {return mCallContext;}
3758 31749366 : XPCCallContext* SetCallContext(XPCCallContext* ccx)
3759 31749366 : {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
3760 :
3761 1692821 : jsid GetResolveName() const {return mResolveName;}
3762 6501348 : jsid SetResolveName(jsid name)
3763 6501348 : {jsid old = mResolveName; mResolveName = name; return old;}
3764 :
3765 224081 : XPCWrappedNative* GetResolvingWrapper() const {return mResolvingWrapper;}
3766 1037978 : XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w)
3767 1037978 : {XPCWrappedNative* old = mResolvingWrapper;
3768 1037978 : mResolvingWrapper = w; return old;}
3769 :
3770 : void Cleanup();
3771 : void ReleaseNatives();
3772 :
3773 1407 : bool IsValid() const {return mJSContextStack != nsnull;}
3774 :
3775 35766 : static Mutex* GetLock() {return gLock;}
3776 : // Must be called with the threads locked.
3777 : static XPCPerThreadData* IterateThreads(XPCPerThreadData** iteratorp);
3778 :
3779 45535894 : AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;}
3780 :
3781 : void TraceJS(JSTracer* trc);
3782 : void MarkAutoRootsAfterJSFinalize();
3783 :
3784 1404 : static void InitStatics()
3785 1404 : { gLock = nsnull; gThreads = nsnull; gTLSIndex = BAD_TLS_INDEX; }
3786 :
3787 : #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
3788 0 : uint32_t IncrementWrappedNativeThreadsafetyReportDepth()
3789 0 : {return ++mWrappedNativeThreadsafetyReportDepth;}
3790 0 : void ClearWrappedNativeThreadsafetyReportDepth()
3791 0 : {mWrappedNativeThreadsafetyReportDepth = 0;}
3792 : #endif
3793 :
3794 1403 : static void ShutDown()
3795 1403 : {sMainJSThread = nsnull; sMainThreadData = nsnull;}
3796 :
3797 12879431 : static bool IsMainThread(JSContext *cx)
3798 12879431 : { return js::GetOwnerThread(cx) == sMainJSThread; }
3799 :
3800 : private:
3801 : XPCPerThreadData();
3802 : static XPCPerThreadData* GetDataImpl(JSContext *cx);
3803 :
3804 : private:
3805 : XPCJSContextStack* mJSContextStack;
3806 : XPCPerThreadData* mNextThread;
3807 : XPCCallContext* mCallContext;
3808 : jsid mResolveName;
3809 : XPCWrappedNative* mResolvingWrapper;
3810 :
3811 : nsIExceptionManager* mExceptionManager;
3812 : nsIException* mException;
3813 : JSBool mExceptionManagerNotAvailable;
3814 : AutoMarkingPtr* mAutoRoots;
3815 :
3816 : #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
3817 : uint32_t mWrappedNativeThreadsafetyReportDepth;
3818 : #endif
3819 : PRThread* mThread;
3820 :
3821 : static Mutex* gLock;
3822 : static XPCPerThreadData* gThreads;
3823 : static PRUintn gTLSIndex;
3824 :
3825 : // Cached value of cx->thread on the main thread.
3826 : static void *sMainJSThread;
3827 :
3828 : // Cached per thread data for the main thread. Only safe to access
3829 : // if cx->thread == sMainJSThread.
3830 : static XPCPerThreadData *sMainThreadData;
3831 : };
3832 :
3833 : /***************************************************************************/
3834 : #include "nsIScriptSecurityManager.h"
3835 :
3836 : class BackstagePass : public nsIScriptObjectPrincipal,
3837 : public nsIXPCScriptable,
3838 : public nsIClassInfo
3839 : {
3840 : public:
3841 : NS_DECL_ISUPPORTS
3842 : NS_DECL_NSIXPCSCRIPTABLE
3843 : NS_DECL_NSICLASSINFO
3844 :
3845 5603479 : virtual nsIPrincipal* GetPrincipal() {
3846 5603479 : return mPrincipal;
3847 : }
3848 :
3849 1391 : BackstagePass(nsIPrincipal *prin) :
3850 1391 : mPrincipal(prin)
3851 : {
3852 1391 : }
3853 :
3854 5492 : virtual ~BackstagePass() { }
3855 :
3856 : private:
3857 : nsCOMPtr<nsIPrincipal> mPrincipal;
3858 : };
3859 : // 'Components' object
3860 :
3861 : class nsXPCComponents : public nsIXPCComponents,
3862 : public nsIXPCScriptable,
3863 : public nsIClassInfo,
3864 : public nsISecurityCheckedComponent
3865 : {
3866 : public:
3867 : NS_DECL_ISUPPORTS
3868 : NS_DECL_NSIXPCCOMPONENTS
3869 : NS_DECL_NSIXPCSCRIPTABLE
3870 : NS_DECL_NSICLASSINFO
3871 : NS_DECL_NSISECURITYCHECKEDCOMPONENT
3872 :
3873 : public:
3874 : static JSBool
3875 : AttachNewComponentsObject(XPCCallContext& ccx,
3876 : XPCWrappedNativeScope* aScope,
3877 : JSObject* aGlobal);
3878 :
3879 24 : void SystemIsBeingShutDown() {ClearMembers();}
3880 :
3881 : virtual ~nsXPCComponents();
3882 :
3883 : private:
3884 : nsXPCComponents();
3885 : void ClearMembers();
3886 :
3887 : private:
3888 : nsXPCComponents_Interfaces* mInterfaces;
3889 : nsXPCComponents_InterfacesByID* mInterfacesByID;
3890 : nsXPCComponents_Classes* mClasses;
3891 : nsXPCComponents_ClassesByID* mClassesByID;
3892 : nsXPCComponents_Results* mResults;
3893 : nsXPCComponents_ID* mID;
3894 : nsXPCComponents_Exception* mException;
3895 : nsXPCComponents_Constructor* mConstructor;
3896 : nsXPCComponents_Utils* mUtils;
3897 : };
3898 :
3899 :
3900 : /***************************************************************************/
3901 :
3902 : extern JSObject*
3903 : xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID);
3904 :
3905 : extern const nsID*
3906 : xpc_JSObjectToID(JSContext *cx, JSObject* obj);
3907 :
3908 : extern JSBool
3909 : xpc_JSObjectIsID(JSContext *cx, JSObject* obj);
3910 :
3911 : /***************************************************************************/
3912 : // in xpcdebug.cpp
3913 :
3914 : extern JSBool
3915 : xpc_DumpJSStack(JSContext* cx, JSBool showArgs, JSBool showLocals,
3916 : JSBool showThisProps);
3917 :
3918 : // Return a newly-allocated string containing a representation of the
3919 : // current JS stack. It is the *caller's* responsibility to free this
3920 : // string with JS_smprintf_free().
3921 : extern char*
3922 : xpc_PrintJSStack(JSContext* cx, JSBool showArgs, JSBool showLocals,
3923 : JSBool showThisProps);
3924 :
3925 : extern JSBool
3926 : xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text);
3927 :
3928 : extern JSBool
3929 : xpc_DumpJSObject(JSObject* obj);
3930 :
3931 : extern JSBool
3932 : xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
3933 :
3934 : /***************************************************************************/
3935 :
3936 : // Definition of nsScriptError, defined here because we lack a place to put
3937 : // XPCOM objects associated with the JavaScript engine.
3938 : class nsScriptError : public nsIScriptError {
3939 : public:
3940 : nsScriptError();
3941 :
3942 : virtual ~nsScriptError();
3943 :
3944 : // TODO - do something reasonable on getting null from these babies.
3945 :
3946 : NS_DECL_ISUPPORTS
3947 : NS_DECL_NSICONSOLEMESSAGE
3948 : NS_DECL_NSISCRIPTERROR
3949 :
3950 : private:
3951 : nsString mMessage;
3952 : nsString mSourceName;
3953 : PRUint32 mLineNumber;
3954 : nsString mSourceLine;
3955 : PRUint32 mColumnNumber;
3956 : PRUint32 mFlags;
3957 : nsCString mCategory;
3958 : PRUint64 mOuterWindowID;
3959 : PRUint64 mInnerWindowID;
3960 : PRInt64 mTimeStamp;
3961 : };
3962 :
3963 : /******************************************************************************
3964 : * Handles pre/post script processing and the setting/resetting the error
3965 : * reporter
3966 : */
3967 : class NS_STACK_CLASS AutoScriptEvaluate
3968 : {
3969 : public:
3970 : /**
3971 : * Saves the JSContext as well as initializing our state
3972 : * @param cx The JSContext, this can be null, we don't do anything then
3973 : */
3974 1520912 : AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
3975 : : mJSContext(cx), mState(0), mErrorReporterSet(false),
3976 1520912 : mEvaluated(false), mContextHasThread(0) {
3977 1520912 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
3978 1520912 : }
3979 :
3980 : /**
3981 : * Does the pre script evaluation and sets the error reporter if given
3982 : * This function should only be called once, and will assert if called
3983 : * more than once
3984 : * @param errorReporter the error reporter callback function to set
3985 : */
3986 :
3987 : bool StartEvaluating(JSObject *scope, JSErrorReporter errorReporter = nsnull);
3988 : /**
3989 : * Does the post script evaluation and resets the error reporter
3990 : */
3991 : ~AutoScriptEvaluate();
3992 : private:
3993 : JSContext* mJSContext;
3994 : JSExceptionState* mState;
3995 : bool mErrorReporterSet;
3996 : bool mEvaluated;
3997 : intptr_t mContextHasThread;
3998 : JSAutoEnterCompartment mEnterCompartment;
3999 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
4000 :
4001 : // No copying or assignment allowed
4002 : AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
4003 : AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;
4004 : };
4005 :
4006 : /***************************************************************************/
4007 : class NS_STACK_CLASS AutoResolveName
4008 : {
4009 : public:
4010 1719228 : AutoResolveName(XPCCallContext& ccx, jsid name
4011 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
4012 1719228 : : mTLS(ccx.GetThreadData()),
4013 1719228 : mOld(mTLS->SetResolveName(name)),
4014 3438456 : mCheck(name) {
4015 1719228 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
4016 1719228 : }
4017 1719228 : ~AutoResolveName()
4018 1719228 : {
4019 : #ifdef DEBUG
4020 : jsid old =
4021 : #endif
4022 1719228 : mTLS->SetResolveName(mOld);
4023 1719228 : NS_ASSERTION(old == mCheck, "Bad Nesting!");
4024 1719228 : }
4025 :
4026 : private:
4027 : XPCPerThreadData* mTLS;
4028 : jsid mOld;
4029 : jsid mCheck;
4030 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
4031 : };
4032 :
4033 : /***************************************************************************/
4034 : class XPCMarkableJSVal
4035 : {
4036 : public:
4037 1873201 : XPCMarkableJSVal(jsval val) : mVal(val), mValPtr(&mVal) {}
4038 8140419 : XPCMarkableJSVal(jsval *pval) : mVal(JSVAL_VOID), mValPtr(pval) {}
4039 10013620 : ~XPCMarkableJSVal() {}
4040 7 : void Mark() {}
4041 7 : void TraceJS(JSTracer* trc)
4042 : {
4043 7 : JS_CALL_VALUE_TRACER(trc, *mValPtr, "XPCMarkableJSVal");
4044 7 : }
4045 7 : void AutoTrace(JSTracer* trc) {}
4046 : private:
4047 : XPCMarkableJSVal(); // not implemented
4048 : jsval mVal;
4049 : jsval* mValPtr;
4050 : };
4051 :
4052 : /***************************************************************************/
4053 : // AutoMarkingPtr is the base class for the various AutoMarking pointer types
4054 : // below. This system allows us to temporarily protect instances of our garbage
4055 : // collected types after they are constructed but before they are safely
4056 : // attached to other rooted objects.
4057 : // This base class has pure virtual support for marking.
4058 :
4059 : class AutoMarkingPtr
4060 : {
4061 : public:
4062 20772830 : AutoMarkingPtr(XPCCallContext& ccx)
4063 20772830 : : mNext(nsnull), mTLS(ccx.GetThreadData()) {Link();}
4064 2001182 : AutoMarkingPtr()
4065 2001182 : : mNext(nsnull), mTLS(nsnull) {}
4066 :
4067 45548024 : virtual ~AutoMarkingPtr() {Unlink();}
4068 :
4069 1995117 : void Init(XPCCallContext& ccx)
4070 1995117 : {NS_ASSERTION(!mTLS, "Already init'ed!");
4071 1995117 : mTLS = ccx.GetThreadData();
4072 1995117 : Link();}
4073 :
4074 22767947 : void Link()
4075 22767947 : {if (!mTLS) return;
4076 22767947 : AutoMarkingPtr** list = mTLS->GetAutoRootsAdr();
4077 22767947 : mNext = *list; *list = this;}
4078 :
4079 22774012 : void Unlink()
4080 22774012 : {if (!mTLS) return;
4081 22767947 : AutoMarkingPtr** cur = mTLS->GetAutoRootsAdr();
4082 45535894 : while (*cur != this) {
4083 0 : NS_ASSERTION(*cur, "This object not in list!");
4084 0 : cur = &(*cur)->mNext;
4085 : }
4086 22767947 : *cur = mNext;
4087 22767947 : mTLS = nsnull;
4088 : }
4089 :
4090 : AutoMarkingPtr* GetNext() {return mNext;}
4091 :
4092 : virtual void TraceJS(JSTracer* trc) = 0;
4093 : virtual void MarkAfterJSFinalize() = 0;
4094 :
4095 : protected:
4096 : AutoMarkingPtr* mNext;
4097 : XPCPerThreadData* mTLS;
4098 : };
4099 :
4100 : // More joy of macros...
4101 :
4102 : #define DEFINE_AUTO_MARKING_PTR_TYPE(class_, type_) \
4103 : class class_ : public AutoMarkingPtr \
4104 : { \
4105 : public: \
4106 : class_ () \
4107 : : AutoMarkingPtr(), mPtr(nsnull) {} \
4108 : class_ (XPCCallContext& ccx, type_ * ptr = nsnull) \
4109 : : AutoMarkingPtr(ccx), mPtr(ptr) {} \
4110 : virtual ~ class_ () {} \
4111 : \
4112 : virtual void TraceJS(JSTracer* trc) \
4113 : {if (mPtr) { \
4114 : mPtr->TraceJS(trc); \
4115 : mPtr->AutoTrace(trc); \
4116 : } \
4117 : if (mNext) mNext->TraceJS(trc);} \
4118 : \
4119 : virtual void MarkAfterJSFinalize() \
4120 : {if (mPtr) mPtr->Mark(); \
4121 : if (mNext) mNext->MarkAfterJSFinalize();} \
4122 : \
4123 : type_ * get() const {return mPtr;} \
4124 : operator type_ *() const {return mPtr;} \
4125 : type_ * operator->() const {return mPtr;} \
4126 : \
4127 : class_ & operator =(type_ * p) \
4128 : {NS_ASSERTION(mTLS, "Hasn't been init'ed!"); \
4129 : mPtr = p; return *this;} \
4130 : \
4131 : protected: \
4132 : type_ * mPtr; \
4133 : };
4134 :
4135 : // Use the macro above to define our AutoMarking types...
4136 :
4137 35066094 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeInterfacePtr, XPCNativeInterface)
4138 16566700 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeSetPtr, XPCNativeSet)
4139 3768909 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativePtr, XPCWrappedNative)
4140 4582761 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeTearOffPtr, XPCWrappedNativeTearOff)
4141 8312398 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeProtoPtr, XPCWrappedNativeProto)
4142 30040874 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingJSVal, XPCMarkableJSVal)
4143 79302 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeScriptableInfoPtr, XPCNativeScriptableInfo)
4144 :
4145 : #define DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(class_, type_) \
4146 : class class_ : public AutoMarkingPtr \
4147 : { \
4148 : public: \
4149 : class_ (XPCCallContext& ccx) \
4150 : : AutoMarkingPtr(ccx), mPtr(nsnull), mCount(0) {} \
4151 : class_ (XPCCallContext& ccx, type_** aPtr, PRUint32 aCount, \
4152 : bool aClear = false) \
4153 : : AutoMarkingPtr(ccx), mPtr(aPtr), mCount(aCount) \
4154 : { \
4155 : if (!mPtr) mCount = 0; \
4156 : else if (aClear) memset(mPtr, 0, mCount*sizeof(type_*)); \
4157 : } \
4158 : virtual ~ class_ () {} \
4159 : \
4160 : virtual void TraceJS(JSTracer* trc) \
4161 : { \
4162 : for (PRUint32 i = 0; i < mCount; ++i) { \
4163 : type_* cur = mPtr[i]; \
4164 : if (cur) { \
4165 : cur->TraceJS(trc); \
4166 : cur->AutoTrace(trc); \
4167 : } \
4168 : } \
4169 : if (mNext) mNext->TraceJS(trc); \
4170 : } \
4171 : \
4172 : virtual void MarkAfterJSFinalize() \
4173 : { \
4174 : for (PRUint32 i = 0; i < mCount; ++i) { \
4175 : type_* cur = mPtr[i]; \
4176 : if (cur) \
4177 : cur->Mark(); \
4178 : } \
4179 : if (mNext) mNext->MarkAfterJSFinalize(); \
4180 : } \
4181 : \
4182 : type_ ** get() const {return mPtr;} \
4183 : operator type_ **() const {return mPtr;} \
4184 : type_ ** operator->() const {return mPtr;} \
4185 : \
4186 : class_ & operator =(const class_ & inst) \
4187 : {mPtr = inst.mPtr; mCount = inst.mCount; return *this;} \
4188 : \
4189 : protected: \
4190 : type_ ** mPtr; \
4191 : PRUint32 mCount; \
4192 : };
4193 :
4194 1438302 : DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(AutoMarkingNativeInterfacePtrArrayPtr,
4195 : XPCNativeInterface)
4196 :
4197 : // Note: It looked like I would need one of these AutoMarkingPtr types for
4198 : // XPCNativeScriptableInfo in order to manage marking its
4199 : // XPCNativeScriptableShared member during construction. But AFAICT we build
4200 : // these and bind them to rooted things so immediately that this just is not
4201 : // needed.
4202 :
4203 : #define AUTO_MARK_JSVAL_HELPER2(tok, line) tok##line
4204 : #define AUTO_MARK_JSVAL_HELPER(tok, line) AUTO_MARK_JSVAL_HELPER2(tok, line)
4205 :
4206 : #define AUTO_MARK_JSVAL(ccx, val) \
4207 : XPCMarkableJSVal AUTO_MARK_JSVAL_HELPER(_val_,__LINE__)(val); \
4208 : AutoMarkingJSVal AUTO_MARK_JSVAL_HELPER(_automarker_,__LINE__) \
4209 : (ccx, &AUTO_MARK_JSVAL_HELPER(_val_,__LINE__))
4210 :
4211 : /***************************************************************************/
4212 : // Allocates a string that grants all access ("AllAccess")
4213 :
4214 : extern char* xpc_CloneAllAccess();
4215 : /***************************************************************************/
4216 : // Returns access if wideName is in list
4217 :
4218 : extern char * xpc_CheckAccessList(const PRUnichar* wideName, const char* list[]);
4219 :
4220 : /***************************************************************************/
4221 : // in xpcvariant.cpp...
4222 :
4223 : // {1809FD50-91E8-11d5-90F9-0010A4E73D9A}
4224 : #define XPCVARIANT_IID \
4225 : {0x1809fd50, 0x91e8, 0x11d5, \
4226 : { 0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
4227 :
4228 : // {DC524540-487E-4501-9AC7-AAA784B17C1C}
4229 : #define XPCVARIANT_CID \
4230 : {0xdc524540, 0x487e, 0x4501, \
4231 : { 0x9a, 0xc7, 0xaa, 0xa7, 0x84, 0xb1, 0x7c, 0x1c } }
4232 :
4233 : class XPCVariant : public nsIVariant
4234 : {
4235 : public:
4236 2 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
4237 : NS_DECL_NSIVARIANT
4238 31123 : NS_DECL_CYCLE_COLLECTION_CLASS(XPCVariant)
4239 :
4240 : // If this class ever implements nsIWritableVariant, take special care with
4241 : // the case when mJSVal is JSVAL_STRING, since we don't own the data in
4242 : // that case.
4243 :
4244 : // We #define and iid so that out module local code can use QI to detect
4245 : // if a given nsIVariant is in fact an XPCVariant.
4246 : NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
4247 :
4248 : static XPCVariant* newVariant(XPCCallContext& ccx, jsval aJSVal);
4249 :
4250 : /**
4251 : * This getter clears the gray bit before handing out the jsval if the jsval
4252 : * represents a JSObject. That means that the object is guaranteed to be
4253 : * kept alive past the next CC.
4254 : */
4255 8002 : jsval GetJSVal() const
4256 8002 : {if (!JSVAL_IS_PRIMITIVE(mJSVal))
4257 1533 : xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(mJSVal));
4258 8002 : return mJSVal;}
4259 :
4260 : /**
4261 : * This getter does not change the color of the jsval (if it represents a
4262 : * JSObject) meaning that the value returned is not guaranteed to be kept
4263 : * alive past the next CC.
4264 : *
4265 : * This should only be called if you are certain that the return value won't
4266 : * be passed into a JS API function and that it won't be stored without
4267 : * being rooted (or otherwise signaling the stored value to the CC).
4268 : */
4269 4016 : jsval GetJSValPreserveColor() const {return mJSVal;}
4270 :
4271 : XPCVariant(XPCCallContext& ccx, jsval aJSVal);
4272 :
4273 : /**
4274 : * Convert a variant into a jsval.
4275 : *
4276 : * @param ccx the context for the whole procedure
4277 : * @param variant the variant to convert
4278 : * @param scope the default scope to put on the new JSObject's parent chain
4279 : * @param pErr [out] relevant error code, if any.
4280 : * @param pJSVal [out] the resulting jsval.
4281 : */
4282 : static JSBool VariantDataToJS(XPCLazyCallContext& lccx,
4283 : nsIVariant* variant,
4284 : nsresult* pErr, jsval* pJSVal);
4285 :
4286 0 : bool IsPurple()
4287 : {
4288 0 : return mRefCnt.IsPurple();
4289 : }
4290 :
4291 0 : void RemovePurple()
4292 : {
4293 0 : mRefCnt.RemovePurple();
4294 0 : }
4295 :
4296 0 : void SetCCGeneration(PRUint32 aGen)
4297 : {
4298 0 : mCCGeneration = aGen;
4299 0 : }
4300 :
4301 0 : PRUint32 CCGeneration() { return mCCGeneration; }
4302 : protected:
4303 19134 : virtual ~XPCVariant() { }
4304 :
4305 : JSBool InitializeData(XPCCallContext& ccx);
4306 :
4307 : protected:
4308 : nsDiscriminatedUnion mData;
4309 : jsval mJSVal;
4310 : bool mReturnRawObject : 1;
4311 : PRUint32 mCCGeneration : 31;
4312 : };
4313 :
4314 : NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID)
4315 :
4316 : class XPCTraceableVariant: public XPCVariant,
4317 : public XPCRootSetElem
4318 : {
4319 : public:
4320 3463 : XPCTraceableVariant(XPCCallContext& ccx, jsval aJSVal)
4321 3463 : : XPCVariant(ccx, aJSVal)
4322 : {
4323 3463 : ccx.GetRuntime()->AddVariantRoot(this);
4324 3463 : }
4325 :
4326 : virtual ~XPCTraceableVariant();
4327 :
4328 : void TraceJS(JSTracer* trc);
4329 : #ifdef DEBUG
4330 : static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
4331 : #endif
4332 : };
4333 :
4334 : /***************************************************************************/
4335 :
4336 : #define PRINCIPALHOLDER_IID \
4337 : {0xbf109f49, 0xf94a, 0x43d8, {0x93, 0xdb, 0xe4, 0x66, 0x49, 0xc5, 0xd9, 0x7d}}
4338 :
4339 : class PrincipalHolder : public nsIScriptObjectPrincipal
4340 : {
4341 : public:
4342 : NS_DECLARE_STATIC_IID_ACCESSOR(PRINCIPALHOLDER_IID)
4343 :
4344 1706 : PrincipalHolder(nsIPrincipal *holdee)
4345 1706 : : mHoldee(holdee)
4346 : {
4347 1706 : }
4348 6820 : virtual ~PrincipalHolder() { }
4349 :
4350 : NS_DECL_ISUPPORTS
4351 :
4352 : nsIPrincipal *GetPrincipal();
4353 :
4354 : private:
4355 : nsCOMPtr<nsIPrincipal> mHoldee;
4356 : };
4357 :
4358 : NS_DEFINE_STATIC_IID_ACCESSOR(PrincipalHolder, PRINCIPALHOLDER_IID)
4359 :
4360 : /***************************************************************************/
4361 : // Utilities
4362 :
4363 : inline void *
4364 9026462 : xpc_GetJSPrivate(JSObject *obj)
4365 : {
4366 9026462 : return js::GetObjectPrivate(obj);
4367 : }
4368 :
4369 :
4370 : // Helper for creating a sandbox object to use for evaluating
4371 : // untrusted code completely separated from all other code in the
4372 : // system using xpc_EvalInSandbox(). Takes the JSContext on which to
4373 : // do setup etc on, puts the sandbox object in *vp (which must be
4374 : // rooted by the caller), and uses the principal that's either
4375 : // directly passed in prinOrSop or indirectly as an
4376 : // nsIScriptObjectPrincipal holding the principal. If no principal is
4377 : // reachable through prinOrSop, a new null principal will be created
4378 : // and used.
4379 : nsresult
4380 : xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop,
4381 : JSObject *proto, bool preferXray, const nsACString &sandboxName,
4382 : nsISupports *identityPtr = nsnull);
4383 : // Helper for evaluating scripts in a sandbox object created with
4384 : // xpc_CreateSandboxObject(). The caller is responsible of ensuring
4385 : // that *rval doesn't get collected during the call or usage after the
4386 : // call. This helper will use filename and lineNo for error reporting,
4387 : // and if no filename is provided it will use the codebase from the
4388 : // principal and line number 1 as a fallback. if returnStringOnly is
4389 : // true, then the result in *rval, or the exception in cx->exception
4390 : // will be coerced into strings. If an exception is thrown converting
4391 : // an exception to a string, evalInSandbox will return an NS_ERROR_*
4392 : // result, and cx->exception will be empty.
4393 : nsresult
4394 : xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
4395 : const char *filename, PRInt32 lineNo,
4396 : JSVersion jsVersion, bool returnStringOnly, jsval *rval);
4397 :
4398 : /***************************************************************************/
4399 : // Inlined utilities.
4400 :
4401 : inline JSBool
4402 : xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsid id);
4403 :
4404 : inline jsid
4405 : GetRTIdByIndex(JSContext *cx, unsigned index);
4406 :
4407 : // Wrapper for JS_NewObject to mark the new object as system when parent is
4408 : // also a system object. If uniqueType is specified then a new type object will
4409 : // be created which is used only by the result, so that its property types
4410 : // will be tracked precisely.
4411 : inline JSObject*
4412 : xpc_NewSystemInheritingJSObject(JSContext *cx, JSClass *clasp, JSObject *proto,
4413 : bool uniqueType, JSObject *parent);
4414 :
4415 : nsISupports *
4416 : XPC_GetIdentityObject(JSContext *cx, JSObject *obj);
4417 :
4418 : namespace xpc {
4419 :
4420 : struct CompartmentPrivate
4421 : {
4422 3369 : CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays)
4423 : : key(key),
4424 3369 : wantXrays(wantXrays)
4425 : {
4426 3369 : MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
4427 3369 : }
4428 :
4429 : ~CompartmentPrivate();
4430 :
4431 : nsAutoPtr<PtrAndPrincipalHashKey> key;
4432 : bool wantXrays;
4433 : nsAutoPtr<JSObject2JSObjectMap> waiverWrapperMap;
4434 : // NB: we don't want this map to hold a strong reference to the wrapper.
4435 : nsAutoPtr<nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> > expandoMap;
4436 : nsAutoPtr<nsTHashtable<nsPtrHashKey<JSObject> > > domExpandoMap;
4437 : nsCString location;
4438 :
4439 0 : bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
4440 0 : if (!expandoMap) {
4441 0 : expandoMap = new nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *>();
4442 0 : if (!expandoMap->Init(8)) {
4443 0 : expandoMap = nsnull;
4444 0 : return false;
4445 : }
4446 : }
4447 0 : wn->SetHasExpandoObject();
4448 0 : return expandoMap->Put(wn, expando);
4449 : }
4450 :
4451 : /**
4452 : * This lookup does not change the color of the JSObject meaning that the
4453 : * object returned is not guaranteed to be kept alive past the next CC.
4454 : *
4455 : * This should only be called if you are certain that the return value won't
4456 : * be passed into a JS API function and that it won't be stored without
4457 : * being rooted (or otherwise signaling the stored value to the CC).
4458 : */
4459 0 : JSObject *LookupExpandoObjectPreserveColor(XPCWrappedNative *wn) {
4460 0 : return expandoMap ? expandoMap->Get(wn) : nsnull;
4461 : }
4462 :
4463 : /**
4464 : * This lookup clears the gray bit before handing out the JSObject which
4465 : * means that the object is guaranteed to be kept alive past the next CC.
4466 : */
4467 0 : JSObject *LookupExpandoObject(XPCWrappedNative *wn) {
4468 0 : JSObject *obj = LookupExpandoObjectPreserveColor(wn);
4469 0 : xpc_UnmarkGrayObject(obj);
4470 0 : return obj;
4471 : }
4472 :
4473 0 : bool RegisterDOMExpandoObject(JSObject *expando) {
4474 0 : if (!domExpandoMap) {
4475 0 : domExpandoMap = new nsTHashtable<nsPtrHashKey<JSObject> >();
4476 0 : if (!domExpandoMap->Init(8)) {
4477 0 : domExpandoMap = nsnull;
4478 0 : return false;
4479 : }
4480 : }
4481 0 : return domExpandoMap->PutEntry(expando);
4482 : }
4483 0 : void RemoveDOMExpandoObject(JSObject *expando) {
4484 0 : if (domExpandoMap)
4485 0 : domExpandoMap->RemoveEntry(expando);
4486 0 : }
4487 : };
4488 :
4489 : }
4490 :
4491 : /***************************************************************************/
4492 : // Inlines use the above - include last.
4493 :
4494 : #include "XPCInlines.h"
4495 :
4496 : /***************************************************************************/
4497 : // Maps have inlines that use the above - include last.
4498 :
4499 : #include "XPCMaps.h"
4500 :
4501 : /***************************************************************************/
4502 :
4503 : #endif /* xpcprivate_h___ */
|