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 3304 : PtrAndPrincipalHashKey(const PtrAndPrincipalHashKey *aKey)
246 : : mPtr(aKey->mPtr), mPrincipal(aKey->mPrincipal),
247 3304 : mSavedHash(aKey->mSavedHash)
248 : {
249 3304 : MOZ_COUNT_CTOR(PtrAndPrincipalHashKey);
250 3304 : }
251 :
252 18415 : PtrAndPrincipalHashKey(nsISupports *aPtr, nsIPrincipal *aPrincipal)
253 18415 : : mPtr(aPtr), mPrincipal(aPrincipal)
254 : {
255 18415 : MOZ_COUNT_CTOR(PtrAndPrincipalHashKey);
256 36830 : nsCOMPtr<nsIURI> uri;
257 18415 : aPrincipal->GetURI(getter_AddRefs(uri));
258 : mSavedHash = uri
259 2750 : ? NS_SecurityHashURI(uri)
260 21165 : : (NS_PTR_TO_UINT32(mPtr.get()) >> 2);
261 18415 : }
262 :
263 21715 : ~PtrAndPrincipalHashKey()
264 21715 : {
265 21715 : MOZ_COUNT_DTOR(PtrAndPrincipalHashKey);
266 21715 : }
267 :
268 57850 : PtrAndPrincipalHashKey* GetKey() const
269 : {
270 57850 : 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 25019 : KeyToPointer(PtrAndPrincipalHashKey* aKey) { return aKey; }
278 25019 : static PLDHashNumber HashKey(const PtrAndPrincipalHashKey* aKey)
279 : {
280 25019 : 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 14509 : static inline void xpc_NotifyAll(XPCLock* lock)
344 : {
345 14509 : NS_ASSERTION(lock, "xpc_NotifyAll called with null lock!");
346 14509 : lock->NotifyAll();
347 14509 : }
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 1365 : static XPCLock* NewLock(const char* name)
363 1365 : {return new mozilla::ReentrantMonitor(name);}
364 1364 : static void DestroyLock(XPCLock* lock)
365 2728 : {delete lock;}
366 :
367 34351767 : XPCAutoLock(XPCLock* lock MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
368 34351767 : : mLock(lock)
369 : {
370 34351767 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
371 34351767 : if (mLock)
372 17981064 : mLock->Enter();
373 34351767 : }
374 :
375 34351767 : ~XPCAutoLock()
376 34351767 : {
377 34351767 : if (mLock) {
378 17981064 : mLock->Exit();
379 : }
380 34351767 : }
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 1504858 : XPCAutoUnlock(XPCLock* lock MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
407 1504858 : : mLock(lock)
408 : {
409 1504858 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
410 1504858 : if (mLock) {
411 346831 : mLock->Exit();
412 : }
413 1504858 : }
414 :
415 1504858 : ~XPCAutoUnlock()
416 1504858 : {
417 1504858 : if (mLock)
418 346831 : mLock->Enter();
419 1504858 : }
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 5064630 : AddToCCKind(JSGCTraceKind kind)
458 : {
459 5064630 : 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 2621686 : 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 1984810 : nsIXPCSecurityManager* GetDefaultSecurityManager() const
496 : {
497 : // mDefaultSecurityManager is main-thread only.
498 1984810 : if (!NS_IsMainThread()) {
499 0 : return nsnull;
500 : }
501 1984810 : return mDefaultSecurityManager;
502 : }
503 :
504 1982603 : PRUint16 GetDefaultSecurityManagerFlags() const
505 1982603 : {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 1365 : 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 58036 : JSBool IsShuttingDown() const {return mShuttingDown;}
520 :
521 0 : void EnsureGCBeforeCC() { mNeedGCBeforeCC = true; }
522 14509 : 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 6312 : static bool ReportAllJSExceptions()
570 : {
571 6312 : 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 127491 : XPCRootSetElem()
623 : {
624 : #ifdef DEBUG
625 127491 : mNext = nsnull;
626 127491 : mSelfp = nsnull;
627 : #endif
628 127491 : }
629 :
630 127210 : ~XPCRootSetElem()
631 : {
632 127210 : NS_ASSERTION(!mNext, "Must be unlinked");
633 127210 : NS_ASSERTION(!mSelfp, "Must be unlinked");
634 127210 : }
635 :
636 158037 : 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 1817797 : JSRuntime* GetJSRuntime() const {return mJSRuntime;}
657 2188511 : nsXPConnect* GetXPConnect() const {return mXPConnect;}
658 : JSContext* GetJSCycleCollectionContext();
659 :
660 390439 : JSObject2WrappedJSMap* GetWrappedJSMap() const
661 390439 : {return mWrappedJSMap;}
662 :
663 240707 : IID2WrappedJSClassMap* GetWrappedJSClassMap() const
664 240707 : {return mWrappedJSClassMap;}
665 :
666 2640144 : IID2NativeInterfaceMap* GetIID2NativeInterfaceMap() const
667 2640144 : {return mIID2NativeInterfaceMap;}
668 :
669 373254 : ClassInfo2NativeSetMap* GetClassInfo2NativeSetMap() const
670 373254 : {return mClassInfo2NativeSetMap;}
671 :
672 1157926 : NativeSetMap* GetNativeSetMap() const
673 1157926 : {return mNativeSetMap;}
674 :
675 9314 : IID2ThisTranslatorMap* GetThisTranslatorMap() const
676 9314 : {return mThisTranslatorMap;}
677 :
678 250296 : XPCNativeScriptableSharedMap* GetNativeScriptableSharedMap() const
679 250296 : {return mNativeScriptableSharedMap;}
680 :
681 187233 : XPCWrappedNativeProtoMap* GetDyingWrappedNativeProtoMap() const
682 187233 : {return mDyingWrappedNativeProtoMap;}
683 :
684 190300 : XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const
685 190300 : {return mDetachedWrappedNativeProtoMap;}
686 :
687 1365 : XPCNativeWrapperMap* GetExplicitNativeWrapperMap() const
688 1365 : {return mExplicitNativeWrapperMap;}
689 :
690 49323 : XPCCompartmentMap& GetCompartmentMap()
691 49323 : {return mCompartmentMap;}
692 :
693 18169428 : XPCLock* GetMapLock() const {return mMapLock;}
694 :
695 : JSBool OnJSContextNew(JSContext* cx);
696 :
697 : JSBool DeferredRelease(nsISupports* obj);
698 :
699 1241226 : 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 13554285 : jsid GetStringID(unsigned index) const
731 : {
732 13554285 : NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
733 13554285 : 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 2089352 : 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 15388 : bool NewDOMBindingsEnabled()
796 : {
797 15388 : 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 16765765 : static XPCContext* GetXPCContext(JSContext* aJSContext)
861 : {
862 16765765 : NS_ASSERTION(JS_GetSecondContextPrivate(aJSContext), "should already have XPCContext");
863 16765765 : return static_cast<XPCContext *>(JS_GetSecondContextPrivate(aJSContext));
864 : }
865 :
866 14873411 : XPCJSRuntime* GetRuntime() const {return mRuntime;}
867 116105 : 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 33113150 : LangType SetCallingLangType(LangType lt)
876 : {
877 33113150 : LangType tmp = mCallingLangType;
878 33113150 : mCallingLangType = lt;
879 33113150 : return tmp;
880 : }
881 16451375 : JSBool CallerTypeIsJavaScript() const
882 : {
883 16451375 : return LANG_JS == mCallingLangType;
884 : }
885 : JSBool CallerTypeIsNative() const
886 : {
887 : return LANG_NATIVE == mCallingLangType;
888 : }
889 9079552 : JSBool CallerTypeIsKnown() const
890 : {
891 9079552 : return LANG_UNKNOWN != mCallingLangType;
892 : }
893 :
894 6784 : nsresult GetException(nsIException** e)
895 : {
896 6784 : NS_IF_ADDREF(mException);
897 6784 : *e = mException;
898 6784 : return NS_OK;
899 : }
900 1220005 : void SetException(nsIException* e)
901 : {
902 1220005 : NS_IF_ADDREF(e);
903 1220005 : NS_IF_RELEASE(mException);
904 1220005 : mException = e;
905 1220005 : }
906 :
907 2 : nsresult GetLastResult() {return mLastResult;}
908 14743618 : void SetLastResult(nsresult rc) {mLastResult = rc;}
909 :
910 6784 : nsresult GetPendingResult() {return mPendingResult;}
911 1219821 : void SetPendingResult(nsresult rc) {mPendingResult = rc;}
912 :
913 1365 : nsIXPCSecurityManager* GetSecurityManager() const
914 1365 : {return mSecurityManager;}
915 1365 : void SetSecurityManager(nsIXPCSecurityManager* aSecurityManager)
916 1365 : {mSecurityManager = aSecurityManager;}
917 :
918 0 : PRUint16 GetSecurityManagerFlags() const
919 0 : {return mSecurityManagerFlags;}
920 1365 : void SetSecurityManagerFlags(PRUint16 f)
921 1365 : {mSecurityManagerFlags = f;}
922 :
923 9079552 : nsIXPCSecurityManager* GetAppropriateSecurityManager(PRUint16 flags) const
924 : {
925 9079552 : NS_ASSERTION(CallerTypeIsKnown(),"missing caller type set somewhere");
926 9079552 : if (!CallerTypeIsJavaScript())
927 562118 : return nsnull;
928 8517434 : if (mSecurityManager) {
929 6534831 : if (flags & mSecurityManagerFlags)
930 6534831 : return mSecurityManager;
931 : } else {
932 : nsIXPCSecurityManager* mgr;
933 1982603 : nsXPConnect* xpc = mRuntime->GetXPConnect();
934 1982603 : mgr = xpc->GetDefaultSecurityManager();
935 1982603 : if (mgr && (flags & xpc->GetDefaultSecurityManagerFlags()))
936 1982603 : return mgr;
937 : }
938 0 : return nsnull;
939 : }
940 :
941 : void DebugDump(PRInt16 depth);
942 15388 : void AddScope(PRCList *scope) { PR_INSERT_AFTER(scope, &mScopes); }
943 1638 : 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 210038 : {
975 : public:
976 : typedef nsDependentString::char_traits char_traits;
977 :
978 226558 : XPCReadableJSStringWrapper(const PRUnichar *chars, size_t length) :
979 226558 : nsDependentString(chars, length)
980 226558 : { }
981 :
982 22481 : XPCReadableJSStringWrapper() :
983 22481 : nsDependentString(char_traits::sEmptyBuffer, char_traits::sEmptyBuffer)
984 22481 : { 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 41809898 : 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 314864354 : 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 33113150 : 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 21497555 : 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 21497555 : , mTearOff(nsnull)
1234 : #endif
1235 : {
1236 21497555 : }
1237 139812 : 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 139812 : mTearOff(tearoff)
1252 : {
1253 139812 : NS_ASSERTION(cx, "Need a JS context!");
1254 139812 : NS_ASSERTION(callerLanguage == NATIVE_CALLER ||
1255 : callerLanguage == JS_CALLER,
1256 : "Can't deal with unknown caller language!");
1257 : #ifdef DEBUG
1258 139812 : AssertContextIsTopOfStack(cx);
1259 : #endif
1260 139812 : }
1261 21637367 : ~XPCLazyCallContext()
1262 : {
1263 21637367 : if (mCcxToDestroy)
1264 129979 : mCcxToDestroy->~XPCCallContext();
1265 21507388 : else if (mCallBeginRequest == CALLED_BEGINREQUEST)
1266 0 : JS_EndRequest(mCx);
1267 21637367 : }
1268 : void SetWrapper(XPCWrappedNative* wrapper,
1269 : XPCWrappedNativeTearOff* tearoff);
1270 : void SetWrapper(JSObject* flattenedJSObject);
1271 :
1272 25932845 : JSContext *GetJSContext()
1273 : {
1274 25932845 : if (mCcx)
1275 25674126 : return mCcx->GetJSContext();
1276 :
1277 258719 : if (mCallBeginRequest == CALL_BEGINREQUEST) {
1278 99172 : JS_BeginRequest(mCx);
1279 99172 : mCallBeginRequest = CALLED_BEGINREQUEST;
1280 : }
1281 :
1282 258719 : return mCx;
1283 : }
1284 9045299 : JSObject *GetScopeForNewJSObjects() const
1285 : {
1286 9045299 : if (mCcx)
1287 8775215 : return mCcx->GetScopeForNewJSObjects();
1288 :
1289 270084 : return mObj;
1290 : }
1291 637580 : void SetScopeForNewJSObjects(JSObject *obj)
1292 : {
1293 637580 : if (mCcx) {
1294 538408 : mCcx->SetScopeForNewJSObjects(obj);
1295 538408 : return;
1296 : }
1297 99172 : NS_ABORT_IF_FALSE(!mObj, "already set!");
1298 99172 : mObj = obj;
1299 : }
1300 : JSObject *GetFlattenedJSObject() const
1301 : {
1302 : if (mCcx)
1303 : return mCcx->GetFlattenedJSObject();
1304 :
1305 : return mFlattenedJSObject;
1306 : }
1307 5761675 : XPCCallContext &GetXPCCallContext()
1308 : {
1309 5761675 : if (!mCcx) {
1310 : mCcxToDestroy = mCcx =
1311 : new (mData) XPCCallContext(mCallerLanguage, mCx,
1312 : mCallBeginRequest == CALL_BEGINREQUEST,
1313 : mObj,
1314 : mFlattenedJSObject, mWrapper,
1315 129979 : mTearOff);
1316 129979 : if (!mCcx->IsValid()) {
1317 0 : NS_ERROR("This is not supposed to fail!");
1318 : }
1319 : }
1320 :
1321 5761675 : 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 7351529 : 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 7351529 : 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 17040280 : GetRuntime() const {return mRuntime;}
1509 :
1510 : Native2WrappedNativeMap*
1511 4572615 : GetWrappedNativeMap() const {return mWrappedNativeMap;}
1512 :
1513 : ClassInfo2WrappedNativeProtoMap*
1514 569668 : GetWrappedNativeProtoMap(JSBool aMainThreadOnly) const
1515 : {return aMainThreadOnly ?
1516 : mMainThreadWrappedNativeProtoMap :
1517 569668 : mWrappedNativeProtoMap;}
1518 :
1519 : nsXPCComponents*
1520 4547 : GetComponents() const {return mComponents;}
1521 :
1522 : JSObject*
1523 4963659 : GetGlobalJSObject() const {return mGlobalJSObject;}
1524 :
1525 : JSObject*
1526 3367083 : 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 2194253 : GetPrincipal() const
1535 : {return mScriptObjectPrincipal ?
1536 2194253 : 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 151223 : FindInJSObjectScope(XPCCallContext& ccx, JSObject* obj,
1547 : JSBool OKIfNotInitialized = false)
1548 : {
1549 : return FindInJSObjectScope(ccx, obj, OKIfNotInitialized,
1550 151223 : 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 1365 : static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; }
1604 :
1605 116145 : XPCContext *GetContext() { return mContext; }
1606 13749 : void SetContext(XPCContext *xpcc) { mContext = nsnull; }
1607 :
1608 19940 : nsDataHashtable<nsDepCharHashKey, JSObject*>& GetCachedDOMPrototypes()
1609 : {
1610 19940 : return mCachedDOMPrototypes;
1611 : }
1612 :
1613 766620 : static XPCWrappedNativeScope *GetNativeScope(JSObject *obj)
1614 : {
1615 766620 : MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_XPCONNECT_GLOBAL);
1616 :
1617 766620 : const js::Value &v = js::GetObjectSlot(obj, JSCLASS_GLOBAL_SLOT_COUNT);
1618 766620 : return v.isUndefined()
1619 : ? nsnull
1620 766620 : : 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 72276138 : jsid GetName() const {return mName;}
1687 :
1688 10721502 : PRUint16 GetIndex() const {return mIndex;}
1689 :
1690 20110 : JSBool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
1691 : jsval* pval)
1692 20110 : {NS_ASSERTION(IsConstant(),
1693 : "Only call this if you're sure this is a constant!");
1694 20110 : return Resolve(ccx, iface, nsnull, pval);}
1695 :
1696 : JSBool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface,
1697 : JSObject *parent, jsval* pval);
1698 :
1699 3408155 : JSBool IsMethod() const
1700 3408155 : {return 0 != (mFlags & METHOD);}
1701 :
1702 8338253 : JSBool IsConstant() const
1703 8338253 : {return 0 != (mFlags & CONSTANT);}
1704 :
1705 1190135 : JSBool IsAttribute() const
1706 1190135 : {return 0 != (mFlags & GETTER);}
1707 :
1708 1286007 : JSBool IsWritableAttribute() const
1709 1286007 : {return 0 != (mFlags & SETTER_TOO);}
1710 :
1711 172012 : JSBool IsReadOnlyAttribute() const
1712 172012 : {return IsAttribute() && !IsWritableAttribute();}
1713 :
1714 :
1715 1698385 : void SetName(jsid a) {mName = a;}
1716 :
1717 807763 : void SetMethod(PRUint16 index)
1718 807763 : {mFlags = METHOD; mIndex = index;}
1719 :
1720 388446 : void SetConstant(PRUint16 index)
1721 388446 : {mFlags = CONSTANT; mIndex = index;}
1722 :
1723 502176 : void SetReadOnlyAttribute(PRUint16 index)
1724 502176 : {mFlags = GETTER; mIndex = index;}
1725 :
1726 172012 : void SetWritableAttribute()
1727 172012 : {NS_ASSERTION(mFlags == GETTER,"bad"); mFlags = GETTER | SETTER_TOO;}
1728 :
1729 : /* default ctor - leave random contents */
1730 4684966 : XPCNativeMember() {MOZ_COUNT_CTOR(XPCNativeMember);}
1731 4684946 : ~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 8062748 : inline nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo.get();}
1769 12332354 : 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 299127 : PRUint16 GetMemberCount() const
1778 299127 : {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 547476 : void Mark() {mMemberCount |= XPC_NATIVE_IFACE_MARK_FLAG;}
1787 276244 : void Unmark() {mMemberCount &= ~XPC_NATIVE_IFACE_MARK_FLAG;}
1788 13846385 : JSBool IsMarked() const
1789 13846385 : {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 127133 : XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName)
1805 127133 : : mInfo(aInfo), mName(aName), mMemberCount(0)
1806 127133 : {MOZ_COUNT_CTOR(XPCNativeInterface);}
1807 127113 : ~XPCNativeInterface() {MOZ_COUNT_DTOR(XPCNativeInterface);}
1808 :
1809 127133 : 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 1156561 : XPCNativeSetKey(XPCNativeSet* BaseSet = nsnull,
1828 : XPCNativeInterface* Addition = nsnull,
1829 : PRUint16 Position = 0)
1830 : : mIsAKey(IS_A_KEY), mPosition(Position), mBaseSet(BaseSet),
1831 1156561 : mAddition(Addition) {}
1832 1156561 : ~XPCNativeSetKey() {}
1833 :
1834 2296604 : XPCNativeSet* GetBaseSet() const {return mBaseSet;}
1835 2296604 : XPCNativeInterface* GetAddition() const {return mAddition;}
1836 1447706 : 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 2296604 : 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 25589 : PRUint16 GetMemberCount() const {return mMemberCount;}
1908 2465851 : PRUint16 GetInterfaceCount() const
1909 2465851 : {NS_ASSERTION(!IsMarked(), "bad"); return mInterfaceCount;}
1910 695166 : XPCNativeInterface** GetInterfaceArray() {return mInterfaces;}
1911 :
1912 848896 : XPCNativeInterface* GetInterfaceAt(PRUint16 i)
1913 848896 : {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 221994 : void MarkSelfOnly() {mInterfaceCount |= XPC_NATIVE_SET_MARK_FLAG;}
1928 : public:
1929 221994 : void Unmark() {mInterfaceCount &= ~XPC_NATIVE_SET_MARK_FLAG;}
1930 13460477 : JSBool IsMarked() const
1931 13460477 : {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 192195 : XPCNativeSet() {MOZ_COUNT_CTOR(XPCNativeSet);}
1951 192183 : ~XPCNativeSet() {MOZ_COUNT_DTOR(XPCNativeSet);}
1952 192195 : 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 3170290 : XPCNativeScriptableFlags(uint32_t flags = 0) : mFlags(flags) {}
1977 :
1978 1413327 : uint32_t GetFlags() const {return mFlags & ~XPC_WN_SJSFLAGS_MARK_FLAG;}
1979 : void SetFlags(uint32_t flags) {mFlags = flags;}
1980 :
1981 974731 : operator uint32_t() const {return GetFlags();}
1982 :
1983 30286 : XPCNativeScriptableFlags(const XPCNativeScriptableFlags& r)
1984 30286 : {mFlags = r.GetFlags();}
1985 :
1986 408310 : XPCNativeScriptableFlags& operator= (const XPCNativeScriptableFlags& r)
1987 408310 : {mFlags = r.GetFlags(); return *this;}
1988 :
1989 5546109 : void Mark() {mFlags |= XPC_WN_SJSFLAGS_MARK_FLAG;}
1990 101003 : void Unmark() {mFlags &= ~XPC_WN_SJSFLAGS_MARK_FLAG;}
1991 121879 : 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 1477223 : JSBool WantPreCreate() GET_IT(WANT_PRECREATE)
1999 298008 : JSBool WantCreate() GET_IT(WANT_CREATE)
2000 298008 : JSBool WantPostCreate() GET_IT(WANT_POSTCREATE)
2001 20993 : JSBool WantAddProperty() GET_IT(WANT_ADDPROPERTY)
2002 20993 : JSBool WantDelProperty() GET_IT(WANT_DELPROPERTY)
2003 20993 : JSBool WantGetProperty() GET_IT(WANT_GETPROPERTY)
2004 20993 : JSBool WantSetProperty() GET_IT(WANT_SETPROPERTY)
2005 16219 : JSBool WantEnumerate() GET_IT(WANT_ENUMERATE)
2006 21310 : JSBool WantNewEnumerate() GET_IT(WANT_NEWENUMERATE)
2007 1577265 : JSBool WantNewResolve() GET_IT(WANT_NEWRESOLVE)
2008 20993 : JSBool WantConvert() GET_IT(WANT_CONVERT)
2009 20993 : JSBool WantFinalize() GET_IT(WANT_FINALIZE)
2010 20993 : JSBool WantCheckAccess() GET_IT(WANT_CHECKACCESS)
2011 40761 : JSBool WantCall() GET_IT(WANT_CALL)
2012 22637 : JSBool WantConstruct() GET_IT(WANT_CONSTRUCT)
2013 20993 : JSBool WantHasInstance() GET_IT(WANT_HASINSTANCE)
2014 1439 : JSBool WantEquality() GET_IT(WANT_EQUALITY)
2015 20993 : JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT)
2016 19203 : JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY)
2017 20990 : JSBool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY)
2018 19126 : JSBool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY)
2019 520786 : JSBool DontEnumStaticProps() GET_IT(DONT_ENUM_STATIC_PROPS)
2020 277891 : JSBool DontEnumQueryInterface() GET_IT(DONT_ENUM_QUERY_INTERFACE)
2021 623075 : JSBool DontAskInstanceForScriptable() GET_IT(DONT_ASK_INSTANCE_FOR_SCRIPTABLE)
2022 608208 : JSBool ClassInfoInterfacesOnly() GET_IT(CLASSINFO_INTERFACES_ONLY)
2023 1888415 : JSBool AllowPropModsDuringResolve() GET_IT(ALLOW_PROP_MODS_DURING_RESOLVE)
2024 256329 : JSBool AllowPropModsToPrototype() GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE)
2025 299764 : JSBool IsGlobalObject() GET_IT(IS_GLOBAL_OBJECT)
2026 25392 : JSBool DontReflectInterfaceNames() GET_IT(DONT_REFLECT_INTERFACE_NAMES)
2027 20993 : 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 5149411 : const XPCNativeScriptableFlags& GetFlags() const {return mFlags;}
2055 455876 : PRUint32 GetInterfacesBitmap() const
2056 455876 : {return mJSClass.interfacesBitmap;}
2057 2957503 : JSClass* GetJSClass()
2058 2957503 : {return Jsvalify(&mJSClass.base);}
2059 15143 : JSClass* GetSlimJSClass()
2060 15143 : {if (mCanBeSlim) return GetJSClass(); return nsnull;}
2061 :
2062 269924 : XPCNativeScriptableShared(uint32_t aFlags, char* aName,
2063 : PRUint32 interfacesBitmap)
2064 : : mFlags(aFlags),
2065 269924 : mCanBeSlim(false)
2066 269924 : {memset(&mJSClass, 0, sizeof(mJSClass));
2067 269924 : mJSClass.base.name = aName; // take ownership
2068 269924 : mJSClass.interfacesBitmap = interfacesBitmap;
2069 269924 : MOZ_COUNT_CTOR(XPCNativeScriptableShared);}
2070 :
2071 269807 : ~XPCNativeScriptableShared()
2072 269807 : {if (mJSClass.base.name)nsMemory::Free((void*)mJSClass.base.name);
2073 269807 : MOZ_COUNT_DTOR(XPCNativeScriptableShared);}
2074 :
2075 20993 : char* TransferNameOwnership()
2076 20993 : {char* name=(char*)mJSClass.base.name; mJSClass.base.name = nsnull;
2077 20993 : return name;}
2078 :
2079 : void PopulateJSClass();
2080 :
2081 5546109 : void Mark() {mFlags.Mark();}
2082 101003 : void Unmark() {mFlags.Unmark();}
2083 121879 : 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 2102725 : GetCallback() const {return mCallback;}
2103 :
2104 : const XPCNativeScriptableFlags&
2105 4444604 : GetFlags() const {return mShared->GetFlags();}
2106 :
2107 : PRUint32
2108 0 : GetInterfacesBitmap() const {return mShared->GetInterfacesBitmap();}
2109 :
2110 : JSClass*
2111 2237553 : GetJSClass() {return mShared->GetJSClass();}
2112 :
2113 : JSClass*
2114 15143 : 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 248931 : SetScriptableShared(XPCNativeScriptableShared* shared) {mShared = shared;}
2126 :
2127 5546109 : void Mark() {if (mShared) mShared->Mark();}
2128 :
2129 : protected:
2130 248931 : XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nsnull,
2131 : XPCNativeScriptableShared* shared = nsnull)
2132 248931 : : mCallback(scriptable), mShared(shared)
2133 248931 : {MOZ_COUNT_CTOR(XPCNativeScriptableInfo);}
2134 : public:
2135 248882 : ~XPCNativeScriptableInfo() {MOZ_COUNT_DTOR(XPCNativeScriptableInfo);}
2136 : private:
2137 :
2138 : // disable copy ctor and assignment
2139 : XPCNativeScriptableInfo(const XPCNativeScriptableInfo& r); // not implemented
2140 : XPCNativeScriptableInfo& operator= (const XPCNativeScriptableInfo& r); // not implemented
2141 :
2142 : private:
2143 : nsCOMPtr<nsIXPCScriptable> mCallback;
2144 : XPCNativeScriptableShared* mShared;
2145 : };
2146 :
2147 : /***************************************************************************/
2148 : // XPCNativeScriptableCreateInfo is used in creating new wrapper and protos.
2149 : // it abstracts out the scriptable interface pointer and the flags. After
2150 : // creation these are factored differently using XPCNativeScriptableInfo.
2151 :
2152 : class NS_STACK_CLASS XPCNativeScriptableCreateInfo
2153 2487087 : {
2154 : public:
2155 :
2156 0 : XPCNativeScriptableCreateInfo(const XPCNativeScriptableInfo& si)
2157 0 : : mCallback(si.GetCallback()), mFlags(si.GetFlags()),
2158 0 : mInterfacesBitmap(si.GetInterfacesBitmap()) {}
2159 :
2160 15143 : XPCNativeScriptableCreateInfo(already_AddRefed<nsIXPCScriptable> callback,
2161 : XPCNativeScriptableFlags flags,
2162 : PRUint32 interfacesBitmap)
2163 : : mCallback(callback), mFlags(flags),
2164 15143 : mInterfacesBitmap(interfacesBitmap) {}
2165 :
2166 2471944 : XPCNativeScriptableCreateInfo()
2167 2471944 : : mFlags(0), mInterfacesBitmap(0) {}
2168 :
2169 :
2170 : nsIXPCScriptable*
2171 4065571 : GetCallback() const {return mCallback;}
2172 :
2173 : const XPCNativeScriptableFlags&
2174 3806814 : GetFlags() const {return mFlags;}
2175 :
2176 : PRUint32
2177 248931 : GetInterfacesBitmap() const {return mInterfacesBitmap;}
2178 :
2179 : void
2180 382918 : SetCallback(already_AddRefed<nsIXPCScriptable> callback)
2181 382918 : {mCallback = callback;}
2182 :
2183 : void
2184 382918 : SetFlags(const XPCNativeScriptableFlags& flags) {mFlags = flags;}
2185 :
2186 : void
2187 12398 : SetInterfacesBitmap(PRUint32 interfacesBitmap)
2188 12398 : {mInterfacesBitmap = interfacesBitmap;}
2189 :
2190 : private:
2191 : nsCOMPtr<nsIXPCScriptable> mCallback;
2192 : XPCNativeScriptableFlags mFlags;
2193 : PRUint32 mInterfacesBitmap;
2194 : };
2195 :
2196 : /***********************************************/
2197 : // XPCWrappedNativeProto hold the additional shared wrapper data
2198 : // for XPCWrappedNative whose native objects expose nsIClassInfo.
2199 :
2200 : #define UNKNOWN_OFFSETS ((QITableEntry*)1)
2201 :
2202 : class XPCWrappedNativeProto
2203 : {
2204 : public:
2205 : static XPCWrappedNativeProto*
2206 : GetNewOrUsed(XPCCallContext& ccx,
2207 : XPCWrappedNativeScope* scope,
2208 : nsIClassInfo* classInfo,
2209 : const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
2210 : QITableEntry* offsets = UNKNOWN_OFFSETS,
2211 : bool callPostCreatePrototype = true);
2212 :
2213 : XPCWrappedNativeScope*
2214 9295603 : GetScope() const {return mScope;}
2215 :
2216 : XPCJSRuntime*
2217 6322849 : GetRuntime() const {return mScope->GetRuntime();}
2218 :
2219 : JSObject*
2220 396972 : GetJSProtoObject() const {return mJSProtoObject;}
2221 :
2222 : nsIClassInfo*
2223 4085857 : GetClassInfo() const {return mClassInfo;}
2224 :
2225 : XPCNativeSet*
2226 3142708 : GetSet() const {return mSet;}
2227 :
2228 : XPCNativeScriptableInfo*
2229 1726420 : GetScriptableInfo() {return mScriptableInfo;}
2230 :
2231 : void**
2232 2236884 : GetSecurityInfoAddr() {return &mSecurityInfo;}
2233 :
2234 : uint32_t
2235 : GetClassInfoFlags() const {return mClassInfoFlags;}
2236 :
2237 : QITableEntry*
2238 34995 : GetOffsets()
2239 : {
2240 34995 : return InitedOffsets() ? mOffsets : nsnull;
2241 : }
2242 : QITableEntry*
2243 0 : GetOffsetsMasked()
2244 : {
2245 0 : return mOffsets;
2246 : }
2247 : void
2248 383800 : CacheOffsets(nsISupports* identity)
2249 : {
2250 : static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
2251 :
2252 : #ifdef DEBUG
2253 383800 : if (InitedOffsets() && mOffsets) {
2254 : QITableEntry* offsets;
2255 13248 : identity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
2256 13248 : NS_ASSERTION(offsets == mOffsets,
2257 : "We can't deal with objects that have the same "
2258 : "classinfo but different offset tables.");
2259 : }
2260 : #endif
2261 :
2262 383800 : if (!InitedOffsets()) {
2263 186009 : if (mClassInfoFlags & nsIClassInfo::CONTENT_NODE) {
2264 897 : identity->QueryInterface(kThisPtrOffsetsSID, (void**)&mOffsets);
2265 : } else {
2266 185112 : mOffsets = nsnull;
2267 : }
2268 : }
2269 383800 : }
2270 :
2271 : #ifdef GET_IT
2272 : #undef GET_IT
2273 : #endif
2274 : #define GET_IT(f_) const {return !!(mClassInfoFlags & nsIClassInfo:: f_ );}
2275 :
2276 : JSBool ClassIsSingleton() GET_IT(SINGLETON)
2277 11469290 : JSBool ClassIsThreadSafe() GET_IT(THREADSAFE)
2278 1179421 : JSBool ClassIsMainThreadOnly() GET_IT(MAIN_THREAD_ONLY)
2279 32115 : JSBool ClassIsDOMObject() GET_IT(DOM_OBJECT)
2280 : JSBool ClassIsPluginObject() GET_IT(PLUGIN_OBJECT)
2281 :
2282 : #undef GET_IT
2283 :
2284 7149327 : XPCLock* GetLock() const
2285 7149327 : {return ClassIsThreadSafe() ? GetRuntime()->GetMapLock() : nsnull;}
2286 :
2287 : void SetScriptableInfo(XPCNativeScriptableInfo* si)
2288 : {NS_ASSERTION(!mScriptableInfo, "leak here!"); mScriptableInfo = si;}
2289 :
2290 : bool CallPostCreatePrototype(XPCCallContext& ccx);
2291 : void JSProtoObjectFinalized(JSContext *cx, JSObject *obj);
2292 :
2293 : void SystemIsBeingShutDown();
2294 :
2295 : void DebugDump(PRInt16 depth);
2296 :
2297 1902633 : void TraceJS(JSTracer* trc)
2298 : {
2299 1902633 : if (mJSProtoObject) {
2300 1902633 : JS_CALL_OBJECT_TRACER(trc, mJSProtoObject,
2301 : "XPCWrappedNativeProto::mJSProtoObject");
2302 : }
2303 1902633 : if (mScriptableInfo && JS_IsGCMarkingTracer(trc))
2304 821588 : mScriptableInfo->Mark();
2305 1902633 : }
2306 :
2307 0 : void WriteBarrierPre(JSRuntime* rt)
2308 : {
2309 0 : if (js::IsIncrementalBarrierNeeded(rt) && mJSProtoObject)
2310 0 : mJSProtoObject.writeBarrierPre(rt);
2311 0 : }
2312 :
2313 : // NOP. This is just here to make the AutoMarkingPtr code compile.
2314 0 : inline void AutoTrace(JSTracer* trc) {}
2315 :
2316 : // Yes, we *do* need to mark the mScriptableInfo in both cases.
2317 2735029 : void Mark() const
2318 2735029 : {mSet->Mark();
2319 2735029 : if (mScriptableInfo) mScriptableInfo->Mark();}
2320 :
2321 : #ifdef DEBUG
2322 2735029 : void ASSERT_SetNotMarked() const {mSet->ASSERT_NotMarked();}
2323 : #endif
2324 :
2325 : ~XPCWrappedNativeProto();
2326 :
2327 : protected:
2328 : // disable copy ctor and assignment
2329 : XPCWrappedNativeProto(const XPCWrappedNativeProto& r); // not implemented
2330 : XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r); // not implemented
2331 :
2332 : // hide ctor
2333 : XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
2334 : nsIClassInfo* ClassInfo,
2335 : PRUint32 ClassInfoFlags,
2336 : XPCNativeSet* Set,
2337 : QITableEntry* offsets);
2338 :
2339 : JSBool Init(XPCCallContext& ccx,
2340 : const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
2341 : bool callPostCreatePrototype);
2342 :
2343 : private:
2344 : #if defined(DEBUG_xpc_hacker) || defined(DEBUG)
2345 : static PRInt32 gDEBUG_LiveProtoCount;
2346 : #endif
2347 :
2348 : private:
2349 : bool
2350 802595 : InitedOffsets()
2351 : {
2352 802595 : return mOffsets != UNKNOWN_OFFSETS;
2353 : }
2354 :
2355 : XPCWrappedNativeScope* mScope;
2356 : js::ObjectPtr mJSProtoObject;
2357 : nsCOMPtr<nsIClassInfo> mClassInfo;
2358 : PRUint32 mClassInfoFlags;
2359 : XPCNativeSet* mSet;
2360 : void* mSecurityInfo;
2361 : XPCNativeScriptableInfo* mScriptableInfo;
2362 : QITableEntry* mOffsets;
2363 : };
2364 :
2365 : class xpcObjectHelper;
2366 : extern JSBool ConstructSlimWrapper(XPCCallContext &ccx,
2367 : xpcObjectHelper &aHelper,
2368 : XPCWrappedNativeScope* xpcScope,
2369 : jsval *rval);
2370 : extern JSBool MorphSlimWrapper(JSContext *cx, JSObject *obj);
2371 :
2372 : static inline XPCWrappedNativeProto*
2373 35406 : GetSlimWrapperProto(JSObject *obj)
2374 : {
2375 35406 : const js::Value &v = js::GetReservedSlot(obj, 0);
2376 35406 : return static_cast<XPCWrappedNativeProto*>(v.toPrivate());
2377 : }
2378 :
2379 :
2380 : /***********************************************/
2381 : // XPCWrappedNativeTearOff represents the info needed to make calls to one
2382 : // interface on the underlying native object of a XPCWrappedNative.
2383 :
2384 : class XPCWrappedNativeTearOff
2385 : {
2386 : public:
2387 2212418 : JSBool IsAvailable() const {return mInterface == nsnull;}
2388 : JSBool IsReserved() const {return mInterface == (XPCNativeInterface*)1;}
2389 : JSBool IsValid() const {return !IsAvailable() && !IsReserved();}
2390 1504858 : void SetReserved() {mInterface = (XPCNativeInterface*)1;}
2391 :
2392 19021631 : XPCNativeInterface* GetInterface() const {return mInterface;}
2393 12776268 : nsISupports* GetNative() const {return mNative;}
2394 : JSObject* GetJSObject();
2395 : JSObject* GetJSObjectPreserveColor() const;
2396 5486559 : void SetInterface(XPCNativeInterface* Interface) {mInterface = Interface;}
2397 3008342 : void SetNative(nsISupports* Native) {mNative = Native;}
2398 : void SetJSObject(JSObject* JSObj);
2399 :
2400 60 : void JSObjectFinalized() {SetJSObject(nsnull);}
2401 :
2402 1424036 : XPCWrappedNativeTearOff()
2403 1424036 : : mInterface(nsnull), mNative(nsnull), mJSObject(nsnull) {}
2404 : ~XPCWrappedNativeTearOff();
2405 :
2406 : // NOP. This is just here to make the AutoMarkingPtr code compile.
2407 0 : inline void TraceJS(JSTracer* trc) {}
2408 0 : inline void AutoTrace(JSTracer* trc) {}
2409 :
2410 3898 : void Mark() {mJSObject = (JSObject*)(intptr_t(mJSObject) | 1);}
2411 4071535 : void Unmark() {mJSObject = (JSObject*)(intptr_t(mJSObject) & ~1);}
2412 2561657 : bool IsMarked() const {return !!(intptr_t(mJSObject) & 1);}
2413 :
2414 : private:
2415 : XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) MOZ_DELETE;
2416 : XPCWrappedNativeTearOff& operator= (const XPCWrappedNativeTearOff& r) MOZ_DELETE;
2417 :
2418 : private:
2419 : XPCNativeInterface* mInterface;
2420 : nsISupports* mNative;
2421 : JSObject* mJSObject;
2422 : };
2423 :
2424 : /***********************************************/
2425 : // XPCWrappedNativeTearOffChunk is a collections of XPCWrappedNativeTearOff
2426 : // objects. It lets us allocate a set of XPCWrappedNativeTearOff objects and
2427 : // link the sets - rather than only having the option of linking single
2428 : // XPCWrappedNativeTearOff objects.
2429 : //
2430 : // The value of XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK can be tuned at buildtime
2431 : // to balance between the code of allocations of additional chunks and the waste
2432 : // of space for ununsed XPCWrappedNativeTearOff objects.
2433 :
2434 : #define XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK 1
2435 :
2436 : class XPCWrappedNativeTearOffChunk
2437 : {
2438 : friend class XPCWrappedNative;
2439 : private:
2440 1424036 : XPCWrappedNativeTearOffChunk() : mNextChunk(nsnull) {}
2441 2846444 : ~XPCWrappedNativeTearOffChunk() {delete mNextChunk;}
2442 :
2443 : private:
2444 : XPCWrappedNativeTearOff mTearOffs[XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK];
2445 : XPCWrappedNativeTearOffChunk* mNextChunk;
2446 : };
2447 :
2448 : void *xpc_GetJSPrivate(JSObject *obj);
2449 :
2450 : /***************************************************************************/
2451 : // XPCWrappedNative the wrapper around one instance of a native xpcom object
2452 : // to be used from JavaScript.
2453 :
2454 : class XPCWrappedNative : public nsIXPConnectWrappedNative
2455 : {
2456 : public:
2457 : NS_DECL_ISUPPORTS
2458 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
2459 : NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
2460 : // No need to unlink the JS objects, if the XPCWrappedNative will be cycle
2461 : // collected then its mFlatJSObject will be cycle collected too and
2462 : // finalization of the mFlatJSObject will unlink the js objects (see
2463 : // XPC_WN_NoHelper_Finalize and FlatJSObjectFinalized).
2464 : // We also give XPCWrappedNative empty Root/Unroot methods, to avoid
2465 : // root/unrooting the JS objects from addrefing/releasing the
2466 : // XPCWrappedNative during unlinking, which would make the JS objects
2467 : // uncollectable to the JS GC.
2468 : class NS_CYCLE_COLLECTION_INNERCLASS
2469 : : public nsXPCOMCycleCollectionParticipant
2470 1396 : {
2471 365 : NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(XPCWrappedNative,
2472 : XPCWrappedNative)
2473 322 : NS_IMETHOD Root(void *p) { return NS_OK; }
2474 : NS_IMETHOD Unlink(void *p);
2475 322 : NS_IMETHOD Unroot(void *p) { return NS_OK; }
2476 : };
2477 : NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
2478 0 : NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(XPCWrappedNative)
2479 :
2480 : nsIPrincipal* GetObjectPrincipal() const;
2481 :
2482 : JSBool
2483 49586206 : IsValid() const {return nsnull != mFlatJSObject;}
2484 :
2485 : #define XPC_SCOPE_WORD(s) (intptr_t(s))
2486 : #define XPC_SCOPE_MASK (intptr_t(0x3))
2487 : #define XPC_SCOPE_TAG (intptr_t(0x1))
2488 : #define XPC_WRAPPER_EXPIRED (intptr_t(0x2))
2489 :
2490 : static inline JSBool
2491 113479713 : IsTaggedScope(XPCWrappedNativeScope* s)
2492 113479713 : {return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;}
2493 :
2494 : static inline XPCWrappedNativeScope*
2495 867315 : TagScope(XPCWrappedNativeScope* s)
2496 867315 : {NS_ASSERTION(!IsTaggedScope(s), "bad pointer!");
2497 867315 : return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) | XPC_SCOPE_TAG);}
2498 :
2499 : static inline XPCWrappedNativeScope*
2500 : UnTagScope(XPCWrappedNativeScope* s)
2501 : {return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) & ~XPC_SCOPE_TAG);}
2502 :
2503 : inline JSBool
2504 1256286 : IsWrapperExpired() const
2505 1256286 : {return XPC_SCOPE_WORD(mMaybeScope) & XPC_WRAPPER_EXPIRED;}
2506 :
2507 : JSBool
2508 112612398 : HasProto() const {return !IsTaggedScope(mMaybeScope);}
2509 :
2510 : XPCWrappedNativeProto*
2511 58164994 : GetProto() const
2512 58164994 : {return HasProto() ?
2513 : (XPCWrappedNativeProto*)
2514 58164994 : (XPC_SCOPE_WORD(mMaybeProto) & ~XPC_SCOPE_MASK) : nsnull;}
2515 :
2516 : void SetProto(XPCWrappedNativeProto* p);
2517 :
2518 : XPCWrappedNativeScope*
2519 14787718 : GetScope() const
2520 21833501 : {return GetProto() ? GetProto()->GetScope() :
2521 : (XPCWrappedNativeScope*)
2522 21833501 : (XPC_SCOPE_WORD(mMaybeScope) & ~XPC_SCOPE_MASK);}
2523 :
2524 : nsISupports*
2525 13942223 : GetIdentityObject() const {return mIdentity;}
2526 :
2527 : /**
2528 : * This getter clears the gray bit before handing out the JSObject which
2529 : * means that the object is guaranteed to be kept alive past the next CC.
2530 : */
2531 : JSObject*
2532 16722835 : GetFlatJSObject() const
2533 16722835 : {if (mFlatJSObject != INVALID_OBJECT)
2534 16722835 : xpc_UnmarkGrayObject(mFlatJSObject);
2535 16722835 : return mFlatJSObject;}
2536 :
2537 : /**
2538 : * This getter does not change the color of the JSObject meaning that the
2539 : * object returned is not guaranteed to be kept alive past the next CC.
2540 : *
2541 : * This should only be called if you are certain that the return value won't
2542 : * be passed into a JS API function and that it won't be stored without
2543 : * being rooted (or otherwise signaling the stored value to the CC).
2544 : */
2545 : JSObject*
2546 15060 : GetFlatJSObjectPreserveColor() const {return mFlatJSObject;}
2547 :
2548 : XPCLock*
2549 46710080 : GetLock() const {return IsValid() && HasProto() ?
2550 46710080 : GetProto()->GetLock() : nsnull;}
2551 :
2552 : XPCNativeSet*
2553 12350517 : GetSet() const {XPCAutoLock al(GetLock()); return mSet;}
2554 :
2555 : void
2556 158 : SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;}
2557 :
2558 : private:
2559 : inline void
2560 322 : ExpireWrapper()
2561 : {mMaybeScope = (XPCWrappedNativeScope*)
2562 322 : (XPC_SCOPE_WORD(mMaybeScope) | XPC_WRAPPER_EXPIRED);}
2563 :
2564 : public:
2565 :
2566 : XPCNativeScriptableInfo*
2567 15275550 : GetScriptableInfo() const {return mScriptableInfo;}
2568 :
2569 : nsIXPCScriptable* // call this wrong and you deserve to crash
2570 506347 : GetScriptableCallback() const {return mScriptableInfo->GetCallback();}
2571 :
2572 : void**
2573 8323300 : GetSecurityInfoAddr() {return HasProto() ?
2574 8323300 : GetProto()->GetSecurityInfoAddr() : nsnull;}
2575 :
2576 : nsIClassInfo*
2577 16648720 : GetClassInfo() const {return IsValid() && HasProto() ?
2578 16648720 : GetProto()->GetClassInfo() : nsnull;}
2579 :
2580 : JSBool
2581 1348573 : HasMutatedSet() const {return IsValid() &&
2582 1348573 : (!HasProto() ||
2583 2697146 : GetSet() != GetProto()->GetSet());}
2584 :
2585 : XPCJSRuntime*
2586 4983576 : GetRuntime() const {XPCWrappedNativeScope* scope = GetScope();
2587 4983576 : return scope ? scope->GetRuntime() : nsnull;}
2588 :
2589 : static nsresult
2590 : WrapNewGlobal(XPCCallContext &ccx, xpcObjectHelper &nativeHelper,
2591 : nsIPrincipal *principal, bool initStandardClasses,
2592 : XPCWrappedNative **wrappedGlobal);
2593 :
2594 : static nsresult
2595 : GetNewOrUsed(XPCCallContext& ccx,
2596 : xpcObjectHelper& helper,
2597 : XPCWrappedNativeScope* Scope,
2598 : XPCNativeInterface* Interface,
2599 : XPCWrappedNative** wrapper);
2600 :
2601 : static nsresult
2602 : Morph(XPCCallContext& ccx,
2603 : JSObject* existingJSObject,
2604 : XPCNativeInterface* Interface,
2605 : nsWrapperCache *cache,
2606 : XPCWrappedNative** resultWrapper);
2607 :
2608 : public:
2609 : static nsresult
2610 : GetUsedOnly(XPCCallContext& ccx,
2611 : nsISupports* Object,
2612 : XPCWrappedNativeScope* Scope,
2613 : XPCNativeInterface* Interface,
2614 : XPCWrappedNative** wrapper);
2615 :
2616 : // If pobj2 is not null and *pobj2 is not null after the call then *pobj2
2617 : // points to an object for which IS_SLIM_WRAPPER_OBJECT is true.
2618 : // cx is null when invoked from the marking phase of the GC. In this case
2619 : // fubobj must be null as well.
2620 : static XPCWrappedNative*
2621 : GetWrappedNativeOfJSObject(JSContext* cx, JSObject* obj,
2622 : JSObject* funobj = nsnull,
2623 : JSObject** pobj2 = nsnull,
2624 : XPCWrappedNativeTearOff** pTearOff = nsnull);
2625 : static XPCWrappedNative*
2626 237391 : GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj)
2627 : {
2628 237391 : JSObject *obj2 = nsnull;
2629 : XPCWrappedNative* wrapper =
2630 237391 : GetWrappedNativeOfJSObject(cx, obj, nsnull, &obj2);
2631 237391 : if (wrapper || !obj2)
2632 237391 : return wrapper;
2633 :
2634 0 : NS_ASSERTION(IS_SLIM_WRAPPER(obj2),
2635 : "Hmm, someone changed GetWrappedNativeOfJSObject?");
2636 : SLIM_LOG_WILL_MORPH(cx, obj2);
2637 0 : return MorphSlimWrapper(cx, obj2) ?
2638 0 : (XPCWrappedNative*)xpc_GetJSPrivate(obj2) :
2639 0 : nsnull;
2640 : }
2641 :
2642 : static nsresult
2643 : ReparentWrapperIfFound(XPCCallContext& ccx,
2644 : XPCWrappedNativeScope* aOldScope,
2645 : XPCWrappedNativeScope* aNewScope,
2646 : JSObject* aNewParent,
2647 : nsISupports* aCOMObj,
2648 : XPCWrappedNative** aWrapper);
2649 :
2650 : void FlatJSObjectFinalized();
2651 :
2652 : void SystemIsBeingShutDown();
2653 :
2654 : enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
2655 :
2656 : static JSBool CallMethod(XPCCallContext& ccx,
2657 : CallMode mode = CALL_METHOD);
2658 :
2659 2331607 : static JSBool GetAttribute(XPCCallContext& ccx)
2660 2331607 : {return CallMethod(ccx, CALL_GETTER);}
2661 :
2662 95872 : static JSBool SetAttribute(XPCCallContext& ccx)
2663 95872 : {return CallMethod(ccx, CALL_SETTER);}
2664 :
2665 : inline JSBool HasInterfaceNoQI(const nsIID& iid);
2666 :
2667 : XPCWrappedNativeTearOff* LocateTearOff(XPCCallContext& ccx,
2668 : XPCNativeInterface* aInterface);
2669 : XPCWrappedNativeTearOff* FindTearOff(XPCCallContext& ccx,
2670 : XPCNativeInterface* aInterface,
2671 : JSBool needJSObject = false,
2672 : nsresult* pError = nsnull);
2673 2232933 : void Mark() const
2674 : {
2675 2232933 : mSet->Mark();
2676 2232933 : if (mScriptableInfo) mScriptableInfo->Mark();
2677 2232933 : if (HasProto()) GetProto()->Mark();
2678 2232933 : }
2679 :
2680 : // Yes, we *do* need to mark the mScriptableInfo in both cases.
2681 2287106 : inline void TraceJS(JSTracer* trc)
2682 : {
2683 2287106 : if (mScriptableInfo && JS_IsGCMarkingTracer(trc))
2684 1898151 : mScriptableInfo->Mark();
2685 2287106 : if (HasProto()) GetProto()->TraceJS(trc);
2686 2287106 : JSObject* wrapper = GetWrapperPreserveColor();
2687 2287106 : if (wrapper)
2688 0 : JS_CALL_OBJECT_TRACER(trc, wrapper, "XPCWrappedNative::mWrapper");
2689 4232415 : if (mScriptableInfo &&
2690 1945309 : (mScriptableInfo->GetJSClass()->flags & JSCLASS_XPCONNECT_GLOBAL))
2691 134677 : TraceXPCGlobal(trc, mFlatJSObject);
2692 :
2693 2287106 : }
2694 :
2695 0 : inline void AutoTrace(JSTracer* trc)
2696 : {
2697 : // If this got called, we're being kept alive by someone who really
2698 : // needs us alive and whole. Do not let our mFlatJSObject go away.
2699 : // This is the only time we should be tracing our mFlatJSObject,
2700 : // normally somebody else is doing that. Be careful not to trace the
2701 : // bogus INVALID_OBJECT value we can have during init, though.
2702 0 : if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT) {
2703 0 : JS_CALL_OBJECT_TRACER(trc, mFlatJSObject,
2704 : "XPCWrappedNative::mFlatJSObject");
2705 : }
2706 0 : }
2707 :
2708 : #ifdef DEBUG
2709 2232933 : void ASSERT_SetsNotMarked() const
2710 2232933 : {mSet->ASSERT_NotMarked();
2711 2232933 : if (HasProto()){GetProto()->ASSERT_SetNotMarked();}}
2712 :
2713 : int DEBUG_CountOfTearoffChunks() const
2714 : {int i = 0; const XPCWrappedNativeTearOffChunk* to;
2715 : for (to = &mFirstChunk; to; to = to->mNextChunk) {i++;} return i;}
2716 : #endif
2717 :
2718 : inline void SweepTearOffs();
2719 :
2720 : // Returns a string that shuld be free'd using JS_smprintf_free (or null).
2721 : char* ToString(XPCCallContext& ccx,
2722 : XPCWrappedNativeTearOff* to = nsnull) const;
2723 :
2724 : static void GatherProtoScriptableCreateInfo(nsIClassInfo* classInfo,
2725 : XPCNativeScriptableCreateInfo& sciProto);
2726 :
2727 3876890 : JSBool HasExternalReference() const {return mRefCnt > 1;}
2728 :
2729 1554521 : JSBool NeedsSOW() { return !!(mWrapperWord & NEEDS_SOW); }
2730 0 : void SetNeedsSOW() { mWrapperWord |= NEEDS_SOW; }
2731 : JSBool NeedsCOW() { return !!(mWrapperWord & NEEDS_COW); }
2732 0 : void SetNeedsCOW() { mWrapperWord |= NEEDS_COW; }
2733 365 : JSBool MightHaveExpandoObject() { return !!(mWrapperWord & MIGHT_HAVE_EXPANDO); }
2734 0 : void SetHasExpandoObject() { mWrapperWord |= MIGHT_HAVE_EXPANDO; }
2735 :
2736 2287106 : JSObject* GetWrapperPreserveColor() const
2737 2287106 : {return (JSObject*)(mWrapperWord & (size_t)~(size_t)FLAG_MASK);}
2738 :
2739 0 : JSObject* GetWrapper()
2740 : {
2741 0 : JSObject* wrapper = GetWrapperPreserveColor();
2742 0 : if (wrapper) {
2743 0 : xpc_UnmarkGrayObject(wrapper);
2744 : // Call this to unmark mFlatJSObject.
2745 0 : GetFlatJSObject();
2746 : }
2747 0 : return wrapper;
2748 : }
2749 0 : void SetWrapper(JSObject *obj)
2750 : {
2751 0 : js::IncrementalReferenceBarrier(GetWrapperPreserveColor());
2752 0 : PRWord newval = PRWord(obj) | (mWrapperWord & FLAG_MASK);
2753 0 : mWrapperWord = newval;
2754 0 : }
2755 :
2756 : void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
2757 :
2758 32115 : QITableEntry* GetOffsets()
2759 : {
2760 32115 : if (!HasProto() || !GetProto()->ClassIsDOMObject())
2761 0 : return nsnull;
2762 :
2763 32115 : XPCWrappedNativeProto* proto = GetProto();
2764 32115 : QITableEntry* offsets = proto->GetOffsets();
2765 32115 : if (!offsets) {
2766 : static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
2767 30192 : mIdentity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
2768 : }
2769 32115 : return offsets;
2770 : }
2771 :
2772 : // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
2773 : protected:
2774 : XPCWrappedNative(); // not implemented
2775 :
2776 : // This ctor is used if this object will have a proto.
2777 : XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
2778 : XPCWrappedNativeProto* aProto);
2779 :
2780 : // This ctor is used if this object will NOT have a proto.
2781 : XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
2782 : XPCWrappedNativeScope* aScope,
2783 : XPCNativeSet* aSet);
2784 :
2785 : virtual ~XPCWrappedNative();
2786 : void Destroy();
2787 :
2788 : void UpdateScriptableInfo(XPCNativeScriptableInfo *si);
2789 :
2790 : private:
2791 : enum {
2792 : NEEDS_SOW = JS_BIT(0),
2793 : NEEDS_COW = JS_BIT(1),
2794 : MIGHT_HAVE_EXPANDO = JS_BIT(2),
2795 : FLAG_MASK = JS_BITMASK(3)
2796 : };
2797 :
2798 : private:
2799 :
2800 : JSBool Init(XPCCallContext& ccx, JSObject* parent, const XPCNativeScriptableCreateInfo* sci);
2801 : JSBool Init(XPCCallContext &ccx, JSObject *existingJSObject);
2802 : JSBool FinishInit(XPCCallContext &ccx);
2803 :
2804 : JSBool ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface);
2805 :
2806 : nsresult InitTearOff(XPCCallContext& ccx,
2807 : XPCWrappedNativeTearOff* aTearOff,
2808 : XPCNativeInterface* aInterface,
2809 : JSBool needJSObject);
2810 :
2811 : JSBool InitTearOffJSObject(XPCCallContext& ccx,
2812 : XPCWrappedNativeTearOff* to);
2813 :
2814 : public:
2815 : static const XPCNativeScriptableCreateInfo& GatherScriptableCreateInfo(nsISupports* obj,
2816 : nsIClassInfo* classInfo,
2817 : XPCNativeScriptableCreateInfo& sciProto,
2818 : XPCNativeScriptableCreateInfo& sciWrapper);
2819 :
2820 : private:
2821 : union
2822 : {
2823 : XPCWrappedNativeScope* mMaybeScope;
2824 : XPCWrappedNativeProto* mMaybeProto;
2825 : };
2826 : XPCNativeSet* mSet;
2827 : JSObject* mFlatJSObject;
2828 : XPCNativeScriptableInfo* mScriptableInfo;
2829 : XPCWrappedNativeTearOffChunk mFirstChunk;
2830 : PRWord mWrapperWord;
2831 :
2832 : #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
2833 : public:
2834 : // Don't want to overload _mOwningThread
2835 : PRThread* mThread;
2836 : #endif
2837 : };
2838 :
2839 : /***************************************************************************
2840 : ****************************************************************************
2841 : *
2842 : * Core classes for wrapped JSObject for use from native code...
2843 : *
2844 : ****************************************************************************
2845 : ***************************************************************************/
2846 :
2847 : // this interfaces exists so we can refcount nsXPCWrappedJSClass
2848 : // {2453EBA0-A9B8-11d2-BA64-00805F8A5DD7}
2849 : #define NS_IXPCONNECT_WRAPPED_JS_CLASS_IID \
2850 : { 0x2453eba0, 0xa9b8, 0x11d2, \
2851 : { 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
2852 :
2853 : class nsIXPCWrappedJSClass : public nsISupports
2854 32582 : {
2855 : public:
2856 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
2857 : NS_IMETHOD DebugDump(PRInt16 depth) = 0;
2858 : };
2859 :
2860 : NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPCWrappedJSClass,
2861 : NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
2862 :
2863 : /*************************/
2864 : // nsXPCWrappedJSClass represents the sharable factored out common code and
2865 : // data for nsXPCWrappedJS instances for the same interface type.
2866 :
2867 : class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass
2868 : {
2869 : // all the interface method declarations...
2870 : NS_DECL_ISUPPORTS
2871 : NS_IMETHOD DebugDump(PRInt16 depth);
2872 : public:
2873 :
2874 : static nsresult
2875 : GetNewOrUsed(XPCCallContext& ccx,
2876 : REFNSIID aIID,
2877 : nsXPCWrappedJSClass** clazz);
2878 :
2879 691234 : REFNSIID GetIID() const {return mIID;}
2880 131266 : XPCJSRuntime* GetRuntime() const {return mRuntime;}
2881 555585 : nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
2882 : const char* GetInterfaceName();
2883 :
2884 : static JSBool IsWrappedJS(nsISupports* aPtr);
2885 :
2886 : NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
2887 : void** aInstancePtr);
2888 :
2889 : JSObject* GetRootJSObject(XPCCallContext& ccx, JSObject* aJSObj);
2890 :
2891 : NS_IMETHOD CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
2892 : const XPTMethodDescriptor* info,
2893 : nsXPTCMiniVariant* params);
2894 :
2895 : JSObject* CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
2896 : JSObject* jsobj, REFNSIID aIID);
2897 :
2898 : static nsresult BuildPropertyEnumerator(XPCCallContext& ccx,
2899 : JSObject* aJSObj,
2900 : nsISimpleEnumerator** aEnumerate);
2901 :
2902 : static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
2903 : JSObject* aJSObj,
2904 : const nsAString& aName,
2905 : nsIVariant** aResult);
2906 :
2907 : virtual ~nsXPCWrappedJSClass();
2908 :
2909 : static nsresult CheckForException(XPCCallContext & ccx,
2910 : const char * aPropertyName,
2911 : const char * anInterfaceName,
2912 : bool aForceReport);
2913 : private:
2914 : nsXPCWrappedJSClass(); // not implemented
2915 : nsXPCWrappedJSClass(XPCCallContext& ccx, REFNSIID aIID,
2916 : nsIInterfaceInfo* aInfo);
2917 :
2918 : JSObject* NewOutObject(JSContext* cx, JSObject* scope);
2919 :
2920 1219826 : JSBool IsReflectable(uint16_t i) const
2921 1219826 : {return (JSBool)(mDescriptors[i/32] & (1 << (i%32)));}
2922 183263 : void SetReflectable(uint16_t i, JSBool b)
2923 183263 : {if (b) mDescriptors[i/32] |= (1 << (i%32));
2924 66022 : else mDescriptors[i/32] &= ~(1 << (i%32));}
2925 :
2926 : JSBool GetArraySizeFromParam(JSContext* cx,
2927 : const XPTMethodDescriptor* method,
2928 : const nsXPTParamInfo& param,
2929 : uint16_t methodIndex,
2930 : uint8_t paramIndex,
2931 : nsXPTCMiniVariant* params,
2932 : uint32_t* result);
2933 :
2934 : JSBool GetInterfaceTypeFromParam(JSContext* cx,
2935 : const XPTMethodDescriptor* method,
2936 : const nsXPTParamInfo& param,
2937 : uint16_t methodIndex,
2938 : const nsXPTType& type,
2939 : nsXPTCMiniVariant* params,
2940 : nsID* result);
2941 :
2942 : void CleanupPointerArray(const nsXPTType& datum_type,
2943 : uint32_t array_count,
2944 : void** arrayp);
2945 :
2946 : void CleanupPointerTypeObject(const nsXPTType& type,
2947 : void** pp);
2948 :
2949 : private:
2950 : XPCJSRuntime* mRuntime;
2951 : nsIInterfaceInfo* mInfo;
2952 : char* mName;
2953 : nsIID mIID;
2954 : uint32_t* mDescriptors;
2955 : };
2956 :
2957 : /*************************/
2958 : // nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
2959 : // nsXPCWrappedJS objects are chained together to represent the various
2960 : // interface on the single underlying (possibly aggregate) JSObject.
2961 :
2962 : class nsXPCWrappedJS : protected nsAutoXPTCStub,
2963 : public nsIXPConnectWrappedJS,
2964 : public nsSupportsWeakReference,
2965 : public nsIPropertyBag,
2966 : public XPCRootSetElem
2967 : {
2968 : public:
2969 : NS_DECL_ISUPPORTS
2970 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
2971 : NS_DECL_NSIXPCONNECTWRAPPEDJS
2972 : NS_DECL_NSISUPPORTSWEAKREFERENCE
2973 : NS_DECL_NSIPROPERTYBAG
2974 :
2975 35173 : NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
2976 0 : NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(nsXPCWrappedJS)
2977 :
2978 : NS_IMETHOD CallMethod(PRUint16 methodIndex,
2979 : const XPTMethodDescriptor *info,
2980 : nsXPTCMiniVariant* params);
2981 :
2982 : /*
2983 : * This is rarely called directly. Instead one usually calls
2984 : * XPCConvert::JSObject2NativeInterface which will handles cases where the
2985 : * JS object is already a wrapped native or a DOM object.
2986 : */
2987 :
2988 : static nsresult
2989 : GetNewOrUsed(XPCCallContext& ccx,
2990 : JSObject* aJSObj,
2991 : REFNSIID aIID,
2992 : nsISupports* aOuter,
2993 : nsXPCWrappedJS** wrapper);
2994 :
2995 490965 : nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
2996 :
2997 : /**
2998 : * This getter clears the gray bit before handing out the JSObject which
2999 : * means that the object is guaranteed to be kept alive past the next CC.
3000 : */
3001 3295888 : JSObject* GetJSObject() const {xpc_UnmarkGrayObject(mJSObj);
3002 3295888 : return mJSObj;}
3003 :
3004 : /**
3005 : * This getter does not change the color of the JSObject meaning that the
3006 : * object returned is not guaranteed to be kept alive past the next CC.
3007 : *
3008 : * This should only be called if you are certain that the return value won't
3009 : * be passed into a JS API function and that it won't be stored without
3010 : * being rooted (or otherwise signaling the stored value to the CC).
3011 : */
3012 552872 : JSObject* GetJSObjectPreserveColor() const {return mJSObj;}
3013 :
3014 2031269 : nsXPCWrappedJSClass* GetClass() const {return mClass;}
3015 502057 : REFNSIID GetIID() const {return GetClass()->GetIID();}
3016 15065 : nsXPCWrappedJS* GetRootWrapper() const {return mRoot;}
3017 212946 : nsXPCWrappedJS* GetNextWrapper() const {return mNext;}
3018 :
3019 : nsXPCWrappedJS* Find(REFNSIID aIID);
3020 : nsXPCWrappedJS* FindInherited(REFNSIID aIID);
3021 :
3022 3037050 : JSBool IsValid() const {return mJSObj != nsnull;}
3023 : void SystemIsBeingShutDown(JSRuntime* rt);
3024 :
3025 : // This is used by XPCJSRuntime::GCCallback to find wrappers that no
3026 : // longer root their JSObject and are only still alive because they
3027 : // were being used via nsSupportsWeakReference at the time when their
3028 : // last (outside) reference was released. Wrappers that fit into that
3029 : // category are only deleted when we see that their corresponding JSObject
3030 : // is to be finalized.
3031 214984 : JSBool IsSubjectToFinalization() const {return IsValid() && mRefCnt == 1;}
3032 :
3033 1787 : JSBool IsAggregatedToNative() const {return mRoot->mOuter != nsnull;}
3034 958712 : nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
3035 :
3036 107637 : void SetIsMainThreadOnly() {
3037 107637 : MOZ_ASSERT(mMainThread);
3038 107637 : mMainThreadOnly = true;
3039 107637 : }
3040 107723 : bool IsMainThreadOnly() const {return mMainThreadOnly;}
3041 :
3042 : void TraceJS(JSTracer* trc);
3043 : #ifdef DEBUG
3044 : static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
3045 : #endif
3046 :
3047 : virtual ~nsXPCWrappedJS();
3048 : protected:
3049 : nsXPCWrappedJS(); // not implemented
3050 : nsXPCWrappedJS(XPCCallContext& ccx,
3051 : JSObject* aJSObj,
3052 : nsXPCWrappedJSClass* aClass,
3053 : nsXPCWrappedJS* root,
3054 : nsISupports* aOuter);
3055 :
3056 : void Unlink();
3057 :
3058 : private:
3059 : JSObject* mJSObj;
3060 : nsXPCWrappedJSClass* mClass;
3061 : nsXPCWrappedJS* mRoot;
3062 : nsXPCWrappedJS* mNext;
3063 : nsISupports* mOuter; // only set in root
3064 : bool mMainThread;
3065 : bool mMainThreadOnly;
3066 : };
3067 :
3068 : /***************************************************************************/
3069 :
3070 : class XPCJSObjectHolder : public nsIXPConnectJSObjectHolder,
3071 : public XPCRootSetElem
3072 : {
3073 : public:
3074 : // all the interface method declarations...
3075 : NS_DECL_ISUPPORTS
3076 : NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
3077 :
3078 : // non-interface implementation
3079 :
3080 : public:
3081 : static XPCJSObjectHolder* newHolder(XPCCallContext& ccx, JSObject* obj);
3082 :
3083 : virtual ~XPCJSObjectHolder();
3084 :
3085 : void TraceJS(JSTracer *trc);
3086 : #ifdef DEBUG
3087 : static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
3088 : #endif
3089 :
3090 : private:
3091 : XPCJSObjectHolder(XPCCallContext& ccx, JSObject* obj);
3092 : XPCJSObjectHolder(); // not implemented
3093 :
3094 : JSObject* mJSObj;
3095 : };
3096 :
3097 : /***************************************************************************
3098 : ****************************************************************************
3099 : *
3100 : * All manner of utility classes follow...
3101 : *
3102 : ****************************************************************************
3103 : ***************************************************************************/
3104 :
3105 : class xpcProperty : public nsIProperty
3106 : {
3107 : public:
3108 : NS_DECL_ISUPPORTS
3109 : NS_DECL_NSIPROPERTY
3110 :
3111 : xpcProperty(const PRUnichar* aName, PRUint32 aNameLen, nsIVariant* aValue);
3112 0 : virtual ~xpcProperty() {}
3113 :
3114 : private:
3115 : nsString mName;
3116 : nsCOMPtr<nsIVariant> mValue;
3117 : };
3118 :
3119 : /***************************************************************************/
3120 : // data conversion
3121 :
3122 : class xpcObjectHelper
3123 2138641 : {
3124 : public:
3125 2102771 : xpcObjectHelper(nsISupports *aObject, nsWrapperCache *aCache = nsnull)
3126 : : mCanonical(nsnull),
3127 : mObject(aObject),
3128 : mCache(aCache),
3129 2102771 : mIsNode(false)
3130 : {
3131 2102771 : if (!mCache) {
3132 2102769 : if (aObject)
3133 2102769 : CallQueryInterface(aObject, &mCache);
3134 : else
3135 0 : mCache = nsnull;
3136 : }
3137 2102771 : }
3138 :
3139 3320483 : nsISupports* Object()
3140 : {
3141 3320483 : return mObject;
3142 : }
3143 :
3144 2163927 : nsISupports* GetCanonical()
3145 : {
3146 2163927 : if (!mCanonical) {
3147 2105265 : mCanonicalStrong = do_QueryInterface(mObject);
3148 2105265 : mCanonical = mCanonicalStrong;
3149 : }
3150 2163927 : return mCanonical;
3151 : }
3152 :
3153 1251115 : already_AddRefed<nsISupports> forgetCanonical()
3154 : {
3155 1251115 : NS_ASSERTION(mCanonical, "Huh, no canonical to forget?");
3156 :
3157 1251115 : if (!mCanonicalStrong)
3158 12204 : mCanonicalStrong = mCanonical;
3159 1251115 : mCanonical = nsnull;
3160 1251115 : return mCanonicalStrong.forget();
3161 : }
3162 :
3163 1249144 : nsIClassInfo *GetClassInfo()
3164 : {
3165 1249144 : if (mXPCClassInfo)
3166 4969 : return mXPCClassInfo;
3167 1244175 : if (!mClassInfo)
3168 1231003 : mClassInfo = do_QueryInterface(mObject);
3169 1244175 : return mClassInfo;
3170 : }
3171 61599 : nsXPCClassInfo *GetXPCClassInfo()
3172 : {
3173 61599 : if (!mXPCClassInfo) {
3174 46456 : if (mIsNode)
3175 14947 : mXPCClassInfo = static_cast<nsINode*>(GetCanonical())->GetClassInfo();
3176 : else
3177 31509 : CallQueryInterface(mObject, getter_AddRefs(mXPCClassInfo));
3178 : }
3179 61599 : return mXPCClassInfo;
3180 : }
3181 :
3182 15143 : already_AddRefed<nsXPCClassInfo> forgetXPCClassInfo()
3183 : {
3184 15143 : GetXPCClassInfo();
3185 :
3186 15143 : return mXPCClassInfo.forget();
3187 : }
3188 :
3189 : // We assert that we can reach an nsIXPCScriptable somehow.
3190 26344 : PRUint32 GetScriptableFlags()
3191 : {
3192 : // Try getting an nsXPCClassInfo - this handles DOM scriptable helpers.
3193 52688 : nsCOMPtr<nsIXPCScriptable> sinfo = GetXPCClassInfo();
3194 :
3195 : // If that didn't work, try just QI-ing. This handles BackstagePass.
3196 26344 : if (!sinfo)
3197 26344 : sinfo = do_QueryInterface(GetCanonical());
3198 :
3199 : // We should have something by now.
3200 26344 : MOZ_ASSERT(sinfo);
3201 :
3202 : // Grab the flags. This should not fail.
3203 : PRUint32 flags;
3204 52688 : mozilla::DebugOnly<nsresult> rv = sinfo->GetScriptableFlags(&flags);
3205 26344 : MOZ_ASSERT(NS_SUCCEEDED(rv));
3206 :
3207 26344 : return flags;
3208 : }
3209 :
3210 4240920 : nsWrapperCache *GetWrapperCache()
3211 : {
3212 4240920 : return mCache;
3213 : }
3214 :
3215 : protected:
3216 35870 : xpcObjectHelper(nsISupports *aObject, nsISupports *aCanonical,
3217 : nsWrapperCache *aCache, bool aIsNode)
3218 : : mCanonical(aCanonical),
3219 : mObject(aObject),
3220 : mCache(aCache),
3221 35870 : mIsNode(aIsNode)
3222 : {
3223 35870 : if (!mCache && aObject)
3224 17585 : CallQueryInterface(aObject, &mCache);
3225 35870 : }
3226 :
3227 : nsCOMPtr<nsISupports> mCanonicalStrong;
3228 : nsISupports* mCanonical;
3229 :
3230 : private:
3231 : xpcObjectHelper(xpcObjectHelper& aOther);
3232 :
3233 : nsISupports* mObject;
3234 : nsWrapperCache* mCache;
3235 : nsCOMPtr<nsIClassInfo> mClassInfo;
3236 : nsRefPtr<nsXPCClassInfo> mXPCClassInfo;
3237 : bool mIsNode;
3238 : };
3239 :
3240 : // class here just for static methods
3241 : class XPCConvert
3242 : {
3243 : public:
3244 : static JSBool IsMethodReflectable(const XPTMethodDescriptor& info);
3245 :
3246 : /**
3247 : * Convert a native object into a jsval.
3248 : *
3249 : * @param ccx the context for the whole procedure
3250 : * @param d [out] the resulting jsval
3251 : * @param s the native object we're working with
3252 : * @param type the type of object that s is
3253 : * @param iid the interface of s that we want
3254 : * @param scope the default scope to put on the new JSObject's parent
3255 : * chain
3256 : * @param pErr [out] relevant error code, if any.
3257 : */
3258 20916012 : static JSBool NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s,
3259 : const nsXPTType& type, const nsID* iid,
3260 : nsresult* pErr)
3261 : {
3262 41832024 : XPCLazyCallContext lccx(ccx);
3263 20916012 : return NativeData2JS(lccx, d, s, type, iid, pErr);
3264 : }
3265 : static JSBool NativeData2JS(XPCLazyCallContext& lccx, jsval* d,
3266 : const void* s, const nsXPTType& type,
3267 : const nsID* iid, nsresult* pErr);
3268 :
3269 : static JSBool JSData2Native(XPCCallContext& ccx, void* d, jsval s,
3270 : const nsXPTType& type,
3271 : JSBool useAllocator, const nsID* iid,
3272 : nsresult* pErr);
3273 :
3274 : /**
3275 : * Convert a native nsISupports into a JSObject.
3276 : *
3277 : * @param ccx the context for the whole procedure
3278 : * @param dest [out] the resulting JSObject
3279 : * @param src the native object we're working with
3280 : * @param iid the interface of src that we want (may be null)
3281 : * @param Interface the interface of src that we want
3282 : * @param cache the wrapper cache for src (may be null, in which case src
3283 : * will be QI'ed to get the cache)
3284 : * @param allowNativeWrapper if true, this method may wrap the resulting
3285 : * JSObject in an XPCNativeWrapper and return that, as needed.
3286 : * @param pErr [out] relevant error code, if any.
3287 : * @param src_is_identity optional performance hint. Set to true only
3288 : * if src is the identity pointer.
3289 : */
3290 4144 : static JSBool NativeInterface2JSObject(XPCCallContext& ccx,
3291 : jsval* d,
3292 : nsIXPConnectJSObjectHolder** dest,
3293 : xpcObjectHelper& aHelper,
3294 : const nsID* iid,
3295 : XPCNativeInterface** Interface,
3296 : bool allowNativeWrapper,
3297 : nsresult* pErr)
3298 : {
3299 8288 : XPCLazyCallContext lccx(ccx);
3300 : return NativeInterface2JSObject(lccx, d, dest, aHelper, iid, Interface,
3301 4144 : allowNativeWrapper, pErr);
3302 : }
3303 : static JSBool NativeInterface2JSObject(XPCLazyCallContext& lccx,
3304 : jsval* d,
3305 : nsIXPConnectJSObjectHolder** dest,
3306 : xpcObjectHelper& aHelper,
3307 : const nsID* iid,
3308 : XPCNativeInterface** Interface,
3309 : bool allowNativeWrapper,
3310 : nsresult* pErr);
3311 :
3312 : static JSBool GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
3313 : void** dest, JSObject* src,
3314 : const nsID* iid,
3315 : nsresult* pErr);
3316 : static JSBool JSObject2NativeInterface(XPCCallContext& ccx,
3317 : void** dest, JSObject* src,
3318 : const nsID* iid,
3319 : nsISupports* aOuter,
3320 : nsresult* pErr);
3321 : static JSBool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
3322 :
3323 : /**
3324 : * Convert a native array into a jsval.
3325 : *
3326 : * @param ccx the context for the whole procedure
3327 : * @param d [out] the resulting jsval
3328 : * @param s the native array we're working with
3329 : * @param type the type of objects in the array
3330 : * @param iid the interface of each object in the array that we want
3331 : * @param count the number of items in the array
3332 : * @param scope the default scope to put on the new JSObjects' parent chain
3333 : * @param pErr [out] relevant error code, if any.
3334 : */
3335 : static JSBool NativeArray2JS(XPCLazyCallContext& ccx,
3336 : jsval* d, const void** s,
3337 : const nsXPTType& type, const nsID* iid,
3338 : uint32_t count, nsresult* pErr);
3339 :
3340 : static JSBool JSArray2Native(XPCCallContext& ccx, void** d, jsval s,
3341 : uint32_t count, const nsXPTType& type,
3342 : const nsID* iid, nsresult* pErr);
3343 :
3344 : static JSBool JSTypedArray2Native(XPCCallContext& ccx,
3345 : void** d,
3346 : JSObject* jsarray,
3347 : uint32_t count,
3348 : const nsXPTType& type,
3349 : nsresult* pErr);
3350 :
3351 : static JSBool NativeStringWithSize2JS(JSContext* cx,
3352 : jsval* d, const void* s,
3353 : const nsXPTType& type,
3354 : uint32_t count,
3355 : nsresult* pErr);
3356 :
3357 : static JSBool JSStringWithSize2Native(XPCCallContext& ccx, void* d, jsval s,
3358 : uint32_t count, const nsXPTType& type,
3359 : unsigned* pErr);
3360 :
3361 : static nsresult JSValToXPCException(XPCCallContext& ccx,
3362 : jsval s,
3363 : const char* ifaceName,
3364 : const char* methodName,
3365 : nsIException** exception);
3366 :
3367 : static nsresult JSErrorToXPCException(XPCCallContext& ccx,
3368 : const char* message,
3369 : const char* ifaceName,
3370 : const char* methodName,
3371 : const JSErrorReport* report,
3372 : nsIException** exception);
3373 :
3374 : static nsresult ConstructException(nsresult rv, const char* message,
3375 : const char* ifaceName,
3376 : const char* methodName,
3377 : nsISupports* data,
3378 : nsIException** exception,
3379 : JSContext* cx,
3380 : jsval *jsExceptionPtr);
3381 :
3382 : private:
3383 : XPCConvert(); // not implemented
3384 :
3385 : };
3386 :
3387 : /***************************************************************************/
3388 :
3389 : // readable string conversions, static methods only
3390 : class XPCStringConvert
3391 : {
3392 : public:
3393 :
3394 : // If the string shares the readable's buffer, that buffer will
3395 : // get assigned to *sharedBuffer. Otherwise null will be
3396 : // assigned.
3397 : static jsval ReadableToJSVal(JSContext *cx, const nsAString &readable,
3398 : nsStringBuffer** sharedBuffer);
3399 :
3400 : private:
3401 : XPCStringConvert(); // not implemented
3402 : };
3403 :
3404 : /***************************************************************************/
3405 : // code for throwing exceptions into JS
3406 :
3407 : class XPCThrower
3408 : {
3409 : public:
3410 : static void Throw(nsresult rv, JSContext* cx);
3411 : static void Throw(nsresult rv, XPCCallContext& ccx);
3412 : static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
3413 : static void ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx);
3414 : static JSBool SetVerbosity(JSBool state)
3415 : {JSBool old = sVerbose; sVerbose = state; return old;}
3416 :
3417 : static void BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz);
3418 : static JSBool CheckForPendingException(nsresult result, JSContext *cx);
3419 :
3420 : private:
3421 : static void Verbosify(XPCCallContext& ccx,
3422 : char** psz, bool own);
3423 :
3424 : static JSBool ThrowExceptionObject(JSContext* cx, nsIException* e);
3425 :
3426 : private:
3427 : static JSBool sVerbose;
3428 : };
3429 :
3430 :
3431 : /***************************************************************************/
3432 :
3433 : class XPCJSStack
3434 : {
3435 : public:
3436 : static nsresult
3437 : CreateStack(JSContext* cx, nsIStackFrame** stack);
3438 :
3439 : static nsresult
3440 : CreateStackFrameLocation(PRUint32 aLanguage,
3441 : const char* aFilename,
3442 : const char* aFunctionName,
3443 : PRInt32 aLineNumber,
3444 : nsIStackFrame* aCaller,
3445 : nsIStackFrame** stack);
3446 : private:
3447 : XPCJSStack(); // not implemented
3448 : };
3449 :
3450 : /***************************************************************************/
3451 :
3452 : class nsXPCException :
3453 : public nsIXPCException
3454 : {
3455 : public:
3456 108 : NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCEXCEPTION_CID)
3457 :
3458 : NS_DECL_ISUPPORTS
3459 : NS_DECL_NSIEXCEPTION
3460 : NS_DECL_NSIXPCEXCEPTION
3461 :
3462 : static nsresult NewException(const char *aMessage,
3463 : nsresult aResult,
3464 : nsIStackFrame *aLocation,
3465 : nsISupports *aData,
3466 : nsIException** exception);
3467 :
3468 : static JSBool NameAndFormatForNSResult(nsresult rv,
3469 : const char** name,
3470 : const char** format);
3471 :
3472 : static void* IterateNSResults(nsresult* rv,
3473 : const char** name,
3474 : const char** format,
3475 : void** iterp);
3476 :
3477 : static PRUint32 GetNSResultCount();
3478 :
3479 : nsXPCException();
3480 : virtual ~nsXPCException();
3481 :
3482 1365 : static void InitStatics() { sEverMadeOneFromFactory = false; }
3483 :
3484 : protected:
3485 : void Reset();
3486 : private:
3487 : char* mMessage;
3488 : nsresult mResult;
3489 : char* mName;
3490 : nsIStackFrame* mLocation;
3491 : nsISupports* mData;
3492 : char* mFilename;
3493 : int mLineNumber;
3494 : nsIException* mInner;
3495 : bool mInitialized;
3496 :
3497 : nsAutoJSValHolder mThrownJSVal;
3498 :
3499 : static JSBool sEverMadeOneFromFactory;
3500 : };
3501 :
3502 : /***************************************************************************/
3503 : /*
3504 : * nsJSID implements nsIJSID. It is also used by nsJSIID and nsJSCID as a
3505 : * member (as a hidden implementaion detail) to which they delegate many calls.
3506 : */
3507 :
3508 : // Initialization is done on demand, and calling the destructor below is always
3509 : // safe.
3510 : extern void xpc_DestroyJSxIDClassObjects();
3511 :
3512 : class nsJSID : public nsIJSID
3513 : {
3514 : public:
3515 3241 : NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID)
3516 :
3517 : NS_DECL_ISUPPORTS
3518 : NS_DECL_NSIJSID
3519 :
3520 : bool InitWithName(const nsID& id, const char *nameString);
3521 : bool SetName(const char* name);
3522 0 : void SetNameToNoString()
3523 0 : {NS_ASSERTION(!mName, "name already set"); mName = gNoString;}
3524 0 : bool NameIsSet() const {return nsnull != mName;}
3525 373845 : const nsID& ID() const {return mID;}
3526 186238 : bool IsValid() const {return !mID.Equals(GetInvalidIID());}
3527 :
3528 : static nsJSID* NewID(const char* str);
3529 : static nsJSID* NewID(const nsID& id);
3530 :
3531 : nsJSID();
3532 : virtual ~nsJSID();
3533 : protected:
3534 :
3535 : void Reset();
3536 : const nsID& GetInvalidIID() const;
3537 :
3538 : protected:
3539 : static char gNoString[];
3540 : nsID mID;
3541 : char* mNumber;
3542 : char* mName;
3543 : };
3544 :
3545 : // nsJSIID
3546 :
3547 : class nsJSIID : public nsIJSIID,
3548 : public nsIXPCScriptable,
3549 : public nsISecurityCheckedComponent
3550 : {
3551 : public:
3552 : NS_DECL_ISUPPORTS
3553 :
3554 : // we manually delagate these to nsJSID
3555 : NS_DECL_NSIJSID
3556 :
3557 : // we implement the rest...
3558 : NS_DECL_NSIJSIID
3559 : NS_DECL_NSIXPCSCRIPTABLE
3560 : NS_DECL_NSISECURITYCHECKEDCOMPONENT
3561 :
3562 : static nsJSIID* NewID(nsIInterfaceInfo* aInfo);
3563 :
3564 : nsJSIID(nsIInterfaceInfo* aInfo);
3565 : nsJSIID(); // not implemented
3566 : virtual ~nsJSIID();
3567 :
3568 : private:
3569 : nsCOMPtr<nsIInterfaceInfo> mInfo;
3570 : };
3571 :
3572 : // nsJSCID
3573 :
3574 : class nsJSCID : public nsIJSCID, public nsIXPCScriptable
3575 : {
3576 : public:
3577 : NS_DECL_ISUPPORTS
3578 :
3579 : // we manually delagate these to nsJSID
3580 : NS_DECL_NSIJSID
3581 :
3582 : // we implement the rest...
3583 : NS_DECL_NSIJSCID
3584 : NS_DECL_NSIXPCSCRIPTABLE
3585 :
3586 : static nsJSCID* NewID(const char* str);
3587 :
3588 : nsJSCID();
3589 : virtual ~nsJSCID();
3590 :
3591 : private:
3592 : void ResolveName();
3593 :
3594 : private:
3595 : nsJSID mDetails;
3596 : };
3597 :
3598 :
3599 : /***************************************************************************/
3600 : // XPCJSContextStack is not actually an xpcom object, but xpcom calls are
3601 : // delegated to it as an implementation detail.
3602 616204 : struct XPCJSContextInfo {
3603 616204 : XPCJSContextInfo(JSContext* aCx) :
3604 : cx(aCx),
3605 : savedFrameChain(false),
3606 616204 : suspendDepth(0)
3607 616204 : {}
3608 : JSContext* cx;
3609 :
3610 : // Whether the frame chain was saved
3611 : bool savedFrameChain;
3612 :
3613 : // Greater than 0 if a request was suspended.
3614 : unsigned suspendDepth;
3615 : };
3616 :
3617 : class XPCJSContextStack
3618 : {
3619 : public:
3620 1367 : XPCJSContextStack()
3621 : : mSafeJSContext(NULL)
3622 1367 : , mOwnSafeJSContext(NULL)
3623 1367 : { }
3624 :
3625 : virtual ~XPCJSContextStack();
3626 :
3627 0 : uint32_t Count()
3628 : {
3629 0 : return mStack.Length();
3630 : }
3631 :
3632 19315371 : JSContext *Peek()
3633 : {
3634 19315371 : return mStack.IsEmpty() ? NULL : mStack[mStack.Length() - 1].cx;
3635 : }
3636 :
3637 : JSContext *Pop();
3638 : bool Push(JSContext *cx);
3639 : JSContext *GetSafeJSContext();
3640 :
3641 : #ifdef DEBUG
3642 : bool DEBUG_StackHasJSContext(JSContext *cx);
3643 : #endif
3644 :
3645 0 : const InfallibleTArray<XPCJSContextInfo>* GetStack()
3646 0 : { return &mStack; }
3647 :
3648 : private:
3649 : AutoInfallibleTArray<XPCJSContextInfo, 16> mStack;
3650 : JSContext* mSafeJSContext;
3651 : JSContext* mOwnSafeJSContext;
3652 : };
3653 :
3654 : /***************************************************************************/
3655 :
3656 : #define NS_XPC_JSCONTEXT_STACK_ITERATOR_CID \
3657 : { 0x05bae29d, 0x8aef, 0x486d, \
3658 : { 0x84, 0xaa, 0x53, 0xf4, 0x8f, 0x14, 0x68, 0x11 } }
3659 :
3660 : class nsXPCJSContextStackIterator : public nsIJSContextStackIterator
3661 0 : {
3662 : public:
3663 : NS_DECL_ISUPPORTS
3664 : NS_DECL_NSIJSCONTEXTSTACKITERATOR
3665 :
3666 : private:
3667 : const InfallibleTArray<XPCJSContextInfo> *mStack;
3668 : PRUint32 mPosition;
3669 : };
3670 :
3671 : /**************************************************************/
3672 : // All of our thread local storage.
3673 :
3674 : class XPCPerThreadData
3675 : {
3676 : typedef mozilla::Mutex Mutex;
3677 :
3678 : public:
3679 : // Get the instance of this object for the current thread
3680 20349765 : static inline XPCPerThreadData* GetData(JSContext *cx)
3681 : {
3682 : // Do a release-mode assert that we're not doing anything significant in
3683 : // XPConnect off the main thread. If you're an extension developer hitting
3684 : // this, you need to change your code. See bug 716167.
3685 20349765 : if (!NS_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
3686 0 : MOZ_Assert("NS_IsMainThread()", __FILE__, __LINE__);
3687 :
3688 20349765 : if (cx) {
3689 14992753 : if (js::GetOwnerThread(cx) == sMainJSThread)
3690 14991384 : return sMainThreadData;
3691 5357012 : } else if (sMainThreadData && sMainThreadData->mThread == PR_GetCurrentThread()) {
3692 5355647 : return sMainThreadData;
3693 : }
3694 :
3695 2734 : return GetDataImpl(cx);
3696 : }
3697 :
3698 : static void CleanupAllThreads();
3699 :
3700 : ~XPCPerThreadData();
3701 :
3702 18998 : nsresult GetException(nsIException** aException)
3703 : {
3704 18998 : if (EnsureExceptionManager())
3705 18998 : return mExceptionManager->GetCurrentException(aException);
3706 :
3707 0 : NS_IF_ADDREF(mException);
3708 0 : *aException = mException;
3709 0 : return NS_OK;
3710 : }
3711 :
3712 9811725 : nsresult SetException(nsIException* aException)
3713 : {
3714 9811725 : if (EnsureExceptionManager())
3715 9811725 : return mExceptionManager->SetCurrentException(aException);
3716 :
3717 0 : NS_IF_ADDREF(aException);
3718 0 : NS_IF_RELEASE(mException);
3719 0 : mException = aException;
3720 0 : return NS_OK;
3721 : }
3722 :
3723 18793 : nsIExceptionManager* GetExceptionManager()
3724 : {
3725 18793 : if (EnsureExceptionManager())
3726 18793 : return mExceptionManager;
3727 0 : return nsnull;
3728 : }
3729 :
3730 9849516 : JSBool EnsureExceptionManager()
3731 : {
3732 9849516 : if (mExceptionManager)
3733 9848151 : return true;
3734 :
3735 1365 : if (mExceptionManagerNotAvailable)
3736 0 : return false;
3737 :
3738 : nsCOMPtr<nsIExceptionService> xs =
3739 2730 : do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
3740 1365 : if (xs)
3741 1365 : xs->GetCurrentExceptionManager(&mExceptionManager);
3742 1365 : if (mExceptionManager)
3743 1365 : return true;
3744 :
3745 0 : mExceptionManagerNotAvailable = true;
3746 0 : return false;
3747 : }
3748 :
3749 20314225 : XPCJSContextStack* GetJSContextStack() {return mJSContextStack;}
3750 :
3751 252510 : XPCCallContext* GetCallContext() const {return mCallContext;}
3752 33113150 : XPCCallContext* SetCallContext(XPCCallContext* ccx)
3753 33113150 : {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
3754 :
3755 1670908 : jsid GetResolveName() const {return mResolveName;}
3756 6534346 : jsid SetResolveName(jsid name)
3757 6534346 : {jsid old = mResolveName; mResolveName = name; return old;}
3758 :
3759 223550 : XPCWrappedNative* GetResolvingWrapper() const {return mResolvingWrapper;}
3760 1030760 : XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w)
3761 1030760 : {XPCWrappedNative* old = mResolvingWrapper;
3762 1030760 : mResolvingWrapper = w; return old;}
3763 :
3764 : void Cleanup();
3765 : void ReleaseNatives();
3766 :
3767 1367 : bool IsValid() const {return mJSContextStack != nsnull;}
3768 :
3769 35343 : static Mutex* GetLock() {return gLock;}
3770 : // Must be called with the threads locked.
3771 : static XPCPerThreadData* IterateThreads(XPCPerThreadData** iteratorp);
3772 :
3773 46566302 : AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;}
3774 :
3775 : void TraceJS(JSTracer* trc);
3776 : void MarkAutoRootsAfterJSFinalize();
3777 :
3778 1365 : static void InitStatics()
3779 1365 : { gLock = nsnull; gThreads = nsnull; gTLSIndex = BAD_TLS_INDEX; }
3780 :
3781 : #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
3782 0 : uint32_t IncrementWrappedNativeThreadsafetyReportDepth()
3783 0 : {return ++mWrappedNativeThreadsafetyReportDepth;}
3784 0 : void ClearWrappedNativeThreadsafetyReportDepth()
3785 0 : {mWrappedNativeThreadsafetyReportDepth = 0;}
3786 : #endif
3787 :
3788 1364 : static void ShutDown()
3789 1364 : {sMainJSThread = nsnull; sMainThreadData = nsnull;}
3790 :
3791 13659981 : static bool IsMainThread(JSContext *cx)
3792 13659981 : { return js::GetOwnerThread(cx) == sMainJSThread; }
3793 :
3794 : private:
3795 : XPCPerThreadData();
3796 : static XPCPerThreadData* GetDataImpl(JSContext *cx);
3797 :
3798 : private:
3799 : XPCJSContextStack* mJSContextStack;
3800 : XPCPerThreadData* mNextThread;
3801 : XPCCallContext* mCallContext;
3802 : jsid mResolveName;
3803 : XPCWrappedNative* mResolvingWrapper;
3804 :
3805 : nsIExceptionManager* mExceptionManager;
3806 : nsIException* mException;
3807 : JSBool mExceptionManagerNotAvailable;
3808 : AutoMarkingPtr* mAutoRoots;
3809 :
3810 : #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
3811 : uint32_t mWrappedNativeThreadsafetyReportDepth;
3812 : #endif
3813 : PRThread* mThread;
3814 :
3815 : static Mutex* gLock;
3816 : static XPCPerThreadData* gThreads;
3817 : static PRUintn gTLSIndex;
3818 :
3819 : // Cached value of cx->thread on the main thread.
3820 : static void *sMainJSThread;
3821 :
3822 : // Cached per thread data for the main thread. Only safe to access
3823 : // if cx->thread == sMainJSThread.
3824 : static XPCPerThreadData *sMainThreadData;
3825 : };
3826 :
3827 : /***************************************************************************/
3828 : #include "nsIScriptSecurityManager.h"
3829 :
3830 : class BackstagePass : public nsIScriptObjectPrincipal,
3831 : public nsIXPCScriptable,
3832 : public nsIClassInfo
3833 : {
3834 : public:
3835 : NS_DECL_ISUPPORTS
3836 : NS_DECL_NSIXPCSCRIPTABLE
3837 : NS_DECL_NSICLASSINFO
3838 :
3839 6583303 : virtual nsIPrincipal* GetPrincipal() {
3840 6583303 : return mPrincipal;
3841 : }
3842 :
3843 1365 : BackstagePass(nsIPrincipal *prin) :
3844 1365 : mPrincipal(prin)
3845 : {
3846 1365 : }
3847 :
3848 5388 : virtual ~BackstagePass() { }
3849 :
3850 : private:
3851 : nsCOMPtr<nsIPrincipal> mPrincipal;
3852 : };
3853 : // 'Components' object
3854 :
3855 : class nsXPCComponents : public nsIXPCComponents,
3856 : public nsIXPCScriptable,
3857 : public nsIClassInfo,
3858 : public nsISecurityCheckedComponent
3859 : {
3860 : public:
3861 : NS_DECL_ISUPPORTS
3862 : NS_DECL_NSIXPCCOMPONENTS
3863 : NS_DECL_NSIXPCSCRIPTABLE
3864 : NS_DECL_NSICLASSINFO
3865 : NS_DECL_NSISECURITYCHECKEDCOMPONENT
3866 :
3867 : public:
3868 : static JSBool
3869 : AttachNewComponentsObject(XPCCallContext& ccx,
3870 : XPCWrappedNativeScope* aScope,
3871 : JSObject* aGlobal);
3872 :
3873 24 : void SystemIsBeingShutDown() {ClearMembers();}
3874 :
3875 : virtual ~nsXPCComponents();
3876 :
3877 : private:
3878 : nsXPCComponents();
3879 : void ClearMembers();
3880 :
3881 : private:
3882 : nsXPCComponents_Interfaces* mInterfaces;
3883 : nsXPCComponents_InterfacesByID* mInterfacesByID;
3884 : nsXPCComponents_Classes* mClasses;
3885 : nsXPCComponents_ClassesByID* mClassesByID;
3886 : nsXPCComponents_Results* mResults;
3887 : nsXPCComponents_ID* mID;
3888 : nsXPCComponents_Exception* mException;
3889 : nsXPCComponents_Constructor* mConstructor;
3890 : nsXPCComponents_Utils* mUtils;
3891 : };
3892 :
3893 :
3894 : /***************************************************************************/
3895 :
3896 : extern JSObject*
3897 : xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID);
3898 :
3899 : extern const nsID*
3900 : xpc_JSObjectToID(JSContext *cx, JSObject* obj);
3901 :
3902 : extern JSBool
3903 : xpc_JSObjectIsID(JSContext *cx, JSObject* obj);
3904 :
3905 : /***************************************************************************/
3906 : // in xpcdebug.cpp
3907 :
3908 : extern JSBool
3909 : xpc_DumpJSStack(JSContext* cx, JSBool showArgs, JSBool showLocals,
3910 : JSBool showThisProps);
3911 :
3912 : // Return a newly-allocated string containing a representation of the
3913 : // current JS stack. It is the *caller's* responsibility to free this
3914 : // string with JS_smprintf_free().
3915 : extern char*
3916 : xpc_PrintJSStack(JSContext* cx, JSBool showArgs, JSBool showLocals,
3917 : JSBool showThisProps);
3918 :
3919 : extern JSBool
3920 : xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text);
3921 :
3922 : extern JSBool
3923 : xpc_DumpJSObject(JSObject* obj);
3924 :
3925 : extern JSBool
3926 : xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
3927 :
3928 : /***************************************************************************/
3929 :
3930 : // Definition of nsScriptError, defined here because we lack a place to put
3931 : // XPCOM objects associated with the JavaScript engine.
3932 : class nsScriptError : public nsIScriptError {
3933 : public:
3934 : nsScriptError();
3935 :
3936 : virtual ~nsScriptError();
3937 :
3938 : // TODO - do something reasonable on getting null from these babies.
3939 :
3940 : NS_DECL_ISUPPORTS
3941 : NS_DECL_NSICONSOLEMESSAGE
3942 : NS_DECL_NSISCRIPTERROR
3943 :
3944 : private:
3945 : nsString mMessage;
3946 : nsString mSourceName;
3947 : PRUint32 mLineNumber;
3948 : nsString mSourceLine;
3949 : PRUint32 mColumnNumber;
3950 : PRUint32 mFlags;
3951 : nsCString mCategory;
3952 : PRUint64 mOuterWindowID;
3953 : PRUint64 mInnerWindowID;
3954 : PRInt64 mTimeStamp;
3955 : };
3956 :
3957 : /******************************************************************************
3958 : * Handles pre/post script processing and the setting/resetting the error
3959 : * reporter
3960 : */
3961 : class NS_STACK_CLASS AutoScriptEvaluate
3962 : {
3963 : public:
3964 : /**
3965 : * Saves the JSContext as well as initializing our state
3966 : * @param cx The JSContext, this can be null, we don't do anything then
3967 : */
3968 1546789 : AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
3969 : : mJSContext(cx), mState(0), mErrorReporterSet(false),
3970 1546789 : mEvaluated(false), mContextHasThread(0) {
3971 1546789 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
3972 1546789 : }
3973 :
3974 : /**
3975 : * Does the pre script evaluation and sets the error reporter if given
3976 : * This function should only be called once, and will assert if called
3977 : * more than once
3978 : * @param errorReporter the error reporter callback function to set
3979 : */
3980 :
3981 : bool StartEvaluating(JSObject *scope, JSErrorReporter errorReporter = nsnull);
3982 : /**
3983 : * Does the post script evaluation and resets the error reporter
3984 : */
3985 : ~AutoScriptEvaluate();
3986 : private:
3987 : JSContext* mJSContext;
3988 : JSExceptionState* mState;
3989 : bool mErrorReporterSet;
3990 : bool mEvaluated;
3991 : intptr_t mContextHasThread;
3992 : JSAutoEnterCompartment mEnterCompartment;
3993 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
3994 :
3995 : // No copying or assignment allowed
3996 : AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
3997 : AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;
3998 : };
3999 :
4000 : /***************************************************************************/
4001 : class NS_STACK_CLASS AutoResolveName
4002 : {
4003 : public:
4004 1697306 : AutoResolveName(XPCCallContext& ccx, jsid name
4005 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
4006 1697306 : : mTLS(ccx.GetThreadData()),
4007 1697306 : mOld(mTLS->SetResolveName(name)),
4008 3394612 : mCheck(name) {
4009 1697306 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
4010 1697306 : }
4011 1697306 : ~AutoResolveName()
4012 1697306 : {
4013 : #ifdef DEBUG
4014 : jsid old =
4015 : #endif
4016 1697306 : mTLS->SetResolveName(mOld);
4017 1697306 : NS_ASSERTION(old == mCheck, "Bad Nesting!");
4018 1697306 : }
4019 :
4020 : private:
4021 : XPCPerThreadData* mTLS;
4022 : jsid mOld;
4023 : jsid mCheck;
4024 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
4025 : };
4026 :
4027 : /***************************************************************************/
4028 : class XPCMarkableJSVal
4029 : {
4030 : public:
4031 1842203 : XPCMarkableJSVal(jsval val) : mVal(val), mValPtr(&mVal) {}
4032 8676136 : XPCMarkableJSVal(jsval *pval) : mVal(JSVAL_VOID), mValPtr(pval) {}
4033 10518339 : ~XPCMarkableJSVal() {}
4034 6 : void Mark() {}
4035 6 : void TraceJS(JSTracer* trc)
4036 : {
4037 6 : JS_CALL_VALUE_TRACER(trc, *mValPtr, "XPCMarkableJSVal");
4038 6 : }
4039 6 : void AutoTrace(JSTracer* trc) {}
4040 : private:
4041 : XPCMarkableJSVal(); // not implemented
4042 : jsval mVal;
4043 : jsval* mValPtr;
4044 : };
4045 :
4046 : /***************************************************************************/
4047 : // AutoMarkingPtr is the base class for the various AutoMarking pointer types
4048 : // below. This system allows us to temporarily protect instances of our garbage
4049 : // collected types after they are constructed but before they are safely
4050 : // attached to other rooted objects.
4051 : // This base class has pure virtual support for marking.
4052 :
4053 : class AutoMarkingPtr
4054 : {
4055 : public:
4056 21205264 : AutoMarkingPtr(XPCCallContext& ccx)
4057 21205264 : : mNext(nsnull), mTLS(ccx.GetThreadData()) {Link();}
4058 2084131 : AutoMarkingPtr()
4059 2084131 : : mNext(nsnull), mTLS(nsnull) {}
4060 :
4061 46578790 : virtual ~AutoMarkingPtr() {Unlink();}
4062 :
4063 2077887 : void Init(XPCCallContext& ccx)
4064 2077887 : {NS_ASSERTION(!mTLS, "Already init'ed!");
4065 2077887 : mTLS = ccx.GetThreadData();
4066 2077887 : Link();}
4067 :
4068 23283151 : void Link()
4069 23283151 : {if (!mTLS) return;
4070 23283151 : AutoMarkingPtr** list = mTLS->GetAutoRootsAdr();
4071 23283151 : mNext = *list; *list = this;}
4072 :
4073 23289395 : void Unlink()
4074 23289395 : {if (!mTLS) return;
4075 23283151 : AutoMarkingPtr** cur = mTLS->GetAutoRootsAdr();
4076 46566302 : while (*cur != this) {
4077 0 : NS_ASSERTION(*cur, "This object not in list!");
4078 0 : cur = &(*cur)->mNext;
4079 : }
4080 23283151 : *cur = mNext;
4081 23283151 : mTLS = nsnull;
4082 : }
4083 :
4084 : AutoMarkingPtr* GetNext() {return mNext;}
4085 :
4086 : virtual void TraceJS(JSTracer* trc) = 0;
4087 : virtual void MarkAfterJSFinalize() = 0;
4088 :
4089 : protected:
4090 : AutoMarkingPtr* mNext;
4091 : XPCPerThreadData* mTLS;
4092 : };
4093 :
4094 : // More joy of macros...
4095 :
4096 : #define DEFINE_AUTO_MARKING_PTR_TYPE(class_, type_) \
4097 : class class_ : public AutoMarkingPtr \
4098 : { \
4099 : public: \
4100 : class_ () \
4101 : : AutoMarkingPtr(), mPtr(nsnull) {} \
4102 : class_ (XPCCallContext& ccx, type_ * ptr = nsnull) \
4103 : : AutoMarkingPtr(ccx), mPtr(ptr) {} \
4104 : virtual ~ class_ () {} \
4105 : \
4106 : virtual void TraceJS(JSTracer* trc) \
4107 : {if (mPtr) { \
4108 : mPtr->TraceJS(trc); \
4109 : mPtr->AutoTrace(trc); \
4110 : } \
4111 : if (mNext) mNext->TraceJS(trc);} \
4112 : \
4113 : virtual void MarkAfterJSFinalize() \
4114 : {if (mPtr) mPtr->Mark(); \
4115 : if (mNext) mNext->MarkAfterJSFinalize();} \
4116 : \
4117 : type_ * get() const {return mPtr;} \
4118 : operator type_ *() const {return mPtr;} \
4119 : type_ * operator->() const {return mPtr;} \
4120 : \
4121 : class_ & operator =(type_ * p) \
4122 : {NS_ASSERTION(mTLS, "Hasn't been init'ed!"); \
4123 : mPtr = p; return *this;} \
4124 : \
4125 : protected: \
4126 : type_ * mPtr; \
4127 : };
4128 :
4129 : // Use the macro above to define our AutoMarking types...
4130 :
4131 36032442 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeInterfacePtr, XPCNativeInterface)
4132 16113154 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeSetPtr, XPCNativeSet)
4133 3726111 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativePtr, XPCWrappedNative)
4134 4529634 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeTearOffPtr, XPCWrappedNativeTearOff)
4135 8273463 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeProtoPtr, XPCWrappedNativeProto)
4136 31555029 : DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingJSVal, XPCMarkableJSVal)
4137 :
4138 : #define DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(class_, type_) \
4139 : class class_ : public AutoMarkingPtr \
4140 : { \
4141 : public: \
4142 : class_ (XPCCallContext& ccx) \
4143 : : AutoMarkingPtr(ccx), mPtr(nsnull), mCount(0) {} \
4144 : class_ (XPCCallContext& ccx, type_** aPtr, PRUint32 aCount, \
4145 : bool aClear = false) \
4146 : : AutoMarkingPtr(ccx), mPtr(aPtr), mCount(aCount) \
4147 : { \
4148 : if (!mPtr) mCount = 0; \
4149 : else if (aClear) memset(mPtr, 0, mCount*sizeof(type_*)); \
4150 : } \
4151 : virtual ~ class_ () {} \
4152 : \
4153 : virtual void TraceJS(JSTracer* trc) \
4154 : { \
4155 : for (PRUint32 i = 0; i < mCount; ++i) { \
4156 : type_* cur = mPtr[i]; \
4157 : if (cur) { \
4158 : cur->TraceJS(trc); \
4159 : cur->AutoTrace(trc); \
4160 : } \
4161 : } \
4162 : if (mNext) mNext->TraceJS(trc); \
4163 : } \
4164 : \
4165 : virtual void MarkAfterJSFinalize() \
4166 : { \
4167 : for (PRUint32 i = 0; i < mCount; ++i) { \
4168 : type_* cur = mPtr[i]; \
4169 : if (cur) \
4170 : cur->Mark(); \
4171 : } \
4172 : if (mNext) mNext->MarkAfterJSFinalize(); \
4173 : } \
4174 : \
4175 : type_ ** get() const {return mPtr;} \
4176 : operator type_ **() const {return mPtr;} \
4177 : type_ ** operator->() const {return mPtr;} \
4178 : \
4179 : class_ & operator =(const class_ & inst) \
4180 : {mPtr = inst.mPtr; mCount = inst.mCount; return *this;} \
4181 : \
4182 : protected: \
4183 : type_ ** mPtr; \
4184 : PRUint32 mCount; \
4185 : };
4186 :
4187 1434832 : DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(AutoMarkingNativeInterfacePtrArrayPtr,
4188 : XPCNativeInterface)
4189 :
4190 : // Note: It looked like I would need one of these AutoMarkingPtr types for
4191 : // XPCNativeScriptableInfo in order to manage marking its
4192 : // XPCNativeScriptableShared member during construction. But AFAICT we build
4193 : // these and bind them to rooted things so immediately that this just is not
4194 : // needed.
4195 :
4196 : #define AUTO_MARK_JSVAL_HELPER2(tok, line) tok##line
4197 : #define AUTO_MARK_JSVAL_HELPER(tok, line) AUTO_MARK_JSVAL_HELPER2(tok, line)
4198 :
4199 : #define AUTO_MARK_JSVAL(ccx, val) \
4200 : XPCMarkableJSVal AUTO_MARK_JSVAL_HELPER(_val_,__LINE__)(val); \
4201 : AutoMarkingJSVal AUTO_MARK_JSVAL_HELPER(_automarker_,__LINE__) \
4202 : (ccx, &AUTO_MARK_JSVAL_HELPER(_val_,__LINE__))
4203 :
4204 : /***************************************************************************/
4205 : // Allocates a string that grants all access ("AllAccess")
4206 :
4207 : extern char* xpc_CloneAllAccess();
4208 : /***************************************************************************/
4209 : // Returns access if wideName is in list
4210 :
4211 : extern char * xpc_CheckAccessList(const PRUnichar* wideName, const char* list[]);
4212 :
4213 : /***************************************************************************/
4214 : // in xpcvariant.cpp...
4215 :
4216 : // {1809FD50-91E8-11d5-90F9-0010A4E73D9A}
4217 : #define XPCVARIANT_IID \
4218 : {0x1809fd50, 0x91e8, 0x11d5, \
4219 : { 0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
4220 :
4221 : // {DC524540-487E-4501-9AC7-AAA784B17C1C}
4222 : #define XPCVARIANT_CID \
4223 : {0xdc524540, 0x487e, 0x4501, \
4224 : { 0x9a, 0xc7, 0xaa, 0xa7, 0x84, 0xb1, 0x7c, 0x1c } }
4225 :
4226 : class XPCVariant : public nsIVariant
4227 : {
4228 : public:
4229 362 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
4230 : NS_DECL_NSIVARIANT
4231 32340 : NS_DECL_CYCLE_COLLECTION_CLASS(XPCVariant)
4232 :
4233 : // If this class ever implements nsIWritableVariant, take special care with
4234 : // the case when mJSVal is JSVAL_STRING, since we don't own the data in
4235 : // that case.
4236 :
4237 : // We #define and iid so that out module local code can use QI to detect
4238 : // if a given nsIVariant is in fact an XPCVariant.
4239 : NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
4240 :
4241 : static XPCVariant* newVariant(XPCCallContext& ccx, jsval aJSVal);
4242 :
4243 : /**
4244 : * This getter clears the gray bit before handing out the jsval if the jsval
4245 : * represents a JSObject. That means that the object is guaranteed to be
4246 : * kept alive past the next CC.
4247 : */
4248 8004 : jsval GetJSVal() const
4249 8004 : {if (!JSVAL_IS_PRIMITIVE(mJSVal))
4250 1537 : xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(mJSVal));
4251 8004 : return mJSVal;}
4252 :
4253 : /**
4254 : * This getter does not change the color of the jsval (if it represents a
4255 : * JSObject) meaning that the value returned is not guaranteed to be kept
4256 : * alive past the next CC.
4257 : *
4258 : * This should only be called if you are certain that the return value won't
4259 : * be passed into a JS API function and that it won't be stored without
4260 : * being rooted (or otherwise signaling the stored value to the CC).
4261 : */
4262 4537 : jsval GetJSValPreserveColor() const {return mJSVal;}
4263 :
4264 : XPCVariant(XPCCallContext& ccx, jsval aJSVal);
4265 :
4266 : /**
4267 : * Convert a variant into a jsval.
4268 : *
4269 : * @param ccx the context for the whole procedure
4270 : * @param variant the variant to convert
4271 : * @param scope the default scope to put on the new JSObject's parent chain
4272 : * @param pErr [out] relevant error code, if any.
4273 : * @param pJSVal [out] the resulting jsval.
4274 : */
4275 : static JSBool VariantDataToJS(XPCLazyCallContext& lccx,
4276 : nsIVariant* variant,
4277 : nsresult* pErr, jsval* pJSVal);
4278 :
4279 0 : bool IsPurple()
4280 : {
4281 0 : return mRefCnt.IsPurple();
4282 : }
4283 :
4284 0 : void RemovePurple()
4285 : {
4286 0 : mRefCnt.RemovePurple();
4287 0 : }
4288 :
4289 0 : void SetCCGeneration(PRUint32 aGen)
4290 : {
4291 0 : mCCGeneration = aGen;
4292 0 : }
4293 :
4294 160 : PRUint32 CCGeneration() { return mCCGeneration; }
4295 : protected:
4296 19136 : virtual ~XPCVariant() { }
4297 :
4298 : JSBool InitializeData(XPCCallContext& ccx);
4299 :
4300 : protected:
4301 : nsDiscriminatedUnion mData;
4302 : jsval mJSVal;
4303 : bool mReturnRawObject : 1;
4304 : PRUint32 mCCGeneration : 31;
4305 : };
4306 :
4307 : NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID)
4308 :
4309 : class XPCTraceableVariant: public XPCVariant,
4310 : public XPCRootSetElem
4311 : {
4312 : public:
4313 3464 : XPCTraceableVariant(XPCCallContext& ccx, jsval aJSVal)
4314 3464 : : XPCVariant(ccx, aJSVal)
4315 : {
4316 3464 : ccx.GetRuntime()->AddVariantRoot(this);
4317 3464 : }
4318 :
4319 : virtual ~XPCTraceableVariant();
4320 :
4321 : void TraceJS(JSTracer* trc);
4322 : #ifdef DEBUG
4323 : static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
4324 : #endif
4325 : };
4326 :
4327 : /***************************************************************************/
4328 :
4329 : #define PRINCIPALHOLDER_IID \
4330 : {0xbf109f49, 0xf94a, 0x43d8, {0x93, 0xdb, 0xe4, 0x66, 0x49, 0xc5, 0xd9, 0x7d}}
4331 :
4332 : class PrincipalHolder : public nsIScriptObjectPrincipal
4333 : {
4334 : public:
4335 : NS_DECLARE_STATIC_IID_ACCESSOR(PRINCIPALHOLDER_IID)
4336 :
4337 1667 : PrincipalHolder(nsIPrincipal *holdee)
4338 1667 : : mHoldee(holdee)
4339 : {
4340 1667 : }
4341 6664 : virtual ~PrincipalHolder() { }
4342 :
4343 : NS_DECL_ISUPPORTS
4344 :
4345 : nsIPrincipal *GetPrincipal();
4346 :
4347 : private:
4348 : nsCOMPtr<nsIPrincipal> mHoldee;
4349 : };
4350 :
4351 : NS_DEFINE_STATIC_IID_ACCESSOR(PrincipalHolder, PRINCIPALHOLDER_IID)
4352 :
4353 : /***************************************************************************/
4354 : // Utilities
4355 :
4356 : inline void *
4357 9807467 : xpc_GetJSPrivate(JSObject *obj)
4358 : {
4359 9807467 : return js::GetObjectPrivate(obj);
4360 : }
4361 :
4362 :
4363 : // Helper for creating a sandbox object to use for evaluating
4364 : // untrusted code completely separated from all other code in the
4365 : // system using xpc_EvalInSandbox(). Takes the JSContext on which to
4366 : // do setup etc on, puts the sandbox object in *vp (which must be
4367 : // rooted by the caller), and uses the principal that's either
4368 : // directly passed in prinOrSop or indirectly as an
4369 : // nsIScriptObjectPrincipal holding the principal. If no principal is
4370 : // reachable through prinOrSop, a new null principal will be created
4371 : // and used.
4372 : nsresult
4373 : xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop,
4374 : JSObject *proto, bool preferXray, const nsACString &sandboxName,
4375 : nsISupports *identityPtr = nsnull);
4376 : // Helper for evaluating scripts in a sandbox object created with
4377 : // xpc_CreateSandboxObject(). The caller is responsible of ensuring
4378 : // that *rval doesn't get collected during the call or usage after the
4379 : // call. This helper will use filename and lineNo for error reporting,
4380 : // and if no filename is provided it will use the codebase from the
4381 : // principal and line number 1 as a fallback. if returnStringOnly is
4382 : // true, then the result in *rval, or the exception in cx->exception
4383 : // will be coerced into strings. If an exception is thrown converting
4384 : // an exception to a string, evalInSandbox will return an NS_ERROR_*
4385 : // result, and cx->exception will be empty.
4386 : nsresult
4387 : xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
4388 : const char *filename, PRInt32 lineNo,
4389 : JSVersion jsVersion, bool returnStringOnly, jsval *rval);
4390 :
4391 : /***************************************************************************/
4392 : // Inlined utilities.
4393 :
4394 : inline JSBool
4395 : xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsid id);
4396 :
4397 : inline jsid
4398 : GetRTIdByIndex(JSContext *cx, unsigned index);
4399 :
4400 : // Wrapper for JS_NewObject to mark the new object as system when parent is
4401 : // also a system object. If uniqueType is specified then a new type object will
4402 : // be created which is used only by the result, so that its property types
4403 : // will be tracked precisely.
4404 : inline JSObject*
4405 : xpc_NewSystemInheritingJSObject(JSContext *cx, JSClass *clasp, JSObject *proto,
4406 : bool uniqueType, JSObject *parent);
4407 :
4408 : nsISupports *
4409 : XPC_GetIdentityObject(JSContext *cx, JSObject *obj);
4410 :
4411 : namespace xpc {
4412 :
4413 : struct CompartmentPrivate
4414 : {
4415 3304 : CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays)
4416 : : key(key),
4417 3304 : wantXrays(wantXrays)
4418 : {
4419 3304 : MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
4420 3304 : }
4421 :
4422 : ~CompartmentPrivate();
4423 :
4424 : nsAutoPtr<PtrAndPrincipalHashKey> key;
4425 : bool wantXrays;
4426 : nsAutoPtr<JSObject2JSObjectMap> waiverWrapperMap;
4427 : // NB: we don't want this map to hold a strong reference to the wrapper.
4428 : nsAutoPtr<nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> > expandoMap;
4429 : nsAutoPtr<nsTHashtable<nsPtrHashKey<JSObject> > > domExpandoMap;
4430 : nsCString location;
4431 :
4432 0 : bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
4433 0 : if (!expandoMap) {
4434 0 : expandoMap = new nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *>();
4435 0 : if (!expandoMap->Init(8)) {
4436 0 : expandoMap = nsnull;
4437 0 : return false;
4438 : }
4439 : }
4440 0 : wn->SetHasExpandoObject();
4441 0 : return expandoMap->Put(wn, expando);
4442 : }
4443 :
4444 : /**
4445 : * This lookup does not change the color of the JSObject meaning that the
4446 : * object returned is not guaranteed to be kept alive past the next CC.
4447 : *
4448 : * This should only be called if you are certain that the return value won't
4449 : * be passed into a JS API function and that it won't be stored without
4450 : * being rooted (or otherwise signaling the stored value to the CC).
4451 : */
4452 0 : JSObject *LookupExpandoObjectPreserveColor(XPCWrappedNative *wn) {
4453 0 : return expandoMap ? expandoMap->Get(wn) : nsnull;
4454 : }
4455 :
4456 : /**
4457 : * This lookup clears the gray bit before handing out the JSObject which
4458 : * means that the object is guaranteed to be kept alive past the next CC.
4459 : */
4460 0 : JSObject *LookupExpandoObject(XPCWrappedNative *wn) {
4461 0 : JSObject *obj = LookupExpandoObjectPreserveColor(wn);
4462 0 : xpc_UnmarkGrayObject(obj);
4463 0 : return obj;
4464 : }
4465 :
4466 0 : bool RegisterDOMExpandoObject(JSObject *expando) {
4467 0 : if (!domExpandoMap) {
4468 0 : domExpandoMap = new nsTHashtable<nsPtrHashKey<JSObject> >();
4469 0 : if (!domExpandoMap->Init(8)) {
4470 0 : domExpandoMap = nsnull;
4471 0 : return false;
4472 : }
4473 : }
4474 0 : return domExpandoMap->PutEntry(expando);
4475 : }
4476 0 : void RemoveDOMExpandoObject(JSObject *expando) {
4477 0 : if (domExpandoMap)
4478 0 : domExpandoMap->RemoveEntry(expando);
4479 0 : }
4480 : };
4481 :
4482 : }
4483 :
4484 : /***************************************************************************/
4485 : // Inlines use the above - include last.
4486 :
4487 : #include "XPCInlines.h"
4488 :
4489 : /***************************************************************************/
4490 : // Maps have inlines that use the above - include last.
4491 :
4492 : #include "XPCMaps.h"
4493 :
4494 : /***************************************************************************/
4495 :
4496 : #endif /* xpcprivate_h___ */
|