LCOV - code coverage report
Current view: directory - js/xpconnect/src - nsXPConnect.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1232 608 49.4 %
Date: 2012-06-02 Functions: 137 89 65.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code, released
      17                 :  * March 31, 1998.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   John Bandhauer <jband@netscape.com> (original author)
      26                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      27                 :  *   Nate Nielsen <nielsen@memberwebs.com>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      31                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : /* High level class and public functions implementation. */
      44                 : 
      45                 : #include "mozilla/Assertions.h"
      46                 : #include "mozilla/Base64.h"
      47                 : #include "mozilla/Util.h"
      48                 : 
      49                 : #include "xpcprivate.h"
      50                 : #include "XPCWrapper.h"
      51                 : #include "nsBaseHashtable.h"
      52                 : #include "nsHashKeys.h"
      53                 : #include "jsatom.h"
      54                 : #include "jsfriendapi.h"
      55                 : #include "jsgc.h"
      56                 : #include "dom_quickstubs.h"
      57                 : #include "nsNullPrincipal.h"
      58                 : #include "nsIURI.h"
      59                 : #include "nsJSEnvironment.h"
      60                 : #include "nsThreadUtils.h"
      61                 : 
      62                 : #include "XrayWrapper.h"
      63                 : #include "WrapperFactory.h"
      64                 : #include "AccessCheck.h"
      65                 : 
      66                 : #include "jsdIDebuggerService.h"
      67                 : 
      68                 : #include "XPCQuickStubs.h"
      69                 : #include "dombindings.h"
      70                 : 
      71                 : #include "nsWrapperCacheInlines.h"
      72                 : 
      73        10425367 : NS_IMPL_THREADSAFE_ISUPPORTS7(nsXPConnect,
      74                 :                               nsIXPConnect,
      75                 :                               nsISupportsWeakReference,
      76                 :                               nsIThreadObserver,
      77                 :                               nsIJSRuntimeService,
      78                 :                               nsIJSContextStack,
      79                 :                               nsIThreadJSContextStack,
      80                 :                               nsIJSEngineTelemetryStats)
      81                 : 
      82                 : nsXPConnect* nsXPConnect::gSelf = nsnull;
      83                 : JSBool       nsXPConnect::gOnceAliveNowDead = false;
      84                 : PRUint32     nsXPConnect::gReportAllJSExceptions = 0;
      85                 : JSBool       nsXPConnect::gDebugMode = false;
      86                 : JSBool       nsXPConnect::gDesiredDebugMode = false;
      87                 : 
      88                 : // Global cache of the default script security manager (QI'd to
      89                 : // nsIScriptSecurityManager)
      90                 : nsIScriptSecurityManager *nsXPConnect::gScriptSecurityManager = nsnull;
      91                 : 
      92                 : const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1";
      93                 : const char XPC_RUNTIME_CONTRACTID[]       = "@mozilla.org/js/xpc/RuntimeService;1";
      94                 : const char XPC_EXCEPTION_CONTRACTID[]     = "@mozilla.org/js/xpc/Exception;1";
      95                 : const char XPC_CONSOLE_CONTRACTID[]       = "@mozilla.org/consoleservice;1";
      96                 : const char XPC_SCRIPT_ERROR_CONTRACTID[]  = "@mozilla.org/scripterror;1";
      97                 : const char XPC_ID_CONTRACTID[]            = "@mozilla.org/js/xpc/ID;1";
      98                 : const char XPC_XPCONNECT_CONTRACTID[]     = "@mozilla.org/js/xpc/XPConnect;1";
      99                 : 
     100                 : /***************************************************************************/
     101                 : 
     102            1404 : nsXPConnect::nsXPConnect()
     103                 :     :   mRuntime(nsnull),
     104                 :         mInterfaceInfoManager(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)),
     105                 :         mDefaultSecurityManager(nsnull),
     106                 :         mDefaultSecurityManagerFlags(0),
     107                 :         mShuttingDown(false),
     108                 :         mNeedGCBeforeCC(true),
     109                 :         mEventDepth(0),
     110            1404 :         mCycleCollectionContext(nsnull)
     111                 : {
     112            1404 :     mRuntime = XPCJSRuntime::newXPCJSRuntime(this);
     113                 : 
     114            1404 :     nsCycleCollector_registerRuntime(nsIProgrammingLanguage::JAVASCRIPT, this);
     115                 : #ifdef DEBUG_CC
     116                 :     mJSRoots.ops = nsnull;
     117                 : #endif
     118                 : 
     119            1404 :     char* reportableEnv = PR_GetEnv("MOZ_REPORT_ALL_JS_EXCEPTIONS");
     120            1404 :     if (reportableEnv && *reportableEnv)
     121               0 :         gReportAllJSExceptions = 1;
     122            1404 : }
     123                 : 
     124            4209 : nsXPConnect::~nsXPConnect()
     125                 : {
     126            1403 :     nsCycleCollector_forgetRuntime(nsIProgrammingLanguage::JAVASCRIPT);
     127                 : 
     128            1403 :     JSContext *cx = nsnull;
     129            1403 :     if (mRuntime) {
     130                 :         // Create our own JSContext rather than an XPCCallContext, since
     131                 :         // otherwise we will create a new safe JS context and attach a
     132                 :         // components object that won't get GCed.
     133                 :         // And do this before calling CleanupAllThreads, so that we
     134                 :         // don't create an extra xpcPerThreadData.
     135            1403 :         cx = JS_NewContext(mRuntime->GetJSRuntime(), 8192);
     136                 :     }
     137                 : 
     138            1403 :     XPCPerThreadData::CleanupAllThreads();
     139            1403 :     mShuttingDown = true;
     140            1403 :     if (cx) {
     141                 :         // XXX Call even if |mRuntime| null?
     142            1403 :         XPCWrappedNativeScope::SystemIsBeingShutDown();
     143                 : 
     144            1403 :         mRuntime->SystemIsBeingShutDown();
     145            1403 :         JS_DestroyContext(cx);
     146                 :     }
     147                 : 
     148            1403 :     NS_IF_RELEASE(mDefaultSecurityManager);
     149                 : 
     150            1403 :     gScriptSecurityManager = nsnull;
     151                 : 
     152                 :     // shutdown the logging system
     153            1403 :     XPC_LOG_FINISH();
     154                 : 
     155            1403 :     delete mRuntime;
     156                 : 
     157            1403 :     gSelf = nsnull;
     158            1403 :     gOnceAliveNowDead = true;
     159            5612 : }
     160                 : 
     161                 : // static
     162                 : nsXPConnect*
     163        18723706 : nsXPConnect::GetXPConnect()
     164                 : {
     165                 :     // Do a release-mode assert that we're not doing anything significant in
     166                 :     // XPConnect off the main thread. If you're an extension developer hitting
     167                 :     // this, you need to change your code. See bug 716167.
     168        18723706 :     if (!NS_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
     169               0 :         MOZ_Assert("NS_IsMainThread()", __FILE__, __LINE__);
     170                 : 
     171        18723706 :     if (!gSelf) {
     172            1404 :         if (gOnceAliveNowDead)
     173               0 :             return nsnull;
     174            1404 :         gSelf = new nsXPConnect();
     175            1404 :         if (!gSelf)
     176               0 :             return nsnull;
     177                 : 
     178            1404 :         if (!gSelf->mRuntime) {
     179               0 :             NS_RUNTIMEABORT("Couldn't create XPCJSRuntime.");
     180                 :         }
     181            1404 :         if (!gSelf->mInterfaceInfoManager) {
     182               0 :             NS_RUNTIMEABORT("Couldn't get global interface info manager.");
     183                 :         }
     184                 : 
     185                 :         // Initial extra ref to keep the singleton alive
     186                 :         // balanced by explicit call to ReleaseXPConnectSingleton()
     187            1404 :         NS_ADDREF(gSelf);
     188                 : 
     189                 :         // Add XPConnect as an thread observer.
     190                 :         //
     191                 :         // The cycle collector sometimes calls GetXPConnect, but it should never
     192                 :         // be the one that initializes gSelf.
     193            1404 :         MOZ_ASSERT(NS_IsMainThread());
     194            2808 :         nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
     195            1404 :         if (NS_FAILED(thread->AddObserver(gSelf))) {
     196               0 :             NS_RELEASE(gSelf);
     197                 :             // Fall through to returning null
     198                 :         }
     199                 :     }
     200        18723706 :     return gSelf;
     201                 : }
     202                 : 
     203                 : // static
     204                 : nsXPConnect*
     205            1403 : nsXPConnect::GetSingleton()
     206                 : {
     207            1403 :     nsXPConnect* xpc = nsXPConnect::GetXPConnect();
     208            1403 :     NS_IF_ADDREF(xpc);
     209            1403 :     return xpc;
     210                 : }
     211                 : 
     212                 : // static
     213                 : void
     214            1404 : nsXPConnect::ReleaseXPConnectSingleton()
     215                 : {
     216            1404 :     nsXPConnect* xpc = gSelf;
     217            1404 :     if (xpc) {
     218                 : 
     219                 :         // The thread subsystem may have been shut down already, so make sure
     220                 :         // to check for null here.
     221            2808 :         nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
     222            1404 :         if (thread) {
     223               0 :             MOZ_ASSERT(NS_IsMainThread());
     224               0 :             thread->RemoveObserver(xpc);
     225                 :         }
     226                 : 
     227                 : #ifdef DEBUG
     228                 :         // force a dump of the JavaScript gc heap if JS is still alive
     229                 :         // if requested through XPC_SHUTDOWN_HEAP_DUMP environment variable
     230                 :         {
     231            1404 :             const char* dumpName = getenv("XPC_SHUTDOWN_HEAP_DUMP");
     232            1404 :             if (dumpName) {
     233                 :                 FILE* dumpFile = (*dumpName == '\0' ||
     234               0 :                                   strcmp(dumpName, "stdout") == 0)
     235                 :                                  ? stdout
     236               0 :                                  : fopen(dumpName, "w");
     237               0 :                 if (dumpFile) {
     238                 :                     JS_DumpHeap(xpc->GetRuntime()->GetJSRuntime(), dumpFile, nsnull,
     239               0 :                                 JSTRACE_OBJECT, nsnull, static_cast<size_t>(-1), nsnull);
     240               0 :                     if (dumpFile != stdout)
     241               0 :                         fclose(dumpFile);
     242                 :                 }
     243                 :             }
     244                 :         }
     245                 : #endif
     246                 : #ifdef XPC_DUMP_AT_SHUTDOWN
     247                 :         // NOTE: to see really interesting stuff turn on the prlog stuff.
     248                 :         // See the comment at the top of XPCLog.h to see how to do that.
     249                 :         xpc->DebugDump(7);
     250                 : #endif
     251                 :         nsrefcnt cnt;
     252            1404 :         NS_RELEASE2(xpc, cnt);
     253                 : #ifdef XPC_DUMP_AT_SHUTDOWN
     254                 :         if (0 != cnt)
     255                 :             printf("*** dangling reference to nsXPConnect: refcnt=%d\n", cnt);
     256                 :         else
     257                 :             printf("+++ XPConnect had no dangling references.\n");
     258                 : #endif
     259                 :     }
     260            1404 : }
     261                 : 
     262                 : // static
     263                 : nsresult
     264               0 : nsXPConnect::GetInterfaceInfoManager(nsIInterfaceInfoSuperManager** iim,
     265                 :                                      nsXPConnect* xpc /*= nsnull*/)
     266                 : {
     267               0 :     if (!xpc && !(xpc = GetXPConnect()))
     268               0 :         return NS_ERROR_FAILURE;
     269                 : 
     270               0 :     *iim = xpc->mInterfaceInfoManager;
     271               0 :     NS_IF_ADDREF(*iim);
     272               0 :     return NS_OK;
     273                 : }
     274                 : 
     275                 : // static
     276                 : XPCJSRuntime*
     277         2041731 : nsXPConnect::GetRuntimeInstance()
     278                 : {
     279         2041731 :     nsXPConnect* xpc = GetXPConnect();
     280         2041731 :     NS_ASSERTION(xpc, "Must not be called if XPC failed to initialize");
     281         2041731 :     return xpc->GetRuntime();
     282                 : }
     283                 : 
     284                 : // static
     285                 : JSBool
     286          160071 : nsXPConnect::IsISupportsDescendant(nsIInterfaceInfo* info)
     287                 : {
     288          160071 :     bool found = false;
     289          160071 :     if (info)
     290          160071 :         info->HasAncestor(&NS_GET_IID(nsISupports), &found);
     291          160071 :     return found;
     292                 : }
     293                 : 
     294                 : /***************************************************************************/
     295                 : 
     296                 : typedef bool (*InfoTester)(nsIInterfaceInfoManager* manager, const void* data,
     297                 :                            nsIInterfaceInfo** info);
     298                 : 
     299          308493 : static bool IIDTester(nsIInterfaceInfoManager* manager, const void* data,
     300                 :                       nsIInterfaceInfo** info)
     301                 : {
     302          308493 :     return NS_SUCCEEDED(manager->GetInfoForIID((const nsIID *) data, info)) &&
     303          308493 :            *info;
     304                 : }
     305                 : 
     306            5400 : static bool NameTester(nsIInterfaceInfoManager* manager, const void* data,
     307                 :                        nsIInterfaceInfo** info)
     308                 : {
     309            5400 :     return NS_SUCCEEDED(manager->GetInfoForName((const char *) data, info)) &&
     310            5400 :            *info;
     311                 : }
     312                 : 
     313          313893 : static nsresult FindInfo(InfoTester tester, const void* data,
     314                 :                          nsIInterfaceInfoSuperManager* iism,
     315                 :                          nsIInterfaceInfo** info)
     316                 : {
     317          313893 :     if (tester(iism, data, info))
     318          306454 :         return NS_OK;
     319                 : 
     320                 :     // If not found, then let's ask additional managers.
     321                 : 
     322                 :     bool yes;
     323           14878 :     nsCOMPtr<nsISimpleEnumerator> list;
     324                 : 
     325           14878 :     if (NS_SUCCEEDED(iism->HasAdditionalManagers(&yes)) && yes &&
     326            7439 :         NS_SUCCEEDED(iism->EnumerateAdditionalManagers(getter_AddRefs(list))) &&
     327               0 :         list) {
     328                 :         bool more;
     329               0 :         nsCOMPtr<nsIInterfaceInfoManager> current;
     330                 : 
     331               0 :         while (NS_SUCCEEDED(list->HasMoreElements(&more)) && more &&
     332               0 :                NS_SUCCEEDED(list->GetNext(getter_AddRefs(current))) && current) {
     333               0 :             if (tester(current, data, info))
     334               0 :                 return NS_OK;
     335                 :         }
     336                 :     }
     337                 : 
     338            7439 :     return NS_ERROR_NO_INTERFACE;
     339                 : }
     340                 : 
     341                 : nsresult
     342          308493 : nsXPConnect::GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info)
     343                 : {
     344          308493 :     return FindInfo(IIDTester, aIID, mInterfaceInfoManager, info);
     345                 : }
     346                 : 
     347                 : nsresult
     348            5400 : nsXPConnect::GetInfoForName(const char * name, nsIInterfaceInfo** info)
     349                 : {
     350            5400 :     return FindInfo(NameTester, name, mInterfaceInfoManager, info);
     351                 : }
     352                 : 
     353                 : bool
     354              48 : nsXPConnect::NeedCollect()
     355                 : {
     356              48 :     return !!mNeedGCBeforeCC;
     357                 : }
     358                 : 
     359                 : void
     360            1868 : nsXPConnect::Collect(PRUint32 reason, PRUint32 kind)
     361                 : {
     362                 :     // We're dividing JS objects into 2 categories:
     363                 :     //
     364                 :     // 1. "real" roots, held by the JS engine itself or rooted through the root
     365                 :     //    and lock JS APIs. Roots from this category are considered black in the
     366                 :     //    cycle collector, any cycle they participate in is uncollectable.
     367                 :     //
     368                 :     // 2. roots held by C++ objects that participate in cycle collection,
     369                 :     //    held by XPConnect (see XPCJSRuntime::TraceXPConnectRoots). Roots from
     370                 :     //    this category are considered grey in the cycle collector, their final
     371                 :     //    color depends on the objects that hold them.
     372                 :     //
     373                 :     // Note that if a root is in both categories it is the fact that it is in
     374                 :     // category 1 that takes precedence, so it will be considered black.
     375                 :     //
     376                 :     // During garbage collection we switch to an additional mark color (gray)
     377                 :     // when tracing inside TraceXPConnectRoots. This allows us to walk those
     378                 :     // roots later on and add all objects reachable only from them to the
     379                 :     // cycle collector.
     380                 :     //
     381                 :     // Phases:
     382                 :     //
     383                 :     // 1. marking of the roots in category 1 by having the JS GC do its marking
     384                 :     // 2. marking of the roots in category 2 by XPCJSRuntime::TraceXPConnectRoots
     385                 :     //    using an additional color (gray).
     386                 :     // 3. end of GC, GC can sweep its heap
     387                 :     //
     388                 :     // At some later point, when the cycle collector runs:
     389                 :     //
     390                 :     // 4. walk gray objects and add them to the cycle collector, cycle collect
     391                 :     //
     392                 :     // JS objects that are part of cycles the cycle collector breaks will be
     393                 :     // collected by the next JS.
     394                 :     //
     395                 :     // If DEBUG_CC is not defined the cycle collector will not traverse roots
     396                 :     // from category 1 or any JS objects held by them. Any JS objects they hold
     397                 :     // will already be marked by the JS GC and will thus be colored black
     398                 :     // themselves. Any C++ objects they hold will have a missing (untraversed)
     399                 :     // edge from the JS object to the C++ object and so it will be marked black
     400                 :     // too. This decreases the number of objects that the cycle collector has to
     401                 :     // deal with.
     402                 :     // To improve debugging, if DEBUG_CC is defined all JS objects are
     403                 :     // traversed.
     404                 : 
     405            3736 :     XPCCallContext ccx(NATIVE_CALLER);
     406            1868 :     if (!ccx.IsValid())
     407                 :         return;
     408                 : 
     409            1868 :     JSContext *cx = ccx.GetJSContext();
     410                 : 
     411                 :     // We want to scan the current thread for GC roots only if it was in a
     412                 :     // request prior to the Collect call to avoid false positives during the
     413                 :     // cycle collection. So to compensate for JS_BeginRequest in
     414                 :     // XPCCallContext::Init we disable the conservative scanner if that call
     415                 :     // has started the request on this thread.
     416            3736 :     js::AutoSkipConservativeScan ascs(cx);
     417            1868 :     MOZ_ASSERT(reason < js::gcreason::NUM_REASONS);
     418            1868 :     js::gcreason::Reason gcreason = (js::gcreason::Reason)reason;
     419            1868 :     if (kind == nsGCShrinking) {
     420               0 :         js::ShrinkingGC(cx, gcreason);
     421            1868 :     } else if (kind == nsGCIncremental) {
     422               4 :         js::IncrementalGC(cx, gcreason);
     423                 :     } else {
     424            1864 :         MOZ_ASSERT(kind == nsGCNormal);
     425            1864 :         js::GCForReason(cx, gcreason);
     426                 :     }
     427                 : }
     428                 : 
     429                 : NS_IMETHODIMP
     430               4 : nsXPConnect::GarbageCollect(PRUint32 reason, PRUint32 kind)
     431                 : {
     432               4 :     Collect(reason, kind);
     433               4 :     return NS_OK;
     434                 : }
     435                 : 
     436                 : #ifdef DEBUG_CC
     437                 : struct NoteJSRootTracer : public JSTracer
     438                 : {
     439                 :     NoteJSRootTracer(PLDHashTable *aObjects,
     440                 :                      nsCycleCollectionTraversalCallback& cb)
     441                 :       : mObjects(aObjects),
     442                 :         mCb(cb)
     443                 :     {
     444                 :     }
     445                 :     PLDHashTable* mObjects;
     446                 :     nsCycleCollectionTraversalCallback& mCb;
     447                 : };
     448                 : 
     449                 : static void
     450                 : NoteJSRoot(JSTracer *trc, void *thing, JSGCTraceKind kind)
     451                 : {
     452                 :     if (AddToCCKind(kind)) {
     453                 :         NoteJSRootTracer *tracer = static_cast<NoteJSRootTracer*>(trc);
     454                 :         PLDHashEntryHdr *entry = PL_DHashTableOperate(tracer->mObjects, thing,
     455                 :                                                       PL_DHASH_ADD);
     456                 :         if (entry && !reinterpret_cast<PLDHashEntryStub*>(entry)->key) {
     457                 :             reinterpret_cast<PLDHashEntryStub*>(entry)->key = thing;
     458                 :             tracer->mCb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, thing,
     459                 :                                  nsXPConnect::GetXPConnect());
     460                 :         }
     461                 :     } else if (kind != JSTRACE_STRING) {
     462                 :         JS_TraceChildren(trc, thing, kind);
     463                 :     }
     464                 : }
     465                 : #endif
     466                 : 
     467                 : struct NoteWeakMapChildrenTracer : public JSTracer
     468                 : {
     469            1910 :     NoteWeakMapChildrenTracer(nsCycleCollectionTraversalCallback &cb)
     470            1910 :         : mCb(cb)
     471                 :     {
     472            1910 :     }
     473                 :     nsCycleCollectionTraversalCallback &mCb;
     474                 :     JSObject *mMap;
     475                 :     void *mKey;
     476                 : };
     477                 : 
     478                 : static void
     479               0 : TraceWeakMappingChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
     480                 : {
     481               0 :     MOZ_ASSERT(trc->callback == TraceWeakMappingChild);
     482               0 :     void *thing = *thingp;
     483                 :     NoteWeakMapChildrenTracer *tracer =
     484               0 :         static_cast<NoteWeakMapChildrenTracer *>(trc);
     485               0 :     if (kind == JSTRACE_STRING)
     486               0 :         return;
     487               0 :     if (!xpc_IsGrayGCThing(thing) && !tracer->mCb.WantAllTraces())
     488               0 :         return;
     489               0 :     if (AddToCCKind(kind)) {
     490               0 :         tracer->mCb.NoteWeakMapping(tracer->mMap, tracer->mKey, thing);
     491                 :     } else {
     492               0 :         JS_TraceChildren(trc, thing, kind);
     493                 :     }
     494                 : }
     495                 : 
     496                 : struct NoteWeakMapsTracer : public js::WeakMapTracer
     497                 : {
     498            1910 :     NoteWeakMapsTracer(JSRuntime *rt, js::WeakMapTraceCallback cb,
     499                 :                        nsCycleCollectionTraversalCallback &cccb)
     500            1910 :       : js::WeakMapTracer(rt, cb), mCb(cccb), mChildTracer(cccb)
     501                 :     {
     502            1910 :         JS_TracerInit(&mChildTracer, rt, TraceWeakMappingChild);
     503            1910 :     }
     504                 :     nsCycleCollectionTraversalCallback &mCb;
     505                 :     NoteWeakMapChildrenTracer mChildTracer;
     506                 : };
     507                 : 
     508                 : static void
     509               0 : TraceWeakMapping(js::WeakMapTracer *trc, JSObject *m, 
     510                 :                  void *k, JSGCTraceKind kkind,
     511                 :                  void *v, JSGCTraceKind vkind)
     512                 : {
     513               0 :     MOZ_ASSERT(trc->callback == TraceWeakMapping);
     514               0 :     NoteWeakMapsTracer *tracer = static_cast<NoteWeakMapsTracer *>(trc);
     515               0 :     if (vkind == JSTRACE_STRING)
     516               0 :         return;
     517               0 :     if (!xpc_IsGrayGCThing(v) && !tracer->mCb.WantAllTraces())
     518               0 :         return;
     519                 : 
     520                 :     // The cycle collector can only properly reason about weak maps if it can
     521                 :     // reason about the liveness of their keys, which in turn requires that
     522                 :     // the key can be represented in the cycle collector graph.  All existing
     523                 :     // uses of weak maps use either objects or scripts as keys, which are okay.
     524               0 :     MOZ_ASSERT(AddToCCKind(kkind));
     525                 : 
     526                 :     // As an emergency fallback for non-debug builds, if the key is not
     527                 :     // representable in the cycle collector graph, we treat it as marked.  This
     528                 :     // can cause leaks, but is preferable to ignoring the binding, which could
     529                 :     // cause the cycle collector to free live objects.
     530               0 :     if (!AddToCCKind(kkind))
     531               0 :         k = nsnull;
     532                 : 
     533               0 :     if (AddToCCKind(vkind)) {
     534               0 :         tracer->mCb.NoteWeakMapping(m, k, v);
     535                 :     } else {
     536               0 :         tracer->mChildTracer.mMap = m;
     537               0 :         tracer->mChildTracer.mKey = k;
     538               0 :         JS_TraceChildren(&tracer->mChildTracer, v, vkind);
     539                 :     }
     540                 : }
     541                 : 
     542                 : nsresult
     543            1910 : nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
     544                 :                                   bool explainLiveExpectedGarbage)
     545                 : {
     546                 :     // It is important not to call GetSafeJSContext while on the
     547                 :     // cycle-collector thread since this context will be destroyed
     548                 :     // asynchronously and race with the main thread. In particular, we must
     549                 :     // ensure that a context is passed to the XPCCallContext constructor.
     550            1910 :     JSContext *cx = mRuntime->GetJSCycleCollectionContext();
     551            1910 :     if (!cx)
     552               0 :         return NS_ERROR_OUT_OF_MEMORY;
     553                 : 
     554            1910 :     NS_ASSERTION(!mCycleCollectionContext, "Didn't call FinishTraverse?");
     555            3820 :     mCycleCollectionContext = new XPCCallContext(NATIVE_CALLER, cx);
     556            1910 :     if (!mCycleCollectionContext->IsValid()) {
     557               0 :         mCycleCollectionContext = nsnull;
     558               0 :         return NS_ERROR_FAILURE;
     559                 :     }
     560                 : 
     561                 :     static bool gcHasRun = false;
     562            1910 :     if (!gcHasRun) {
     563            1404 :         JSRuntime* rt = GetRuntime()->GetJSRuntime();
     564            1404 :         uint32_t gcNumber = JS_GetGCParameter(rt, JSGC_NUMBER);
     565            1404 :         if (!gcNumber)
     566               0 :             NS_RUNTIMEABORT("Cannot cycle collect if GC has not run first!");
     567            1404 :         gcHasRun = true;
     568                 :     }
     569                 : 
     570                 : #ifdef DEBUG_CC
     571                 :     NS_ASSERTION(!mJSRoots.ops, "Didn't call FinishCycleCollection?");
     572                 : 
     573                 :     if (explainLiveExpectedGarbage) {
     574                 :         // Being called from nsCycleCollector::ExplainLiveExpectedGarbage.
     575                 : 
     576                 :         // Record all objects held by the JS runtime. This avoids doing a
     577                 :         // complete GC if we're just tracing to explain (from
     578                 :         // ExplainLiveExpectedGarbage), which makes the results of cycle
     579                 :         // collection identical for DEBUG_CC and non-DEBUG_CC builds.
     580                 :         if (!PL_DHashTableInit(&mJSRoots, PL_DHashGetStubOps(), nsnull,
     581                 :                                sizeof(PLDHashEntryStub), PL_DHASH_MIN_SIZE)) {
     582                 :             mJSRoots.ops = nsnull;
     583                 : 
     584                 :             return NS_ERROR_OUT_OF_MEMORY;
     585                 :         }
     586                 : 
     587                 :         NoteJSRootTracer trc(&mJSRoots, cb);
     588                 :         JS_TracerInit(&trc, mCycleCollectionContext->GetJSContext(), NoteJSRoot);
     589                 :         JS_TraceRuntime(&trc);
     590                 :     }
     591                 : #else
     592            1910 :     NS_ASSERTION(!explainLiveExpectedGarbage, "Didn't call nsXPConnect::Collect()?");
     593                 : #endif
     594                 : 
     595            1910 :     GetRuntime()->AddXPConnectRoots(cb);
     596                 :  
     597            1910 :     NoteWeakMapsTracer trc(GetRuntime()->GetJSRuntime(), TraceWeakMapping, cb);
     598            1910 :     js::TraceWeakMaps(&trc);
     599                 : 
     600            1910 :     return NS_OK;
     601                 : }
     602                 : 
     603                 : bool
     604              48 : nsXPConnect::NotifyLeaveMainThread()
     605                 : {
     606              48 :     NS_ABORT_IF_FALSE(NS_IsMainThread(), "Off main thread");
     607              48 :     JSRuntime *rt = mRuntime->GetJSRuntime();
     608              48 :     if (JS_IsInRequest(rt) || JS_IsInSuspendedRequest(rt))
     609              45 :         return false;
     610               3 :     JS_ClearRuntimeThread(rt);
     611               3 :     return true;
     612                 : }
     613                 : 
     614                 : void
     615               3 : nsXPConnect::NotifyEnterCycleCollectionThread()
     616                 : {
     617               3 :     NS_ABORT_IF_FALSE(!NS_IsMainThread(), "On main thread");
     618               3 :     JS_SetRuntimeThread(mRuntime->GetJSRuntime());
     619               3 : }
     620                 : 
     621                 : void
     622               3 : nsXPConnect::NotifyLeaveCycleCollectionThread()
     623                 : {
     624               3 :     NS_ABORT_IF_FALSE(!NS_IsMainThread(), "On main thread");
     625               3 :     JS_ClearRuntimeThread(mRuntime->GetJSRuntime());
     626               3 : }
     627                 : 
     628                 : void
     629               3 : nsXPConnect::NotifyEnterMainThread()
     630                 : {
     631               3 :     NS_ABORT_IF_FALSE(NS_IsMainThread(), "Off main thread");
     632               3 :     JS_SetRuntimeThread(mRuntime->GetJSRuntime());
     633               3 : }
     634                 : 
     635                 : nsresult
     636            1910 : nsXPConnect::FinishTraverse()
     637                 : {
     638            1910 :     if (mCycleCollectionContext)
     639            1910 :         mCycleCollectionContext = nsnull;
     640            1910 :     return NS_OK;
     641                 : }
     642                 : 
     643                 : nsresult
     644            1910 : nsXPConnect::FinishCycleCollection()
     645                 : {
     646                 : #ifdef DEBUG_CC
     647                 :     if (mJSRoots.ops) {
     648                 :         PL_DHashTableFinish(&mJSRoots);
     649                 :         mJSRoots.ops = nsnull;
     650                 :     }
     651                 : #endif
     652                 : 
     653            1910 :     return NS_OK;
     654                 : }
     655                 : 
     656                 : nsCycleCollectionParticipant *
     657         1352183 : nsXPConnect::ToParticipant(void *p)
     658                 : {
     659         1352183 :     if (!AddToCCKind(js_GetGCThingTraceKind(p)))
     660               0 :         return NULL;
     661         1352183 :     return this;
     662                 : }
     663                 : 
     664                 : NS_IMETHODIMP
     665           25671 : nsXPConnect::Root(void *p)
     666                 : {
     667           25671 :     return NS_OK;
     668                 : }
     669                 : 
     670                 : #ifdef DEBUG_CC
     671                 : void
     672                 : nsXPConnect::PrintAllReferencesTo(void *p)
     673                 : {
     674                 : #ifdef DEBUG
     675                 :     XPCCallContext ccx(NATIVE_CALLER);
     676                 :     if (ccx.IsValid())
     677                 :         JS_DumpHeap(ccx.GetJSContext(), stdout, nsnull, 0, p,
     678                 :                     0x7fffffff, nsnull);
     679                 : #endif
     680                 : }
     681                 : #endif
     682                 : 
     683                 : NS_IMETHODIMP
     684           25671 : nsXPConnect::Unlink(void *p)
     685                 : {
     686           25671 :     return NS_OK;
     687                 : }
     688                 : 
     689                 : NS_IMETHODIMP
     690           25671 : nsXPConnect::Unroot(void *p)
     691                 : {
     692           25671 :     return NS_OK;
     693                 : }
     694                 : 
     695                 : JSBool
     696         1357230 : xpc_GCThingIsGrayCCThing(void *thing)
     697                 : {
     698         1357230 :     return AddToCCKind(js_GetGCThingTraceKind(thing)) &&
     699         1357230 :            xpc_IsGrayGCThing(thing);
     700                 : }
     701                 : 
     702                 : struct UnmarkGrayTracer : public JSTracer
     703                 : {
     704            5600 :     UnmarkGrayTracer() : mTracingShape(false), mPreviousShape(nsnull) {}
     705          207798 :     UnmarkGrayTracer(JSTracer *trc, bool aTracingShape)
     706          207798 :         : mTracingShape(aTracingShape), mPreviousShape(nsnull)
     707                 :     {
     708          207798 :         JS_TracerInit(this, trc->runtime, trc->callback);
     709          207798 :     }
     710                 :     bool mTracingShape; // true iff we are tracing the immediate children of a shape
     711                 :     void *mPreviousShape; // If mTracingShape, shape child or NULL. Otherwise, NULL.
     712                 : };
     713                 : 
     714                 : /*
     715                 :  * The GC and CC are run independently. Consequently, the following sequence of
     716                 :  * events can occur:
     717                 :  * 1. GC runs and marks an object gray.
     718                 :  * 2. Some JS code runs that creates a pointer from a JS root to the gray
     719                 :  *    object. If we re-ran a GC at this point, the object would now be black.
     720                 :  * 3. Now we run the CC. It may think it can collect the gray object, even
     721                 :  *    though it's reachable from the JS heap.
     722                 :  *
     723                 :  * To prevent this badness, we unmark the gray bit of an object when it is
     724                 :  * accessed by callers outside XPConnect. This would cause the object to go
     725                 :  * black in step 2 above. This must be done on everything reachable from the
     726                 :  * object being returned. The following code takes care of the recursive
     727                 :  * re-coloring.
     728                 :  */
     729                 : static void
     730          689878 : UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind)
     731                 : {
     732          689878 :     void *thing = *thingp;
     733                 :     int stackDummy;
     734          689878 :     if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(trc->runtime), &stackDummy)) {
     735                 :         /*
     736                 :          * If we run out of stack, we take a more drastic measure: require that
     737                 :          * we GC again before the next CC.
     738                 :          */
     739               0 :         nsXPConnect* xpc = nsXPConnect::GetXPConnect();
     740               0 :         xpc->EnsureGCBeforeCC();
     741               0 :         return;
     742                 :     }
     743                 : 
     744          689878 :     if (!xpc_IsGrayGCThing(thing))
     745          482080 :         return;
     746                 : 
     747          207798 :     static_cast<js::gc::Cell *>(thing)->unmark(js::gc::GRAY);
     748                 : 
     749                 :     /*
     750                 :      * Trace children of |thing|. If |thing| and its parent are both shapes, |thing| will
     751                 :      * get saved to mPreviousShape without being traced. The parent will later
     752                 :      * trace |thing|. This is done to avoid increasing the stack depth during shape
     753                 :      * tracing. It is safe to do because a shape can only have one child that is a shape.
     754                 :      */
     755          207798 :     UnmarkGrayTracer *tracer = static_cast<UnmarkGrayTracer*>(trc);
     756          207798 :     UnmarkGrayTracer childTracer(tracer, kind == JSTRACE_SHAPE);
     757                 : 
     758          207798 :     if (kind != JSTRACE_SHAPE) {
     759          122627 :         JS_TraceChildren(&childTracer, thing, kind);
     760          122627 :         MOZ_ASSERT(!childTracer.mPreviousShape);
     761          122627 :         return;
     762                 :     }
     763                 : 
     764           85171 :     if (tracer->mTracingShape) {
     765           64963 :         MOZ_ASSERT(!tracer->mPreviousShape);
     766           64963 :         tracer->mPreviousShape = thing;
     767           64963 :         return;
     768                 :     }
     769                 : 
     770           85171 :     do {
     771           85171 :         MOZ_ASSERT(!xpc_IsGrayGCThing(thing));
     772           85171 :         JS_TraceChildren(&childTracer, thing, JSTRACE_SHAPE);
     773           85171 :         thing = childTracer.mPreviousShape;
     774           85171 :         childTracer.mPreviousShape = nsnull;
     775                 :     } while (thing);
     776                 : }
     777                 : 
     778                 : void
     779            5600 : xpc_UnmarkGrayObjectRecursive(JSObject *obj)
     780                 : {
     781            5600 :     NS_ASSERTION(obj, "Don't pass me null!");
     782                 : 
     783                 :     // Unmark.
     784            5600 :     js::gc::AsCell(obj)->unmark(js::gc::GRAY);
     785                 : 
     786                 :     // Trace children.
     787            5600 :     UnmarkGrayTracer trc;
     788            5600 :     JS_TracerInit(&trc, JS_GetObjectRuntime(obj), UnmarkGrayChildren);
     789            5600 :     JS_TraceChildren(&trc, obj, JSTRACE_OBJECT);
     790            5600 : }
     791                 : 
     792                 : struct TraversalTracer : public JSTracer
     793                 : {
     794          452318 :     TraversalTracer(nsCycleCollectionTraversalCallback &aCb) : cb(aCb)
     795                 :     {
     796          452318 :     }
     797                 :     nsCycleCollectionTraversalCallback &cb;
     798                 : };
     799                 : 
     800                 : static void
     801         3659381 : NoteJSChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
     802                 : {
     803         3659381 :     TraversalTracer *tracer = static_cast<TraversalTracer*>(trc);
     804         3659381 :     void *thing = *thingp;
     805                 : 
     806                 :     // Don't traverse non-gray objects, unless we want all traces.
     807         3659381 :     if (!xpc_IsGrayGCThing(thing) && !tracer->cb.WantAllTraces())
     808         1630616 :         return;
     809                 : 
     810                 :     /*
     811                 :      * This function needs to be careful to avoid stack overflow. Normally, when
     812                 :      * AddToCCKind is true, the recursion terminates immediately as we just add
     813                 :      * |thing| to the CC graph. So overflow is only possible when there are long
     814                 :      * chains of non-AddToCCKind GC things. Currently, this only can happen via
     815                 :      * shape parent pointers. The special JSTRACE_SHAPE case below handles
     816                 :      * parent pointers iteratively, rather than recursively, to avoid overflow.
     817                 :      */
     818         2028765 :     if (AddToCCKind(kind)) {
     819                 : #if defined(DEBUG)
     820         1345770 :         if (NS_UNLIKELY(tracer->cb.WantDebugInfo())) {
     821                 :             // based on DumpNotify in jsapi.c
     822               0 :             if (tracer->debugPrinter) {
     823                 :                 char buffer[200];
     824               0 :                 tracer->debugPrinter(trc, buffer, sizeof(buffer));
     825               0 :                 tracer->cb.NoteNextEdgeName(buffer);
     826               0 :             } else if (tracer->debugPrintIndex != (size_t)-1) {
     827                 :                 char buffer[200];
     828                 :                 JS_snprintf(buffer, sizeof(buffer), "%s[%lu]",
     829                 :                             static_cast<const char *>(tracer->debugPrintArg),
     830               0 :                             tracer->debugPrintIndex);
     831               0 :                 tracer->cb.NoteNextEdgeName(buffer);
     832                 :             } else {
     833               0 :                 tracer->cb.NoteNextEdgeName(static_cast<const char*>(tracer->debugPrintArg));
     834                 :             }
     835                 :         }
     836                 : #endif
     837         1345770 :         tracer->cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, thing);
     838          682995 :     } else if (kind == JSTRACE_SHAPE) {
     839          375083 :         JS_TraceShapeCycleCollectorChildren(trc, thing);
     840          307912 :     } else if (kind != JSTRACE_STRING) {
     841          307912 :         JS_TraceChildren(trc, thing, kind);
     842                 :     }
     843                 : }
     844                 : 
     845                 : void
     846               0 : xpc_MarkInCCGeneration(nsISupports* aVariant, PRUint32 aGeneration)
     847                 : {
     848               0 :     nsCOMPtr<XPCVariant> variant = do_QueryInterface(aVariant);
     849               0 :     if (variant) {
     850               0 :         variant->SetCCGeneration(aGeneration);
     851               0 :         variant->GetJSVal(); // Unmarks gray JSObject.
     852               0 :         XPCVariant* weak = variant.get();
     853               0 :         variant = nsnull;
     854               0 :         if (weak->IsPurple()) {
     855               0 :           weak->RemovePurple();
     856                 :         }
     857                 :     }
     858               0 : }
     859                 : 
     860                 : void
     861             374 : xpc_UnmarkGrayObject(nsIXPConnectWrappedJS* aWrappedJS)
     862                 : {
     863             374 :     if (aWrappedJS) {
     864                 :         // Unmarks gray JSObject.
     865             374 :         static_cast<nsXPCWrappedJS*>(aWrappedJS)->GetJSObject();
     866                 :     }
     867             374 : }
     868                 : 
     869                 : static JSBool
     870           46164 : WrapperIsNotMainThreadOnly(XPCWrappedNative *wrapper)
     871                 : {
     872           46164 :     XPCWrappedNativeProto *proto = wrapper->GetProto();
     873           46164 :     if (proto && proto->ClassIsMainThreadOnly())
     874             259 :         return false;
     875                 : 
     876                 :     // If the native participates in cycle collection then we know it can only
     877                 :     // be used on the main thread, in that case we assume the wrapped native
     878                 :     // can only be used on the main thread too.
     879                 :     nsXPCOMCycleCollectionParticipant* participant;
     880           45905 :     return NS_FAILED(CallQueryInterface(wrapper->Native(), &participant));
     881                 : }
     882                 : 
     883                 : NS_IMETHODIMP
     884          452374 : nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
     885                 : {
     886          452374 :     JSGCTraceKind traceKind = js_GetGCThingTraceKind(p);
     887          452374 :     JSObject *obj = nsnull;
     888          452374 :     js::Class *clazz = nsnull;
     889                 : 
     890                 :     // We do not want to add wrappers to the cycle collector if they're not
     891                 :     // explicitly marked as main thread only, because the cycle collector isn't
     892                 :     // able to deal with objects that might be used off of the main thread. We
     893                 :     // do want to explicitly mark them for cycle collection if the wrapper has
     894                 :     // an external reference, because the wrapper would mark the JS object if
     895                 :     // we did add the wrapper to the cycle collector.
     896          452374 :     JSBool dontTraverse = false;
     897          452374 :     JSBool markJSObject = false;
     898          452374 :     if (traceKind == JSTRACE_OBJECT) {
     899          404343 :         obj = static_cast<JSObject*>(p);
     900          404343 :         clazz = js::GetObjectClass(obj);
     901                 : 
     902          404343 :         if (clazz == &XPC_WN_Tearoff_JSClass) {
     903                 :             XPCWrappedNative *wrapper =
     904               0 :                 (XPCWrappedNative*)xpc_GetJSPrivate(js::GetObjectParent(obj));
     905               0 :             dontTraverse = WrapperIsNotMainThreadOnly(wrapper);
     906          404343 :         } else if (IS_WRAPPER_CLASS(clazz) && IS_WN_WRAPPER_OBJECT(obj)) {
     907           46164 :             XPCWrappedNative *wrapper = (XPCWrappedNative*)xpc_GetJSPrivate(obj);
     908           46164 :             dontTraverse = WrapperIsNotMainThreadOnly(wrapper);
     909           46164 :             markJSObject = dontTraverse && wrapper->HasExternalReference();
     910                 :         }
     911                 :     }
     912                 : 
     913                 :     bool isMarked;
     914                 : 
     915                 : #ifdef DEBUG_CC
     916                 :     // Note that the conditions under which we specify GCMarked vs.
     917                 :     // GCUnmarked are different between ExplainLiveExpectedGarbage and
     918                 :     // the normal case.  In the normal case, we're saying that anything
     919                 :     // reachable from a JS runtime root is itself such a root.  This
     920                 :     // doesn't actually break anything; it really just does some of the
     921                 :     // cycle collector's work for it.  However, when debugging, we
     922                 :     // (1) actually need to know what the root is and (2) don't want to
     923                 :     // do an extra GC, so we use mJSRoots, built from JS_TraceRuntime,
     924                 :     // which produces a different result because we didn't call
     925                 :     // JS_TraceChildren to trace everything that was reachable.
     926                 :     if (mJSRoots.ops) {
     927                 :         // ExplainLiveExpectedGarbage codepath
     928                 :         PLDHashEntryHdr* entry =
     929                 :             PL_DHashTableOperate(&mJSRoots, p, PL_DHASH_LOOKUP);
     930                 :         isMarked = markJSObject || PL_DHASH_ENTRY_IS_BUSY(entry);
     931                 :     } else
     932                 : #endif
     933                 :     {
     934                 :         // Normal codepath (matches non-DEBUG_CC codepath).
     935          452374 :         isMarked = markJSObject || !xpc_IsGrayGCThing(p);
     936                 :     }
     937                 : 
     938          452374 :     if (cb.WantDebugInfo()) {
     939                 :         char name[72];
     940               0 :         if (traceKind == JSTRACE_OBJECT) {
     941               0 :             XPCNativeScriptableInfo* si = nsnull;
     942               0 :             if (IS_PROTO_CLASS(clazz)) {
     943                 :                 XPCWrappedNativeProto* p =
     944               0 :                     (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
     945               0 :                 si = p->GetScriptableInfo();
     946                 :             }
     947               0 :             if (si) {
     948                 :                 JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
     949               0 :                             clazz->name, si->GetJSClass()->name);
     950               0 :             } else if (clazz == &js::FunctionClass) {
     951               0 :                 JSFunction* fun = JS_GetObjectFunction(obj);
     952               0 :                 JSString* str = JS_GetFunctionId(fun);
     953               0 :                 if (str) {
     954               0 :                     NS_ConvertUTF16toUTF8 fname(JS_GetInternedStringChars(str));
     955                 :                     JS_snprintf(name, sizeof(name),
     956               0 :                                 "JS Object (Function - %s)", fname.get());
     957                 :                 } else {
     958               0 :                     JS_snprintf(name, sizeof(name), "JS Object (Function)");
     959                 :                 }
     960                 :             } else {
     961                 :                 JS_snprintf(name, sizeof(name), "JS Object (%s)",
     962               0 :                             clazz->name);
     963                 :             }
     964                 :         } else {
     965                 :             static const char trace_types[][11] = {
     966                 :                 "Object",
     967                 :                 "String",
     968                 :                 "Script",
     969                 :                 "Xml",
     970                 :                 "Shape",
     971                 :                 "BaseShape",
     972                 :                 "TypeObject",
     973                 :             };
     974                 :             JS_STATIC_ASSERT(NS_ARRAY_LENGTH(trace_types) == JSTRACE_LAST + 1);
     975               0 :             JS_snprintf(name, sizeof(name), "JS %s", trace_types[traceKind]);
     976                 :         }
     977                 : 
     978                 :         // Disable printing global for objects while we figure out ObjShrink fallout.
     979               0 :         cb.DescribeGCedNode(isMarked, sizeof(js::shadow::Object), name);
     980                 :     } else {
     981          452374 :         cb.DescribeGCedNode(isMarked, sizeof(js::shadow::Object), "JS Object");
     982                 :     }
     983                 : 
     984                 :     // There's no need to trace objects that have already been marked by the JS
     985                 :     // GC. Any JS objects hanging from them will already be marked. Only do this
     986                 :     // if DEBUG_CC is not defined, else we do want to know about all JS objects
     987                 :     // to get better graphs and explanations.
     988          452374 :     if (!cb.WantAllTraces() && isMarked)
     989              56 :         return NS_OK;
     990                 : 
     991          452318 :     TraversalTracer trc(cb);
     992                 : 
     993          452318 :     JS_TracerInit(&trc, GetRuntime()->GetJSRuntime(), NoteJSChild);
     994          452318 :     trc.eagerlyTraceWeakMaps = false;
     995          452318 :     JS_TraceChildren(&trc, p, traceKind);
     996                 : 
     997          452318 :     if (traceKind != JSTRACE_OBJECT || dontTraverse)
     998           93776 :         return NS_OK;
     999                 : 
    1000          358542 :     if (clazz == &XPC_WN_Tearoff_JSClass) {
    1001                 :         // A tearoff holds a strong reference to its native object
    1002                 :         // (see XPCWrappedNative::FlatJSObjectFinalized). Its XPCWrappedNative
    1003                 :         // will be held alive through the parent of the JSObject of the tearoff.
    1004                 :         XPCWrappedNativeTearOff *to =
    1005               0 :             (XPCWrappedNativeTearOff*) xpc_GetJSPrivate(obj);
    1006               0 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "xpc_GetJSPrivate(obj)->mNative");
    1007               0 :         cb.NoteXPCOMChild(to->GetNative());
    1008                 :     }
    1009                 :     // XXX This test does seem fragile, we should probably whitelist classes
    1010                 :     //     that do hold a strong reference, but that might not be possible.
    1011          358542 :     else if (clazz->flags & JSCLASS_HAS_PRIVATE &&
    1012                 :              clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
    1013            2285 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "xpc_GetJSPrivate(obj)");
    1014            2285 :         cb.NoteXPCOMChild(static_cast<nsISupports*>(xpc_GetJSPrivate(obj)));
    1015          356257 :     } else if (mozilla::dom::binding::instanceIsProxy(obj)) {
    1016               0 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "js::GetProxyPrivate(obj)");
    1017                 :         nsISupports *identity =
    1018               0 :             static_cast<nsISupports*>(js::GetProxyPrivate(obj).toPrivate());
    1019               0 :         cb.NoteXPCOMChild(identity);
    1020                 :     }
    1021                 : 
    1022          358542 :     return NS_OK;
    1023                 : }
    1024                 : 
    1025                 : unsigned
    1026            5298 : nsXPConnect::GetOutstandingRequests(JSContext* cx)
    1027                 : {
    1028            5298 :     unsigned n = js::GetContextOutstandingRequests(cx);
    1029            5298 :     XPCCallContext* context = mCycleCollectionContext;
    1030                 :     // Ignore the contribution from the XPCCallContext we created for cycle
    1031                 :     // collection.
    1032            5298 :     if (context && cx == context->GetJSContext()) {
    1033            1910 :         MOZ_ASSERT(n);
    1034            1910 :         --n;
    1035                 :     }
    1036            5298 :     return n;
    1037                 : }
    1038                 : 
    1039                 : class JSContextParticipant : public nsCycleCollectionParticipant
    1040            1464 : {
    1041                 : public:
    1042               0 :     NS_IMETHOD Root(void *n)
    1043                 :     {
    1044               0 :         return NS_OK;
    1045                 :     }
    1046               0 :     NS_IMETHOD Unlink(void *n)
    1047                 :     {
    1048               0 :         JSContext *cx = static_cast<JSContext*>(n);
    1049               0 :         JSAutoRequest ar(cx);
    1050               0 :         NS_ASSERTION(JS_GetGlobalObject(cx), "global object NULL before unlinking");
    1051               0 :         JS_SetGlobalObject(cx, NULL);
    1052               0 :         return NS_OK;
    1053                 :     }
    1054               0 :     NS_IMETHOD Unroot(void *n)
    1055                 :     {
    1056               0 :         return NS_OK;
    1057                 :     }
    1058            5298 :     NS_IMETHODIMP Traverse(void *n, nsCycleCollectionTraversalCallback &cb)
    1059                 :     {
    1060            5298 :         JSContext *cx = static_cast<JSContext*>(n);
    1061                 : 
    1062                 :         // Add outstandingRequests to the count, if there are outstanding
    1063                 :         // requests the context needs to be kept alive and adding unknown
    1064                 :         // edges will ensure that any cycles this context is in won't be
    1065                 :         // collected.
    1066            5298 :         unsigned refCount = nsXPConnect::GetXPConnect()->GetOutstandingRequests(cx) + 1;
    1067            5298 :         cb.DescribeRefCountedNode(refCount, js::SizeOfJSContext(), "JSContext");
    1068            5298 :         if (JSObject *global = JS_GetGlobalObject(cx)) {
    1069            3387 :             NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[global object]");
    1070            3387 :             cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, global);
    1071                 :         }
    1072                 : 
    1073            5298 :         return NS_OK;
    1074                 :     }
    1075                 : };
    1076                 : 
    1077            1464 : static JSContextParticipant JSContext_cycleCollectorGlobal;
    1078                 : 
    1079                 : // static
    1080                 : nsCycleCollectionParticipant*
    1081            5298 : nsXPConnect::JSContextParticipant()
    1082                 : {
    1083            5298 :     return &JSContext_cycleCollectorGlobal;
    1084                 : }
    1085                 : 
    1086                 : NS_IMETHODIMP_(void)
    1087               0 : nsXPConnect::NoteJSContext(JSContext *aJSContext,
    1088                 :                            nsCycleCollectionTraversalCallback &aCb)
    1089                 : {
    1090               0 :     aCb.NoteNativeChild(aJSContext, &JSContext_cycleCollectorGlobal);
    1091               0 : }
    1092                 : 
    1093                 : 
    1094                 : /***************************************************************************/
    1095                 : /***************************************************************************/
    1096                 : // nsIXPConnect interface methods...
    1097                 : 
    1098               0 : inline nsresult UnexpectedFailure(nsresult rv)
    1099                 : {
    1100               0 :     NS_ERROR("This is not supposed to fail!");
    1101               0 :     return rv;
    1102                 : }
    1103                 : 
    1104                 : /* void initClasses (in JSContextPtr aJSContext, in JSObjectPtr aGlobalJSObj); */
    1105                 : NS_IMETHODIMP
    1106            2258 : nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
    1107                 : {
    1108            2258 :     NS_ASSERTION(aJSContext, "bad param");
    1109            2258 :     NS_ASSERTION(aGlobalJSObj, "bad param");
    1110                 : 
    1111                 :     // Nest frame chain save/restore in request created by XPCCallContext.
    1112            4516 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1113            2258 :     if (!ccx.IsValid())
    1114               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1115                 : 
    1116            4516 :     JSAutoEnterCompartment ac;
    1117            2258 :     if (!ac.enter(ccx, aGlobalJSObj))
    1118               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1119                 : 
    1120                 :     XPCWrappedNativeScope* scope =
    1121            2258 :         XPCWrappedNativeScope::GetNewOrUsed(ccx, aGlobalJSObj);
    1122                 : 
    1123            2258 :     if (!scope)
    1124               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1125                 : 
    1126            2258 :     scope->RemoveWrappedNativeProtos();
    1127                 : 
    1128            2258 :     if (!nsXPCComponents::AttachNewComponentsObject(ccx, scope, aGlobalJSObj))
    1129               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1130                 : 
    1131            2258 :     if (XPCPerThreadData::IsMainThread(ccx)) {
    1132            2258 :         if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
    1133               0 :             return UnexpectedFailure(NS_ERROR_FAILURE);
    1134                 :     }
    1135                 : 
    1136            2258 :     return NS_OK;
    1137                 : }
    1138                 : 
    1139                 : static bool
    1140            3369 : CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
    1141                 :                      xpc::CompartmentPrivate *priv, JSObject **global,
    1142                 :                      JSCompartment **compartment)
    1143                 : {
    1144                 :     // We take ownership of |priv|. Ensure that either we free it in the case
    1145                 :     // of failure or give ownership to the compartment in case of success (in
    1146                 :     // that case it will be free'd in CompartmentCallback during GC).
    1147            6738 :     nsAutoPtr<xpc::CompartmentPrivate> priv_holder(priv);
    1148                 :     JSObject *tempGlobal =
    1149            3369 :         JS_NewCompartmentAndGlobalObject(cx, clasp, nsJSPrincipals::get(principal));
    1150                 : 
    1151            3369 :     if (!tempGlobal)
    1152               0 :         return false;
    1153                 : 
    1154            3369 :     *global = tempGlobal;
    1155            3369 :     *compartment = js::GetObjectCompartment(tempGlobal);
    1156                 : 
    1157            3369 :     JS_SetCompartmentPrivate(*compartment, priv_holder.forget());
    1158            3369 :     return true;
    1159                 : }
    1160                 : 
    1161                 : #ifdef DEBUG
    1162                 : struct VerifyTraceXPCGlobalCalledTracer
    1163                 : {
    1164                 :     JSTracer base;
    1165                 :     bool ok;
    1166                 : };
    1167                 : 
    1168                 : static void
    1169            5934 : VerifyTraceXPCGlobalCalled(JSTracer *trc, void **thingp, JSGCTraceKind kind)
    1170                 : {
    1171                 :     // We don't do anything here, we only want to verify that TraceXPCGlobal
    1172                 :     // was called.
    1173            5934 : }
    1174                 : #endif
    1175                 : 
    1176                 : void
    1177          149042 : TraceXPCGlobal(JSTracer *trc, JSObject *obj)
    1178                 : {
    1179                 : #ifdef DEBUG
    1180          149042 :     if (trc->callback == VerifyTraceXPCGlobalCalled) {
    1181                 :         // We don't do anything here, we only want to verify that TraceXPCGlobal
    1182                 :         // was called.
    1183            1978 :         reinterpret_cast<VerifyTraceXPCGlobalCalledTracer*>(trc)->ok = true;
    1184            1978 :         return;
    1185                 :     }
    1186                 : #endif
    1187                 : 
    1188          147064 :     if (XPCWrappedNativeScope *scope = XPCWrappedNativeScope::GetNativeScope(obj))
    1189          147064 :         scope->TraceDOMPrototypes(trc);
    1190                 : }
    1191                 : 
    1192                 : nsresult
    1193           15195 : xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
    1194                 :                        nsIPrincipal *principal, nsISupports *ptr,
    1195                 :                        bool wantXrays, JSObject **global,
    1196                 :                        JSCompartment **compartment)
    1197                 : {
    1198           15195 :     NS_ABORT_IF_FALSE(NS_IsMainThread(), "using a principal off the main thread?");
    1199           15195 :     NS_ABORT_IF_FALSE(principal, "bad key");
    1200                 : 
    1201           15195 :     XPCCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetCompartmentMap();
    1202           30390 :     xpc::PtrAndPrincipalHashKey key(ptr, principal);
    1203           15195 :     if (!map.Get(&key, compartment)) {
    1204                 :         xpc::PtrAndPrincipalHashKey *priv_key =
    1205            3369 :             new xpc::PtrAndPrincipalHashKey(ptr, principal);
    1206            3369 :         xpc::CompartmentPrivate *priv = new xpc::CompartmentPrivate(priv_key, wantXrays);
    1207            3369 :         if (!CreateNewCompartment(cx, clasp, principal, priv,
    1208            3369 :                                   global, compartment)) {
    1209               0 :             return UnexpectedFailure(NS_ERROR_FAILURE);
    1210                 :         }
    1211                 : 
    1212            3369 :         map.Put(&key, *compartment);
    1213                 :     } else {
    1214           23652 :         js::AutoSwitchCompartment sc(cx, *compartment);
    1215                 : 
    1216           11826 :         JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp);
    1217           11826 :         if (!tempGlobal)
    1218               0 :             return UnexpectedFailure(NS_ERROR_FAILURE);
    1219           23652 :         *global = tempGlobal;
    1220                 :     }
    1221                 : 
    1222                 : #ifdef DEBUG
    1223                 :     // Verify that the right trace hook is called. Note that this doesn't
    1224                 :     // work right for wrapped globals, since the tracing situation there is
    1225                 :     // more complicated. Manual inspection shows that they do the right thing.
    1226           30390 :     if (clasp->flags & JSCLASS_XPCONNECT_GLOBAL &&
    1227           15195 :         !((js::Class*)clasp)->ext.isWrappedNative)
    1228                 :     {
    1229                 :         VerifyTraceXPCGlobalCalledTracer trc;
    1230            1978 :         JS_TracerInit(&trc.base, JS_GetRuntime(cx), VerifyTraceXPCGlobalCalled);
    1231            1978 :         trc.ok = false;
    1232            1978 :         JS_TraceChildren(&trc.base, *global, JSTRACE_OBJECT);
    1233            1978 :         NS_ABORT_IF_FALSE(trc.ok, "Trace hook needs to call TraceXPCGlobal if JSCLASS_XPCONNECT_GLOBAL is set.");
    1234                 :     }
    1235                 : #endif
    1236                 : 
    1237           15195 :     return NS_OK;
    1238                 : }
    1239                 : 
    1240                 : NS_IMETHODIMP
    1241           13217 : nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
    1242                 :                                              nsISupports *aCOMObj,
    1243                 :                                              nsIPrincipal * aPrincipal,
    1244                 :                                              PRUint32 aFlags,
    1245                 :                                              nsIXPConnectJSObjectHolder **_retval)
    1246                 : {
    1247           13217 :     NS_ASSERTION(aJSContext, "bad param");
    1248           13217 :     NS_ASSERTION(aCOMObj, "bad param");
    1249           13217 :     NS_ASSERTION(_retval, "bad param");
    1250                 : 
    1251                 :     // We pass null for the 'extra' pointer during global object creation, so
    1252                 :     // we need to have a principal.
    1253           13217 :     MOZ_ASSERT(aPrincipal);
    1254                 : 
    1255           26434 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1256                 : 
    1257                 :     // Call into XPCWrappedNative to make a new global object, scope, and global
    1258                 :     // prototype.
    1259           26434 :     xpcObjectHelper helper(aCOMObj);
    1260           13217 :     MOZ_ASSERT(helper.GetScriptableFlags() & nsIXPCScriptable::IS_GLOBAL_OBJECT);
    1261           26434 :     nsRefPtr<XPCWrappedNative> wrappedGlobal;
    1262                 :     nsresult rv =
    1263                 :         XPCWrappedNative::WrapNewGlobal(ccx, helper, aPrincipal,
    1264                 :                                         aFlags & nsIXPConnect::INIT_JS_STANDARD_CLASSES,
    1265           13217 :                                         getter_AddRefs(wrappedGlobal));
    1266           13217 :     NS_ENSURE_SUCCESS(rv, rv);
    1267                 : 
    1268                 :     // Grab a copy of the global and enter its compartment.
    1269           13217 :     JSObject *global = wrappedGlobal->GetFlatJSObject();
    1270           13217 :     MOZ_ASSERT(!js::GetObjectParent(global));
    1271           26434 :     JSAutoEnterCompartment ac;
    1272           13217 :     if (!ac.enter(ccx, global))
    1273               0 :         return NS_ERROR_UNEXPECTED;
    1274                 : 
    1275                 :     // Apply the system flag, if requested.
    1276           13217 :     bool system = (aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT) != 0;
    1277           13217 :     if (system && !JS_MakeSystemObject(aJSContext, global))
    1278               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1279                 : 
    1280           13217 :     if (!(aFlags & nsIXPConnect::OMIT_COMPONENTS_OBJECT)) {
    1281                 :         // XPCCallContext gives us an active request needed to save/restore.
    1282           13217 :         if (!nsXPCComponents::AttachNewComponentsObject(ccx, wrappedGlobal->GetScope(), global))
    1283               0 :             return UnexpectedFailure(NS_ERROR_FAILURE);
    1284                 : 
    1285           13217 :         if (XPCPerThreadData::IsMainThread(ccx)) {
    1286           13217 :             if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, global))
    1287               0 :                 return UnexpectedFailure(NS_ERROR_FAILURE);
    1288                 :         }
    1289                 :     }
    1290                 : 
    1291           13217 :     *_retval = wrappedGlobal.forget().get();
    1292           13217 :     return NS_OK;
    1293                 : }
    1294                 : 
    1295                 : nsresult
    1296               0 : xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph)
    1297                 : {
    1298                 :     nsWrapperCache *cache;
    1299               0 :     CallQueryInterface(tomorph, &cache);
    1300               0 :     if (!cache)
    1301               0 :         return NS_OK;
    1302                 : 
    1303               0 :     JSObject *obj = cache->GetWrapper();
    1304               0 :     if (!obj || !IS_SLIM_WRAPPER(obj))
    1305               0 :         return NS_OK;
    1306               0 :     return MorphSlimWrapper(cx, obj);
    1307                 : }
    1308                 : 
    1309                 : static nsresult
    1310          648602 : NativeInterface2JSObject(XPCLazyCallContext & lccx,
    1311                 :                          JSObject * aScope,
    1312                 :                          nsISupports *aCOMObj,
    1313                 :                          nsWrapperCache *aCache,
    1314                 :                          const nsIID * aIID,
    1315                 :                          bool aAllowWrapping,
    1316                 :                          jsval *aVal,
    1317                 :                          nsIXPConnectJSObjectHolder **aHolder)
    1318                 : {
    1319         1297204 :     JSAutoEnterCompartment ac;
    1320          648602 :     if (!ac.enter(lccx.GetJSContext(), aScope))
    1321               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1322                 : 
    1323          648602 :     lccx.SetScopeForNewJSObjects(aScope);
    1324                 : 
    1325                 :     nsresult rv;
    1326         1297204 :     xpcObjectHelper helper(aCOMObj, aCache);
    1327          648602 :     if (!XPCConvert::NativeInterface2JSObject(lccx, aVal, aHolder, helper, aIID,
    1328          648602 :                                               nsnull, aAllowWrapping, &rv))
    1329               0 :         return rv;
    1330                 : 
    1331                 : #ifdef DEBUG
    1332          648602 :     NS_ASSERTION(aAllowWrapping ||
    1333                 :                  !xpc::WrapperFactory::IsXrayWrapper(JSVAL_TO_OBJECT(*aVal)),
    1334                 :                  "Shouldn't be returning a xray wrapper here");
    1335                 : #endif
    1336                 : 
    1337          648602 :     return NS_OK;
    1338                 : }
    1339                 : 
    1340                 : /* nsIXPConnectJSObjectHolder wrapNative (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
    1341                 : NS_IMETHODIMP
    1342          545593 : nsXPConnect::WrapNative(JSContext * aJSContext,
    1343                 :                         JSObject * aScope,
    1344                 :                         nsISupports *aCOMObj,
    1345                 :                         const nsIID & aIID,
    1346                 :                         nsIXPConnectJSObjectHolder **aHolder)
    1347                 : {
    1348          545593 :     NS_ASSERTION(aHolder, "bad param");
    1349          545593 :     NS_ASSERTION(aJSContext, "bad param");
    1350          545593 :     NS_ASSERTION(aScope, "bad param");
    1351          545593 :     NS_ASSERTION(aCOMObj, "bad param");
    1352                 : 
    1353         1091186 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1354          545593 :     if (!ccx.IsValid())
    1355               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1356         1091186 :     XPCLazyCallContext lccx(ccx);
    1357                 : 
    1358                 :     jsval v;
    1359                 :     return NativeInterface2JSObject(lccx, aScope, aCOMObj, nsnull, &aIID,
    1360          545593 :                                     false, &v, aHolder);
    1361                 : }
    1362                 : 
    1363                 : /* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out jsval aVal, out nsIXPConnectJSObjectHolder aHolder); */
    1364                 : NS_IMETHODIMP
    1365          103009 : nsXPConnect::WrapNativeToJSVal(JSContext * aJSContext,
    1366                 :                                JSObject * aScope,
    1367                 :                                nsISupports *aCOMObj,
    1368                 :                                nsWrapperCache *aCache,
    1369                 :                                const nsIID * aIID,
    1370                 :                                bool aAllowWrapping,
    1371                 :                                jsval *aVal,
    1372                 :                                nsIXPConnectJSObjectHolder **aHolder)
    1373                 : {
    1374          103009 :     NS_ASSERTION(aJSContext, "bad param");
    1375          103009 :     NS_ASSERTION(aScope, "bad param");
    1376          103009 :     NS_ASSERTION(aCOMObj, "bad param");
    1377                 : 
    1378          103009 :     if (aHolder)
    1379             324 :         *aHolder = nsnull;
    1380                 : 
    1381          206018 :     XPCLazyCallContext lccx(NATIVE_CALLER, aJSContext);
    1382                 : 
    1383                 :     return NativeInterface2JSObject(lccx, aScope, aCOMObj, aCache, aIID,
    1384          103009 :                                     aAllowWrapping, aVal, aHolder);
    1385                 : }
    1386                 : 
    1387                 : /* void wrapJS (in JSContextPtr aJSContext, in JSObjectPtr aJSObj, in nsIIDRef aIID, [iid_is (aIID), retval] out nsQIResult result); */
    1388                 : NS_IMETHODIMP
    1389            2452 : nsXPConnect::WrapJS(JSContext * aJSContext,
    1390                 :                     JSObject * aJSObj,
    1391                 :                     const nsIID & aIID,
    1392                 :                     void * *result)
    1393                 : {
    1394            2452 :     NS_ASSERTION(aJSContext, "bad param");
    1395            2452 :     NS_ASSERTION(aJSObj, "bad param");
    1396            2452 :     NS_ASSERTION(result, "bad param");
    1397                 : 
    1398            2452 :     *result = nsnull;
    1399                 : 
    1400            4904 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1401            2452 :     if (!ccx.IsValid())
    1402               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1403                 : 
    1404            4904 :     JSAutoEnterCompartment aec;
    1405                 : 
    1406            2452 :     nsresult rv = NS_ERROR_UNEXPECTED;
    1407            4904 :     if (!aec.enter(ccx, aJSObj) ||
    1408                 :         !XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
    1409            2452 :                                               &aIID, nsnull, &rv))
    1410               0 :         return rv;
    1411            2452 :     return NS_OK;
    1412                 : }
    1413                 : 
    1414                 : NS_IMETHODIMP
    1415               0 : nsXPConnect::JSValToVariant(JSContext *cx,
    1416                 :                             jsval *aJSVal,
    1417                 :                             nsIVariant ** aResult)
    1418                 : {
    1419               0 :     NS_PRECONDITION(aJSVal, "bad param");
    1420               0 :     NS_PRECONDITION(aResult, "bad param");
    1421               0 :     *aResult = nsnull;
    1422                 : 
    1423               0 :     XPCCallContext ccx(NATIVE_CALLER, cx);
    1424               0 :     if (!ccx.IsValid())
    1425               0 :       return NS_ERROR_FAILURE;
    1426                 : 
    1427               0 :     *aResult = XPCVariant::newVariant(ccx, *aJSVal);
    1428               0 :     NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
    1429                 : 
    1430               0 :     return NS_OK;
    1431                 : }
    1432                 : 
    1433                 : /* void wrapJSAggregatedToNative (in nsISupports aOuter, in JSContextPtr aJSContext, in JSObjectPtr aJSObj, in nsIIDRef aIID, [iid_is (aIID), retval] out nsQIResult result); */
    1434                 : NS_IMETHODIMP
    1435               0 : nsXPConnect::WrapJSAggregatedToNative(nsISupports *aOuter,
    1436                 :                                       JSContext * aJSContext,
    1437                 :                                       JSObject * aJSObj,
    1438                 :                                       const nsIID & aIID,
    1439                 :                                       void * *result)
    1440                 : {
    1441               0 :     NS_ASSERTION(aOuter, "bad param");
    1442               0 :     NS_ASSERTION(aJSContext, "bad param");
    1443               0 :     NS_ASSERTION(aJSObj, "bad param");
    1444               0 :     NS_ASSERTION(result, "bad param");
    1445                 : 
    1446               0 :     *result = nsnull;
    1447                 : 
    1448               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1449               0 :     if (!ccx.IsValid())
    1450               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1451                 : 
    1452                 :     nsresult rv;
    1453               0 :     if (!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
    1454               0 :                                               &aIID, aOuter, &rv))
    1455               0 :         return rv;
    1456               0 :     return NS_OK;
    1457                 : }
    1458                 : 
    1459                 : /* nsIXPConnectWrappedNative getWrappedNativeOfJSObject (in JSContextPtr aJSContext, in JSObjectPtr aJSObj); */
    1460                 : NS_IMETHODIMP
    1461           13405 : nsXPConnect::GetWrappedNativeOfJSObject(JSContext * aJSContext,
    1462                 :                                         JSObject * aJSObj,
    1463                 :                                         nsIXPConnectWrappedNative **_retval)
    1464                 : {
    1465           13405 :     NS_ASSERTION(aJSContext, "bad param");
    1466           13405 :     NS_ASSERTION(aJSObj, "bad param");
    1467           13405 :     NS_ASSERTION(_retval, "bad param");
    1468                 : 
    1469           26810 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1470           13405 :     if (!ccx.IsValid())
    1471               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1472                 : 
    1473                 :     SLIM_LOG_WILL_MORPH(aJSContext, aJSObj);
    1474                 :     nsIXPConnectWrappedNative* wrapper =
    1475           13405 :         XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(aJSContext, aJSObj);
    1476           13405 :     if (wrapper) {
    1477           13037 :         NS_ADDREF(wrapper);
    1478           13037 :         *_retval = wrapper;
    1479           13037 :         return NS_OK;
    1480                 :     }
    1481                 : 
    1482                 :     // else...
    1483             368 :     *_retval = nsnull;
    1484             368 :     return NS_ERROR_FAILURE;
    1485                 : }
    1486                 : 
    1487                 : /* nsISupports getNativeOfWrapper(in JSContextPtr aJSContext, in JSObjectPtr  aJSObj); */
    1488                 : NS_IMETHODIMP_(nsISupports*)
    1489            9864 : nsXPConnect::GetNativeOfWrapper(JSContext * aJSContext,
    1490                 :                                 JSObject * aJSObj)
    1491                 : {
    1492            9864 :     NS_ASSERTION(aJSContext, "bad param");
    1493            9864 :     NS_ASSERTION(aJSObj, "bad param");
    1494                 : 
    1495           19728 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1496            9864 :     if (!ccx.IsValid()) {
    1497               0 :         UnexpectedFailure(NS_ERROR_FAILURE);
    1498               0 :         return nsnull;
    1499                 :     }
    1500                 : 
    1501            9864 :     JSObject* obj2 = nsnull;
    1502                 :     nsIXPConnectWrappedNative* wrapper =
    1503                 :         XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj, nsnull,
    1504            9864 :                                                      &obj2);
    1505            9864 :     if (wrapper)
    1506            9848 :         return wrapper->Native();
    1507                 : 
    1508              16 :     if (obj2)
    1509               0 :         return (nsISupports*)xpc_GetJSPrivate(obj2);
    1510                 : 
    1511              16 :     if (mozilla::dom::binding::instanceIsProxy(aJSObj)) {
    1512                 :         // FIXME: Provide a fast non-refcounting way to get the canonical
    1513                 :         //        nsISupports from the proxy.
    1514                 :         nsISupports *supports =
    1515               0 :             static_cast<nsISupports*>(js::GetProxyPrivate(aJSObj).toPrivate());
    1516               0 :         nsCOMPtr<nsISupports> canonical = do_QueryInterface(supports);
    1517               0 :         return canonical.get();
    1518                 :     }
    1519                 : 
    1520              16 :     return nsnull;
    1521                 : }
    1522                 : 
    1523                 : /* JSObjectPtr getJSObjectOfWrapper (in JSContextPtr aJSContext, in JSObjectPtr aJSObj); */
    1524                 : NS_IMETHODIMP
    1525               0 : nsXPConnect::GetJSObjectOfWrapper(JSContext * aJSContext,
    1526                 :                                   JSObject * aJSObj,
    1527                 :                                   JSObject **_retval)
    1528                 : {
    1529               0 :     NS_ASSERTION(aJSContext, "bad param");
    1530               0 :     NS_ASSERTION(aJSObj, "bad param");
    1531               0 :     NS_ASSERTION(_retval, "bad param");
    1532                 : 
    1533               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1534               0 :     if (!ccx.IsValid())
    1535               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1536                 : 
    1537               0 :     JSObject* obj2 = nsnull;
    1538                 :     nsIXPConnectWrappedNative* wrapper =
    1539                 :         XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj, nsnull,
    1540               0 :                                                      &obj2);
    1541               0 :     if (wrapper) {
    1542               0 :         wrapper->GetJSObject(_retval);
    1543               0 :         return NS_OK;
    1544                 :     }
    1545               0 :     if (obj2) {
    1546               0 :         *_retval = obj2;
    1547               0 :         return NS_OK;
    1548                 :     }
    1549               0 :     if (mozilla::dom::binding::instanceIsProxy(aJSObj)) {
    1550               0 :         *_retval = aJSObj;
    1551               0 :         return NS_OK;
    1552                 :     }
    1553                 :     // else...
    1554               0 :     *_retval = nsnull;
    1555               0 :     return NS_ERROR_FAILURE;
    1556                 : }
    1557                 : 
    1558                 : /* nsIXPConnectWrappedNative getWrappedNativeOfNativeObject (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
    1559                 : NS_IMETHODIMP
    1560               0 : nsXPConnect::GetWrappedNativeOfNativeObject(JSContext * aJSContext,
    1561                 :                                             JSObject * aScope,
    1562                 :                                             nsISupports *aCOMObj,
    1563                 :                                             const nsIID & aIID,
    1564                 :                                             nsIXPConnectWrappedNative **_retval)
    1565                 : {
    1566               0 :     NS_ASSERTION(aJSContext, "bad param");
    1567               0 :     NS_ASSERTION(aScope, "bad param");
    1568               0 :     NS_ASSERTION(aCOMObj, "bad param");
    1569               0 :     NS_ASSERTION(_retval, "bad param");
    1570                 : 
    1571               0 :     *_retval = nsnull;
    1572                 : 
    1573               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1574               0 :     if (!ccx.IsValid())
    1575               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1576                 : 
    1577                 :     XPCWrappedNativeScope* scope =
    1578               0 :         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
    1579               0 :     if (!scope)
    1580               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1581                 : 
    1582               0 :     AutoMarkingNativeInterfacePtr iface(ccx);
    1583               0 :     iface = XPCNativeInterface::GetNewOrUsed(ccx, &aIID);
    1584               0 :     if (!iface)
    1585               0 :         return NS_ERROR_FAILURE;
    1586                 : 
    1587                 :     XPCWrappedNative* wrapper;
    1588                 : 
    1589                 :     nsresult rv = XPCWrappedNative::GetUsedOnly(ccx, aCOMObj, scope, iface,
    1590               0 :                                                 &wrapper);
    1591               0 :     if (NS_FAILED(rv))
    1592               0 :         return NS_ERROR_FAILURE;
    1593               0 :     *_retval = static_cast<nsIXPConnectWrappedNative*>(wrapper);
    1594               0 :     return NS_OK;
    1595                 : }
    1596                 : 
    1597                 : /* nsIXPConnectJSObjectHolder reparentWrappedNativeIfFound (in JSContextPtr aJSContext, in JSObjectPtr aScope, in JSObjectPtr aNewParent, in nsISupports aCOMObj); */
    1598                 : NS_IMETHODIMP
    1599               0 : nsXPConnect::ReparentWrappedNativeIfFound(JSContext * aJSContext,
    1600                 :                                           JSObject * aScope,
    1601                 :                                           JSObject * aNewParent,
    1602                 :                                           nsISupports *aCOMObj,
    1603                 :                                           nsIXPConnectJSObjectHolder **_retval)
    1604                 : {
    1605               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1606               0 :     if (!ccx.IsValid())
    1607               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1608                 : 
    1609                 :     XPCWrappedNativeScope* scope =
    1610               0 :         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
    1611               0 :     if (!scope)
    1612               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1613                 : 
    1614                 :     XPCWrappedNativeScope* scope2 =
    1615               0 :         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aNewParent);
    1616               0 :     if (!scope2)
    1617               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1618                 : 
    1619                 :     return XPCWrappedNative::
    1620                 :         ReparentWrapperIfFound(ccx, scope, scope2, aNewParent, aCOMObj,
    1621               0 :                                (XPCWrappedNative**) _retval);
    1622                 : }
    1623                 : 
    1624                 : static JSDHashOperator
    1625               0 : MoveableWrapperFinder(JSDHashTable *table, JSDHashEntryHdr *hdr,
    1626                 :                       uint32_t number, void *arg)
    1627                 : {
    1628                 :     nsTArray<nsRefPtr<XPCWrappedNative> > *array =
    1629               0 :         static_cast<nsTArray<nsRefPtr<XPCWrappedNative> > *>(arg);
    1630               0 :     XPCWrappedNative *wn = ((Native2WrappedNativeMap::Entry*)hdr)->value;
    1631                 : 
    1632                 :     // If a wrapper is expired, then there are no references to it from JS, so
    1633                 :     // we don't have to move it.
    1634               0 :     if (!wn->IsWrapperExpired())
    1635               0 :         array->AppendElement(wn);
    1636               0 :     return JS_DHASH_NEXT;
    1637                 : }
    1638                 : 
    1639                 : static nsresult
    1640               0 : MoveWrapper(XPCCallContext& ccx, XPCWrappedNative *wrapper,
    1641                 :             XPCWrappedNativeScope *newScope, XPCWrappedNativeScope *oldScope)
    1642                 : {
    1643                 :     // First, check to see if this wrapper really needs to be
    1644                 :     // reparented.
    1645                 : 
    1646               0 :     if (wrapper->GetScope() == newScope) {
    1647                 :         // The wrapper already got moved, nothing to do here.
    1648               0 :         return NS_OK;
    1649                 :     }
    1650                 : 
    1651               0 :     nsISupports *identity = wrapper->GetIdentityObject();
    1652               0 :     nsCOMPtr<nsIClassInfo> info(do_QueryInterface(identity));
    1653                 : 
    1654                 :     // ClassInfo is implemented as singleton objects. If the identity
    1655                 :     // object here is the same object as returned by the QI, then it
    1656                 :     // is the singleton classinfo, so we don't need to reparent it.
    1657               0 :     if (SameCOMIdentity(identity, info))
    1658               0 :         info = nsnull;
    1659                 : 
    1660               0 :     if (!info)
    1661               0 :         return NS_OK;
    1662                 : 
    1663               0 :     XPCNativeScriptableCreateInfo sciProto;
    1664               0 :     XPCNativeScriptableCreateInfo sci;
    1665                 :     const XPCNativeScriptableCreateInfo& sciWrapper =
    1666                 :         XPCWrappedNative::GatherScriptableCreateInfo(identity, info,
    1667               0 :                                                      sciProto, sci);
    1668                 : 
    1669                 :     // If the wrapper doesn't want precreate, then we don't need to
    1670                 :     // worry about reparenting it.
    1671               0 :     if (!sciWrapper.GetFlags().WantPreCreate())
    1672               0 :         return NS_OK;
    1673                 : 
    1674               0 :     JSObject *newParent = oldScope->GetGlobalJSObject();
    1675               0 :     nsresult rv = sciWrapper.GetCallback()->PreCreate(identity, ccx,
    1676                 :                                                       newParent,
    1677               0 :                                                       &newParent);
    1678               0 :     if (NS_FAILED(rv))
    1679               0 :         return rv;
    1680                 : 
    1681               0 :     if (newParent == oldScope->GetGlobalJSObject()) {
    1682                 :         // The old scope still works for this wrapper. We have to
    1683                 :         // assume that the wrapper will continue to return the old
    1684                 :         // scope from PreCreate, so don't move it.
    1685               0 :         return NS_OK;
    1686                 :     }
    1687                 : 
    1688                 :     // The wrapper returned a new parent. If the new parent is in a
    1689                 :     // different scope, then we need to reparent it, otherwise, the
    1690                 :     // old scope is fine.
    1691                 : 
    1692                 :     XPCWrappedNativeScope *betterScope =
    1693               0 :         XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent);
    1694               0 :     if (betterScope == oldScope) {
    1695                 :         // The wrapper asked for a different object, but that object
    1696                 :         // was in the same scope. This means that the new parent
    1697                 :         // simply hasn't been reparented yet, so reparent it first,
    1698                 :         // and then continue reparenting the wrapper itself.
    1699                 : 
    1700               0 :         if (!IS_WN_WRAPPER_OBJECT(newParent)) {
    1701                 :             // The parent of wrapper is a slim wrapper, in this case
    1702                 :             // we need to morph the parent so that we can reparent it.
    1703                 : 
    1704               0 :             rv = MorphSlimWrapper(ccx, newParent);
    1705               0 :             NS_ENSURE_SUCCESS(rv, rv);
    1706                 :         }
    1707                 : 
    1708                 :         XPCWrappedNative *parentWrapper =
    1709               0 :             XPCWrappedNative::GetWrappedNativeOfJSObject(ccx, newParent);
    1710                 : 
    1711               0 :         rv = MoveWrapper(ccx, parentWrapper, newScope, oldScope);
    1712               0 :         NS_ENSURE_SUCCESS(rv, rv);
    1713                 : 
    1714                 :         // If the parent wanted to stay in the old scope, we have to stay with
    1715                 :         // it. This can happen when doing document.write when the old detached
    1716                 :         // about:blank document is still floating around in the scope. Leave it
    1717                 :         // behind to die.
    1718               0 :         if (parentWrapper->GetScope() == oldScope)
    1719               0 :             return NS_OK;
    1720               0 :         NS_ASSERTION(parentWrapper->GetScope() == newScope,
    1721                 :                      "A _third_ scope? Oh dear...");
    1722                 : 
    1723               0 :         newParent = parentWrapper->GetFlatJSObject();
    1724                 :     } else
    1725               0 :         NS_ASSERTION(betterScope == newScope, "Weird scope returned");
    1726                 : 
    1727                 :     // Now, reparent the wrapper, since we know that it wants to be
    1728                 :     // reparented.
    1729                 : 
    1730               0 :     nsRefPtr<XPCWrappedNative> junk;
    1731                 :     rv = XPCWrappedNative::ReparentWrapperIfFound(ccx, oldScope,
    1732                 :                                                   newScope, newParent,
    1733                 :                                                   wrapper->GetIdentityObject(),
    1734               0 :                                                   getter_AddRefs(junk));
    1735               0 :     return rv;
    1736                 : }
    1737                 : 
    1738                 : /* void moveWrappers(in JSContextPtr aJSContext, in JSObjectPtr  aOldScope, in JSObjectPtr  aNewScope); */
    1739                 : NS_IMETHODIMP
    1740               0 : nsXPConnect::MoveWrappers(JSContext *aJSContext,
    1741                 :                           JSObject *aOldScope,
    1742                 :                           JSObject *aNewScope)
    1743                 : {
    1744               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1745               0 :     if (!ccx.IsValid())
    1746               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1747                 : 
    1748                 :     XPCWrappedNativeScope *oldScope =
    1749               0 :         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aOldScope);
    1750               0 :     if (!oldScope)
    1751               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1752                 : 
    1753                 :     XPCWrappedNativeScope *newScope =
    1754               0 :         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aNewScope);
    1755               0 :     if (!newScope)
    1756               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1757                 : 
    1758                 :     // First, look through the old scope and find all of the wrappers that
    1759                 :     // we're going to move.
    1760               0 :     nsTArray<nsRefPtr<XPCWrappedNative> > wrappersToMove;
    1761                 : 
    1762                 :     {   // scoped lock
    1763               0 :         XPCAutoLock lock(GetRuntime()->GetMapLock());
    1764               0 :         Native2WrappedNativeMap *map = oldScope->GetWrappedNativeMap();
    1765               0 :         wrappersToMove.SetCapacity(map->Count());
    1766               0 :         map->Enumerate(MoveableWrapperFinder, &wrappersToMove);
    1767                 :     }
    1768                 : 
    1769                 :     // Now that we have the wrappers, reparent them to the new scope.
    1770               0 :     for (PRUint32 i = 0, stop = wrappersToMove.Length(); i < stop; ++i) {
    1771               0 :         nsresult rv = MoveWrapper(ccx, wrappersToMove[i], newScope, oldScope);
    1772               0 :         NS_ENSURE_SUCCESS(rv, rv);
    1773                 :     }
    1774                 : 
    1775               0 :     return NS_OK;
    1776                 : }
    1777                 : 
    1778                 : /* void setSecurityManagerForJSContext (in JSContextPtr aJSContext, in nsIXPCSecurityManager aManager, in PRUint16 flags); */
    1779                 : NS_IMETHODIMP
    1780            1387 : nsXPConnect::SetSecurityManagerForJSContext(JSContext * aJSContext,
    1781                 :                                             nsIXPCSecurityManager *aManager,
    1782                 :                                             PRUint16 flags)
    1783                 : {
    1784            1387 :     NS_ASSERTION(aJSContext, "bad param");
    1785                 : 
    1786            2774 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1787            1387 :     if (!ccx.IsValid())
    1788               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1789                 : 
    1790            1387 :     XPCContext* xpcc = ccx.GetXPCContext();
    1791                 : 
    1792            1387 :     NS_IF_ADDREF(aManager);
    1793            1387 :     nsIXPCSecurityManager* oldManager = xpcc->GetSecurityManager();
    1794            1387 :     NS_IF_RELEASE(oldManager);
    1795                 : 
    1796            1387 :     xpcc->SetSecurityManager(aManager);
    1797            1387 :     xpcc->SetSecurityManagerFlags(flags);
    1798            1387 :     return NS_OK;
    1799                 : }
    1800                 : 
    1801                 : /* void getSecurityManagerForJSContext (in JSContextPtr aJSContext, out nsIXPCSecurityManager aManager, out PRUint16 flags); */
    1802                 : NS_IMETHODIMP
    1803               0 : nsXPConnect::GetSecurityManagerForJSContext(JSContext * aJSContext,
    1804                 :                                             nsIXPCSecurityManager **aManager,
    1805                 :                                             PRUint16 *flags)
    1806                 : {
    1807               0 :     NS_ASSERTION(aJSContext, "bad param");
    1808               0 :     NS_ASSERTION(aManager, "bad param");
    1809               0 :     NS_ASSERTION(flags, "bad param");
    1810                 : 
    1811               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    1812               0 :     if (!ccx.IsValid())
    1813               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1814                 : 
    1815               0 :     XPCContext* xpcc = ccx.GetXPCContext();
    1816                 : 
    1817               0 :     nsIXPCSecurityManager* manager = xpcc->GetSecurityManager();
    1818               0 :     NS_IF_ADDREF(manager);
    1819               0 :     *aManager = manager;
    1820               0 :     *flags = xpcc->GetSecurityManagerFlags();
    1821               0 :     return NS_OK;
    1822                 : }
    1823                 : 
    1824                 : /* void setDefaultSecurityManager (in nsIXPCSecurityManager aManager, in PRUint16 flags); */
    1825                 : NS_IMETHODIMP
    1826            1404 : nsXPConnect::SetDefaultSecurityManager(nsIXPCSecurityManager *aManager,
    1827                 :                                        PRUint16 flags)
    1828                 : {
    1829            1404 :     NS_IF_ADDREF(aManager);
    1830            1404 :     NS_IF_RELEASE(mDefaultSecurityManager);
    1831            1404 :     mDefaultSecurityManager = aManager;
    1832            1404 :     mDefaultSecurityManagerFlags = flags;
    1833                 : 
    1834                 :     nsCOMPtr<nsIScriptSecurityManager> ssm =
    1835            2808 :         do_QueryInterface(mDefaultSecurityManager);
    1836                 : 
    1837                 :     // Remember the result of the above QI for fast access to the
    1838                 :     // script securityt manager.
    1839            1404 :     gScriptSecurityManager = ssm;
    1840                 : 
    1841            1404 :     return NS_OK;
    1842                 : }
    1843                 : 
    1844                 : /* void getDefaultSecurityManager (out nsIXPCSecurityManager aManager, out PRUint16 flags); */
    1845                 : NS_IMETHODIMP
    1846               0 : nsXPConnect::GetDefaultSecurityManager(nsIXPCSecurityManager **aManager,
    1847                 :                                        PRUint16 *flags)
    1848                 : {
    1849               0 :     NS_ASSERTION(aManager, "bad param");
    1850               0 :     NS_ASSERTION(flags, "bad param");
    1851                 : 
    1852               0 :     NS_IF_ADDREF(mDefaultSecurityManager);
    1853               0 :     *aManager = mDefaultSecurityManager;
    1854               0 :     *flags = mDefaultSecurityManagerFlags;
    1855               0 :     return NS_OK;
    1856                 : }
    1857                 : 
    1858                 : /* nsIStackFrame createStackFrameLocation (in PRUint32 aLanguage, in string aFilename, in string aFunctionName, in PRInt32 aLineNumber, in nsIStackFrame aCaller); */
    1859                 : NS_IMETHODIMP
    1860               0 : nsXPConnect::CreateStackFrameLocation(PRUint32 aLanguage,
    1861                 :                                       const char *aFilename,
    1862                 :                                       const char *aFunctionName,
    1863                 :                                       PRInt32 aLineNumber,
    1864                 :                                       nsIStackFrame *aCaller,
    1865                 :                                       nsIStackFrame **_retval)
    1866                 : {
    1867               0 :     NS_ASSERTION(_retval, "bad param");
    1868                 : 
    1869                 :     return XPCJSStack::CreateStackFrameLocation(aLanguage,
    1870                 :                                                 aFilename,
    1871                 :                                                 aFunctionName,
    1872                 :                                                 aLineNumber,
    1873                 :                                                 aCaller,
    1874               0 :                                                 _retval);
    1875                 : }
    1876                 : 
    1877                 : /* readonly attribute nsIStackFrame CurrentJSStack; */
    1878                 : NS_IMETHODIMP
    1879          206181 : nsXPConnect::GetCurrentJSStack(nsIStackFrame * *aCurrentJSStack)
    1880                 : {
    1881          206181 :     NS_ASSERTION(aCurrentJSStack, "bad param");
    1882          206181 :     *aCurrentJSStack = nsnull;
    1883                 : 
    1884                 :     JSContext* cx;
    1885                 :     // is there a current context available?
    1886          206181 :     if (NS_SUCCEEDED(Peek(&cx)) && cx) {
    1887          412362 :         nsCOMPtr<nsIStackFrame> stack;
    1888          206181 :         XPCJSStack::CreateStack(cx, getter_AddRefs(stack));
    1889          206181 :         if (stack) {
    1890                 :             // peel off native frames...
    1891                 :             PRUint32 language;
    1892          394430 :             nsCOMPtr<nsIStackFrame> caller;
    1893          986126 :             while (stack &&
    1894          394430 :                    NS_SUCCEEDED(stack->GetLanguage(&language)) &&
    1895                 :                    language != nsIProgrammingLanguage::JAVASCRIPT &&
    1896          197249 :                    NS_SUCCEEDED(stack->GetCaller(getter_AddRefs(caller))) &&
    1897              17 :                    caller) {
    1898               0 :                 stack = caller;
    1899                 :             }
    1900          197215 :             NS_IF_ADDREF(*aCurrentJSStack = stack);
    1901                 :         }
    1902                 :     }
    1903          206181 :     return NS_OK;
    1904                 : }
    1905                 : 
    1906                 : /* readonly attribute nsIXPCNativeCallContext CurrentNativeCallContext; */
    1907                 : NS_IMETHODIMP
    1908          211895 : nsXPConnect::GetCurrentNativeCallContext(nsAXPCNativeCallContext * *aCurrentNativeCallContext)
    1909                 : {
    1910          211895 :     NS_ASSERTION(aCurrentNativeCallContext, "bad param");
    1911                 : 
    1912          211895 :     XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    1913          211895 :     if (data) {
    1914          211895 :         *aCurrentNativeCallContext = data->GetCallContext();
    1915          211895 :         return NS_OK;
    1916                 :     }
    1917                 :     //else...
    1918               0 :     *aCurrentNativeCallContext = nsnull;
    1919               0 :     return UnexpectedFailure(NS_ERROR_FAILURE);
    1920                 : }
    1921                 : 
    1922                 : /* attribute nsIException PendingException; */
    1923                 : NS_IMETHODIMP
    1924           38278 : nsXPConnect::GetPendingException(nsIException * *aPendingException)
    1925                 : {
    1926           38278 :     NS_ASSERTION(aPendingException, "bad param");
    1927                 : 
    1928           38278 :     XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    1929           38278 :     if (!data) {
    1930               0 :         *aPendingException = nsnull;
    1931               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1932                 :     }
    1933                 : 
    1934           38278 :     return data->GetException(aPendingException);
    1935                 : }
    1936                 : 
    1937                 : NS_IMETHODIMP
    1938             261 : nsXPConnect::SetPendingException(nsIException * aPendingException)
    1939                 : {
    1940             261 :     XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    1941             261 :     if (!data)
    1942               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    1943                 : 
    1944             261 :     data->SetException(aPendingException);
    1945             261 :     return NS_OK;
    1946                 : }
    1947                 : 
    1948                 : NS_IMETHODIMP
    1949               0 : nsXPConnect::SyncJSContexts(void)
    1950                 : {
    1951                 :     // Do-nothing compatibility function
    1952               0 :     return NS_OK;
    1953                 : }
    1954                 : 
    1955                 : /* nsIXPCFunctionThisTranslator setFunctionThisTranslator (in nsIIDRef aIID, in nsIXPCFunctionThisTranslator aTranslator); */
    1956                 : NS_IMETHODIMP
    1957             306 : nsXPConnect::SetFunctionThisTranslator(const nsIID & aIID,
    1958                 :                                        nsIXPCFunctionThisTranslator *aTranslator,
    1959                 :                                        nsIXPCFunctionThisTranslator **_retval)
    1960                 : {
    1961             306 :     XPCJSRuntime* rt = GetRuntime();
    1962                 :     nsIXPCFunctionThisTranslator* old;
    1963             306 :     IID2ThisTranslatorMap* map = rt->GetThisTranslatorMap();
    1964                 : 
    1965                 :     {
    1966             612 :         XPCAutoLock lock(rt->GetMapLock()); // scoped lock
    1967             306 :         if (_retval) {
    1968             306 :             old = map->Find(aIID);
    1969             306 :             NS_IF_ADDREF(old);
    1970             306 :             *_retval = old;
    1971                 :         }
    1972             306 :         map->Add(aIID, aTranslator);
    1973                 :     }
    1974             306 :     return NS_OK;
    1975                 : }
    1976                 : 
    1977                 : /* nsIXPCFunctionThisTranslator getFunctionThisTranslator (in nsIIDRef aIID); */
    1978                 : NS_IMETHODIMP
    1979               0 : nsXPConnect::GetFunctionThisTranslator(const nsIID & aIID,
    1980                 :                                        nsIXPCFunctionThisTranslator **_retval)
    1981                 : {
    1982               0 :     XPCJSRuntime* rt = GetRuntime();
    1983                 :     nsIXPCFunctionThisTranslator* old;
    1984               0 :     IID2ThisTranslatorMap* map = rt->GetThisTranslatorMap();
    1985                 : 
    1986                 :     {
    1987               0 :         XPCAutoLock lock(rt->GetMapLock()); // scoped lock
    1988               0 :         old = map->Find(aIID);
    1989               0 :         NS_IF_ADDREF(old);
    1990               0 :         *_retval = old;
    1991                 :     }
    1992               0 :     return NS_OK;
    1993                 : }
    1994                 : 
    1995                 : /* void clearAllWrappedNativeSecurityPolicies (); */
    1996                 : NS_IMETHODIMP
    1997               1 : nsXPConnect::ClearAllWrappedNativeSecurityPolicies()
    1998                 : {
    1999               2 :     XPCCallContext ccx(NATIVE_CALLER);
    2000               1 :     if (!ccx.IsValid())
    2001               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2002                 : 
    2003               1 :     return XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies(ccx);
    2004                 : }
    2005                 : 
    2006                 : NS_IMETHODIMP
    2007               0 : nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
    2008                 :                            nsIXPConnectJSObjectHolder **_retval)
    2009                 : {
    2010               0 :     XPCCallContext ccx(NATIVE_CALLER, cx);
    2011               0 :     if (!ccx.IsValid())
    2012               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2013                 : 
    2014               0 :     *_retval = nsnull;
    2015                 : 
    2016               0 :     jsval rval = JSVAL_VOID;
    2017               0 :     AUTO_MARK_JSVAL(ccx, &rval);
    2018                 : 
    2019                 :     nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal, NULL, false,
    2020               0 :                                           EmptyCString());
    2021               0 :     NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
    2022                 :                  "Bad return value from xpc_CreateSandboxObject()!");
    2023                 : 
    2024               0 :     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
    2025               0 :         *_retval = XPCJSObjectHolder::newHolder(ccx, JSVAL_TO_OBJECT(rval));
    2026               0 :         NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
    2027                 : 
    2028               0 :         NS_ADDREF(*_retval);
    2029                 :     }
    2030                 : 
    2031               0 :     return rv;
    2032                 : }
    2033                 : 
    2034                 : NS_IMETHODIMP
    2035               0 : nsXPConnect::EvalInSandboxObject(const nsAString& source, JSContext *cx,
    2036                 :                                  nsIXPConnectJSObjectHolder *sandbox,
    2037                 :                                  bool returnStringOnly, jsval *rval)
    2038                 : {
    2039               0 :     if (!sandbox)
    2040               0 :         return NS_ERROR_INVALID_ARG;
    2041                 : 
    2042                 :     JSObject *obj;
    2043               0 :     nsresult rv = sandbox->GetJSObject(&obj);
    2044               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2045                 : 
    2046                 :     return xpc_EvalInSandbox(cx, obj, source,
    2047               0 :                              NS_ConvertUTF16toUTF8(source).get(), 1,
    2048               0 :                              JSVERSION_DEFAULT, returnStringOnly, rval);
    2049                 : }
    2050                 : 
    2051                 : /* nsIXPConnectJSObjectHolder getWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo); */
    2052                 : NS_IMETHODIMP
    2053               0 : nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext,
    2054                 :                                        JSObject * aScope,
    2055                 :                                        nsIClassInfo *aClassInfo,
    2056                 :                                        nsIXPConnectJSObjectHolder **_retval)
    2057                 : {
    2058               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    2059               0 :     if (!ccx.IsValid())
    2060               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2061                 : 
    2062               0 :     JSAutoEnterCompartment ac;
    2063               0 :     if (!ac.enter(aJSContext, aScope))
    2064               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2065                 : 
    2066                 :     XPCWrappedNativeScope* scope =
    2067               0 :         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
    2068               0 :     if (!scope)
    2069               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2070                 : 
    2071               0 :     XPCNativeScriptableCreateInfo sciProto;
    2072               0 :     XPCWrappedNative::GatherProtoScriptableCreateInfo(aClassInfo, sciProto);
    2073                 : 
    2074               0 :     AutoMarkingWrappedNativeProtoPtr proto(ccx);
    2075               0 :     proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, scope, aClassInfo, &sciProto);
    2076               0 :     if (!proto)
    2077               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2078                 : 
    2079                 :     nsIXPConnectJSObjectHolder* holder;
    2080                 :     *_retval = holder = XPCJSObjectHolder::newHolder(ccx,
    2081               0 :                                                      proto->GetJSProtoObject());
    2082               0 :     if (!holder)
    2083               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2084                 : 
    2085               0 :     NS_ADDREF(holder);
    2086               0 :     return NS_OK;
    2087                 : }
    2088                 : 
    2089                 : /* void releaseJSContext (in JSContextPtr aJSContext, in bool noGC); */
    2090                 : NS_IMETHODIMP
    2091               0 : nsXPConnect::ReleaseJSContext(JSContext * aJSContext, bool noGC)
    2092                 : {
    2093               0 :     NS_ASSERTION(aJSContext, "bad param");
    2094               0 :     XPCPerThreadData* tls = XPCPerThreadData::GetData(aJSContext);
    2095               0 :     if (tls) {
    2096               0 :         XPCCallContext* ccx = nsnull;
    2097               0 :         for (XPCCallContext* cur = tls->GetCallContext();
    2098                 :              cur;
    2099                 :              cur = cur->GetPrevCallContext()) {
    2100               0 :             if (cur->GetJSContext() == aJSContext) {
    2101               0 :                 ccx = cur;
    2102                 :                 // Keep looping to find the deepest matching call context.
    2103                 :             }
    2104                 :         }
    2105                 : 
    2106               0 :         if (ccx) {
    2107                 : #ifdef DEBUG_xpc_hacker
    2108                 :             printf("!xpc - deferring destruction of JSContext @ %p\n",
    2109                 :                    (void *)aJSContext);
    2110                 : #endif
    2111               0 :             ccx->SetDestroyJSContextInDestructor(true);
    2112               0 :             return NS_OK;
    2113                 :         }
    2114                 :         // else continue on and synchronously destroy the JSContext ...
    2115                 : 
    2116               0 :         NS_ASSERTION(!tls->GetJSContextStack() ||
    2117                 :                      !tls->GetJSContextStack()->
    2118                 :                      DEBUG_StackHasJSContext(aJSContext),
    2119                 :                      "JSContext still in threadjscontextstack!");
    2120                 :     }
    2121                 : 
    2122               0 :     if (noGC)
    2123               0 :         JS_DestroyContextNoGC(aJSContext);
    2124                 :     else
    2125               0 :         JS_DestroyContext(aJSContext);
    2126               0 :     return NS_OK;
    2127                 : }
    2128                 : 
    2129                 : /* void debugDump (in short depth); */
    2130                 : NS_IMETHODIMP
    2131               0 : nsXPConnect::DebugDump(PRInt16 depth)
    2132                 : {
    2133                 : #ifdef DEBUG
    2134               0 :     depth-- ;
    2135               0 :     XPC_LOG_ALWAYS(("nsXPConnect @ %x with mRefCnt = %d", this, mRefCnt.get()));
    2136               0 :     XPC_LOG_INDENT();
    2137               0 :         XPC_LOG_ALWAYS(("gSelf @ %x", gSelf));
    2138               0 :         XPC_LOG_ALWAYS(("gOnceAliveNowDead is %d", (int)gOnceAliveNowDead));
    2139               0 :         XPC_LOG_ALWAYS(("mDefaultSecurityManager @ %x", mDefaultSecurityManager));
    2140               0 :         XPC_LOG_ALWAYS(("mDefaultSecurityManagerFlags of %x", mDefaultSecurityManagerFlags));
    2141               0 :         XPC_LOG_ALWAYS(("mInterfaceInfoManager @ %x", mInterfaceInfoManager.get()));
    2142               0 :         if (mRuntime) {
    2143               0 :             if (depth)
    2144               0 :                 mRuntime->DebugDump(depth);
    2145                 :             else
    2146               0 :                 XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", mRuntime));
    2147                 :         } else
    2148               0 :             XPC_LOG_ALWAYS(("mRuntime is null"));
    2149               0 :         XPCWrappedNativeScope::DebugDumpAllScopes(depth);
    2150               0 :     XPC_LOG_OUTDENT();
    2151                 : #endif
    2152               0 :     return NS_OK;
    2153                 : }
    2154                 : 
    2155                 : /* void debugDumpObject (in nsISupports aCOMObj, in short depth); */
    2156                 : NS_IMETHODIMP
    2157               0 : nsXPConnect::DebugDumpObject(nsISupports *p, PRInt16 depth)
    2158                 : {
    2159                 : #ifdef DEBUG
    2160               0 :     if (!depth)
    2161               0 :         return NS_OK;
    2162               0 :     if (!p) {
    2163               0 :         XPC_LOG_ALWAYS(("*** Cound not dump object with NULL address"));
    2164               0 :         return NS_OK;
    2165                 :     }
    2166                 : 
    2167                 :     nsIXPConnect* xpc;
    2168                 :     nsIXPCWrappedJSClass* wjsc;
    2169                 :     nsIXPConnectWrappedNative* wn;
    2170                 :     nsIXPConnectWrappedJS* wjs;
    2171                 : 
    2172               0 :     if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnect),
    2173                 :                                        (void**)&xpc))) {
    2174               0 :         XPC_LOG_ALWAYS(("Dumping a nsIXPConnect..."));
    2175               0 :         xpc->DebugDump(depth);
    2176               0 :         NS_RELEASE(xpc);
    2177               0 :     } else if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPCWrappedJSClass),
    2178                 :                                               (void**)&wjsc))) {
    2179               0 :         XPC_LOG_ALWAYS(("Dumping a nsIXPCWrappedJSClass..."));
    2180               0 :         wjsc->DebugDump(depth);
    2181               0 :         NS_RELEASE(wjsc);
    2182               0 :     } else if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnectWrappedNative),
    2183                 :                                               (void**)&wn))) {
    2184               0 :         XPC_LOG_ALWAYS(("Dumping a nsIXPConnectWrappedNative..."));
    2185               0 :         wn->DebugDump(depth);
    2186               0 :         NS_RELEASE(wn);
    2187               0 :     } else if (NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnectWrappedJS),
    2188                 :                                               (void**)&wjs))) {
    2189               0 :         XPC_LOG_ALWAYS(("Dumping a nsIXPConnectWrappedJS..."));
    2190               0 :         wjs->DebugDump(depth);
    2191               0 :         NS_RELEASE(wjs);
    2192                 :     } else
    2193               0 :         XPC_LOG_ALWAYS(("*** Could not dump the nsISupports @ %x", p));
    2194                 : #endif
    2195               0 :     return NS_OK;
    2196                 : }
    2197                 : 
    2198                 : /* void debugDumpJSStack (in bool showArgs, in bool showLocals, in bool showThisProps); */
    2199                 : NS_IMETHODIMP
    2200               0 : nsXPConnect::DebugDumpJSStack(bool showArgs,
    2201                 :                               bool showLocals,
    2202                 :                               bool showThisProps)
    2203                 : {
    2204                 :     JSContext* cx;
    2205               0 :     if (NS_FAILED(Peek(&cx)))
    2206               0 :         printf("failed to peek into nsIThreadJSContextStack service!\n");
    2207               0 :     else if (!cx)
    2208               0 :         printf("there is no JSContext on the nsIThreadJSContextStack!\n");
    2209                 :     else
    2210               0 :         xpc_DumpJSStack(cx, showArgs, showLocals, showThisProps);
    2211                 : 
    2212               0 :     return NS_OK;
    2213                 : }
    2214                 : 
    2215                 : char*
    2216               0 : nsXPConnect::DebugPrintJSStack(bool showArgs,
    2217                 :                                bool showLocals,
    2218                 :                                bool showThisProps)
    2219                 : {
    2220                 :     JSContext* cx;
    2221               0 :     if (NS_FAILED(Peek(&cx)))
    2222               0 :         printf("failed to peek into nsIThreadJSContextStack service!\n");
    2223               0 :     else if (!cx)
    2224               0 :         printf("there is no JSContext on the nsIThreadJSContextStack!\n");
    2225                 :     else
    2226               0 :         return xpc_PrintJSStack(cx, showArgs, showLocals, showThisProps);
    2227                 : 
    2228               0 :     return nsnull;
    2229                 : }
    2230                 : 
    2231                 : /* void debugDumpEvalInJSStackFrame (in PRUint32 aFrameNumber, in string aSourceText); */
    2232                 : NS_IMETHODIMP
    2233               0 : nsXPConnect::DebugDumpEvalInJSStackFrame(PRUint32 aFrameNumber, const char *aSourceText)
    2234                 : {
    2235                 :     JSContext* cx;
    2236               0 :     if (NS_FAILED(Peek(&cx)))
    2237               0 :         printf("failed to peek into nsIThreadJSContextStack service!\n");
    2238               0 :     else if (!cx)
    2239               0 :         printf("there is no JSContext on the nsIThreadJSContextStack!\n");
    2240                 :     else
    2241               0 :         xpc_DumpEvalInJSStackFrame(cx, aFrameNumber, aSourceText);
    2242                 : 
    2243               0 :     return NS_OK;
    2244                 : }
    2245                 : 
    2246                 : /* jsval variantToJS (in JSContextPtr ctx, in JSObjectPtr scope, in nsIVariant value); */
    2247                 : NS_IMETHODIMP
    2248               0 : nsXPConnect::VariantToJS(JSContext* ctx, JSObject* scope, nsIVariant* value, jsval* _retval)
    2249                 : {
    2250               0 :     NS_PRECONDITION(ctx, "bad param");
    2251               0 :     NS_PRECONDITION(scope, "bad param");
    2252               0 :     NS_PRECONDITION(value, "bad param");
    2253               0 :     NS_PRECONDITION(_retval, "bad param");
    2254                 : 
    2255               0 :     XPCCallContext ccx(NATIVE_CALLER, ctx);
    2256               0 :     if (!ccx.IsValid())
    2257               0 :         return NS_ERROR_FAILURE;
    2258               0 :     XPCLazyCallContext lccx(ccx);
    2259                 : 
    2260               0 :     ccx.SetScopeForNewJSObjects(scope);
    2261                 : 
    2262               0 :     nsresult rv = NS_OK;
    2263               0 :     if (!XPCVariant::VariantDataToJS(lccx, value, &rv, _retval)) {
    2264               0 :         if (NS_FAILED(rv))
    2265               0 :             return rv;
    2266                 : 
    2267               0 :         return NS_ERROR_FAILURE;
    2268                 :     }
    2269                 : 
    2270               0 :     return NS_OK;
    2271                 : }
    2272                 : 
    2273                 : /* nsIVariant JSToVariant (in JSContextPtr ctx, in jsval value); */
    2274                 : NS_IMETHODIMP
    2275               0 : nsXPConnect::JSToVariant(JSContext* ctx, const jsval &value, nsIVariant** _retval)
    2276                 : {
    2277               0 :     NS_PRECONDITION(ctx, "bad param");
    2278               0 :     NS_PRECONDITION(value != JSVAL_NULL, "bad param");
    2279               0 :     NS_PRECONDITION(_retval, "bad param");
    2280                 : 
    2281               0 :     XPCCallContext ccx(NATIVE_CALLER, ctx);
    2282               0 :     if (!ccx.IsValid())
    2283               0 :         return NS_ERROR_FAILURE;
    2284                 : 
    2285               0 :     *_retval = XPCVariant::newVariant(ccx, value);
    2286               0 :     if (!(*_retval))
    2287               0 :         return NS_ERROR_FAILURE;
    2288                 : 
    2289               0 :     return NS_OK;
    2290                 : }
    2291                 : 
    2292                 : NS_IMETHODIMP
    2293          174528 : nsXPConnect::OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait,
    2294                 :                                 PRUint32 aRecursionDepth)
    2295                 : {
    2296                 :     // Record this event.
    2297          174528 :     mEventDepth++;
    2298                 : 
    2299                 :     // Push a null JSContext so that we don't see any script during
    2300                 :     // event processing.
    2301          174528 :     MOZ_ASSERT(NS_IsMainThread());
    2302          174528 :     return Push(nsnull);
    2303                 : }
    2304                 : 
    2305                 : NS_IMETHODIMP
    2306          174530 : nsXPConnect::AfterProcessNextEvent(nsIThreadInternal *aThread,
    2307                 :                                    PRUint32 aRecursionDepth)
    2308                 : {
    2309                 :     // Watch out for unpaired events during observer registration.
    2310          174530 :     if (NS_UNLIKELY(mEventDepth == 0))
    2311               2 :         return NS_OK;
    2312          174528 :     mEventDepth--;
    2313                 : 
    2314                 :     // Call cycle collector occasionally.
    2315          174528 :     MOZ_ASSERT(NS_IsMainThread());
    2316          174528 :     nsJSContext::MaybePokeCC();
    2317                 : 
    2318          174528 :     return Pop(nsnull);
    2319                 : }
    2320                 : 
    2321                 : NS_IMETHODIMP
    2322               0 : nsXPConnect::OnDispatchedEvent(nsIThreadInternal* aThread)
    2323                 : {
    2324               0 :     NS_NOTREACHED("Why tell us?");
    2325               0 :     return NS_ERROR_UNEXPECTED;
    2326                 : }
    2327                 : 
    2328                 : NS_IMETHODIMP
    2329            7458 : nsXPConnect::AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer)
    2330                 : {
    2331            7458 :     return mRuntime->AddJSHolder(aHolder, aTracer);
    2332                 : }
    2333                 : 
    2334                 : NS_IMETHODIMP
    2335            7456 : nsXPConnect::RemoveJSHolder(void* aHolder)
    2336                 : {
    2337            7456 :     return mRuntime->RemoveJSHolder(aHolder);
    2338                 : }
    2339                 : 
    2340                 : NS_IMETHODIMP
    2341              50 : nsXPConnect::SetReportAllJSExceptions(bool newval)
    2342                 : {
    2343                 :     // Ignore if the environment variable was set.
    2344              50 :     if (gReportAllJSExceptions != 1)
    2345              50 :         gReportAllJSExceptions = newval ? 2 : 0;
    2346                 : 
    2347              50 :     return NS_OK;
    2348                 : }
    2349                 : 
    2350                 : /* [noscript, notxpcom] bool defineDOMQuickStubs (in JSContextPtr cx, in JSObjectPtr proto, in PRUint32 flags, in PRUint32 interfaceCount, [array, size_is (interfaceCount)] in nsIIDPtr interfaceArray); */
    2351                 : NS_IMETHODIMP_(bool)
    2352            2781 : nsXPConnect::DefineDOMQuickStubs(JSContext * cx,
    2353                 :                                  JSObject * proto,
    2354                 :                                  PRUint32 flags,
    2355                 :                                  PRUint32 interfaceCount,
    2356                 :                                  const nsIID * *interfaceArray)
    2357                 : {
    2358                 :     return DOM_DefineQuickStubs(cx, proto, flags,
    2359            2781 :                                 interfaceCount, interfaceArray);
    2360                 : }
    2361                 : 
    2362                 : /* attribute JSRuntime runtime; */
    2363                 : NS_IMETHODIMP
    2364            3806 : nsXPConnect::GetRuntime(JSRuntime **runtime)
    2365                 : {
    2366            3806 :     if (!runtime)
    2367               0 :         return NS_ERROR_NULL_POINTER;
    2368                 : 
    2369            3806 :     JSRuntime *rt = GetRuntime()->GetJSRuntime();
    2370            3806 :     JS_AbortIfWrongThread(rt);
    2371            3806 :     *runtime = rt;
    2372            3806 :     return NS_OK;
    2373                 : }
    2374                 : 
    2375                 : /* attribute nsIXPCScriptable backstagePass; */
    2376                 : NS_IMETHODIMP
    2377           13217 : nsXPConnect::GetBackstagePass(nsIXPCScriptable **bsp)
    2378                 : {
    2379           13217 :     if (!mBackstagePass) {
    2380            2782 :         nsCOMPtr<nsIPrincipal> sysprin;
    2381                 :         nsCOMPtr<nsIScriptSecurityManager> secman =
    2382            2782 :             do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
    2383            1391 :         if (!secman)
    2384               0 :             return NS_ERROR_NOT_AVAILABLE;
    2385            1391 :         if (NS_FAILED(secman->GetSystemPrincipal(getter_AddRefs(sysprin))))
    2386               0 :             return NS_ERROR_NOT_AVAILABLE;
    2387                 : 
    2388            2782 :         mBackstagePass = new BackstagePass(sysprin);
    2389            1391 :         if (!mBackstagePass)
    2390               0 :             return NS_ERROR_OUT_OF_MEMORY;
    2391                 :     }
    2392           13217 :     NS_ADDREF(*bsp = mBackstagePass);
    2393           13217 :     return NS_OK;
    2394                 : }
    2395                 : 
    2396                 : /* [noscript, notxpcom] void registerGCCallback(in JSGCCallback func); */
    2397                 : NS_IMETHODIMP_(void)
    2398               0 : nsXPConnect::RegisterGCCallback(JSGCCallback func)
    2399                 : {
    2400               0 :     mRuntime->AddGCCallback(func);
    2401               0 : }
    2402                 : 
    2403                 : /* [noscript, notxpcom] void unregisterGCCallback(in JSGCCallback func); */
    2404                 : NS_IMETHODIMP_(void)
    2405               0 : nsXPConnect::UnregisterGCCallback(JSGCCallback func)
    2406                 : {
    2407               0 :     mRuntime->RemoveGCCallback(func);
    2408               0 : }
    2409                 : 
    2410                 : //  nsIJSContextStack and nsIThreadJSContextStack implementations
    2411                 : 
    2412                 : /* readonly attribute PRInt32 Count; */
    2413                 : NS_IMETHODIMP
    2414               0 : nsXPConnect::GetCount(PRInt32 *aCount)
    2415                 : {
    2416               0 :     MOZ_ASSERT(aCount);
    2417                 : 
    2418               0 :     XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    2419                 : 
    2420               0 :     if (!data) {
    2421               0 :         *aCount = 0;
    2422               0 :         return NS_ERROR_FAILURE;
    2423                 :     }
    2424                 : 
    2425               0 :     *aCount = data->GetJSContextStack()->Count();
    2426               0 :     return NS_OK;
    2427                 : }
    2428                 : 
    2429                 : /* JSContext Peek (); */
    2430                 : NS_IMETHODIMP
    2431          721373 : nsXPConnect::Peek(JSContext * *_retval)
    2432                 : {
    2433          721373 :     MOZ_ASSERT(_retval);
    2434                 : 
    2435          721373 :     XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    2436                 : 
    2437          721373 :     if (!data) {
    2438               0 :         *_retval = nsnull;
    2439               0 :         return NS_ERROR_FAILURE;
    2440                 :     }
    2441                 : 
    2442          721373 :     *_retval = data->GetJSContextStack()->Peek();
    2443          721373 :     return NS_OK;
    2444                 : }
    2445                 : 
    2446                 : void
    2447             280 : nsXPConnect::CheckForDebugMode(JSRuntime *rt) {
    2448             280 :     JSContext *cx = NULL;
    2449                 : 
    2450             280 :     if (gDebugMode == gDesiredDebugMode) {
    2451               0 :         return;
    2452                 :     }
    2453                 : 
    2454                 :     // This can happen if a Worker is running, but we don't have the ability to
    2455                 :     // debug workers right now, so just return.
    2456             280 :     if (!NS_IsMainThread()) {
    2457               0 :         return;
    2458                 :     }
    2459                 : 
    2460             280 :     JS_SetRuntimeDebugMode(rt, gDesiredDebugMode);
    2461                 : 
    2462                 :     nsresult rv;
    2463             280 :     const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
    2464             560 :     nsCOMPtr<jsdIDebuggerService> jsds = do_GetService(jsdServiceCtrID, &rv);
    2465             280 :     if (NS_FAILED(rv)) {
    2466               0 :         goto fail;
    2467                 :     }
    2468                 : 
    2469             280 :     if (!(cx = JS_NewContext(rt, 256))) {
    2470               0 :         goto fail;
    2471                 :     }
    2472                 : 
    2473                 :     {
    2474                 :         struct AutoDestroyContext {
    2475                 :             JSContext *cx;
    2476             280 :             AutoDestroyContext(JSContext *cx) : cx(cx) {}
    2477             280 :             ~AutoDestroyContext() { JS_DestroyContext(cx); }
    2478             560 :         } adc(cx);
    2479             560 :         JSAutoRequest ar(cx);
    2480                 : 
    2481             280 :         const js::CompartmentVector &vector = js::GetRuntimeCompartments(rt);
    2482            1120 :         for (JSCompartment * const *p = vector.begin(); p != vector.end(); ++p) {
    2483             840 :             JSCompartment *comp = *p;
    2484             840 :             if (!JS_GetCompartmentPrincipals(comp)) {
    2485                 :                 /* Ignore special compartments (atoms, JSD compartments) */
    2486             280 :                 continue;
    2487                 :             }
    2488                 : 
    2489             560 :             if (!JS_SetDebugModeForCompartment(cx, comp, gDesiredDebugMode))
    2490                 :                 goto fail;
    2491                 :         }
    2492                 :     }
    2493                 : 
    2494             280 :     if (gDesiredDebugMode) {
    2495             280 :         rv = jsds->ActivateDebugger(rt);
    2496                 :     }
    2497                 : 
    2498             280 :     gDebugMode = gDesiredDebugMode;
    2499                 :     return;
    2500                 : 
    2501                 : fail:
    2502               0 :     if (jsds)
    2503               0 :         jsds->DeactivateDebugger();
    2504                 : 
    2505                 :     /*
    2506                 :      * If an attempt to turn debug mode on fails, cancel the request. It's
    2507                 :      * always safe to turn debug mode off, since DeactivateDebugger prevents
    2508                 :      * debugger callbacks from having any effect.
    2509                 :      */
    2510               0 :     if (gDesiredDebugMode)
    2511               0 :         JS_SetRuntimeDebugMode(rt, false);
    2512               0 :     gDesiredDebugMode = gDebugMode = false;
    2513                 : }
    2514                 : 
    2515                 : NS_EXPORT_(void)
    2516             280 : xpc_ActivateDebugMode()
    2517                 : {
    2518             280 :     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
    2519             280 :     nsXPConnect::GetXPConnect()->SetDebugModeWhenPossible(true, true);
    2520             280 :     nsXPConnect::CheckForDebugMode(rt->GetJSRuntime());
    2521             280 : }
    2522                 : 
    2523                 : /* JSContext Pop (); */
    2524                 : NS_IMETHODIMP
    2525          239307 : nsXPConnect::Pop(JSContext * *_retval)
    2526                 : {
    2527          239307 :     XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    2528                 : 
    2529          239307 :     if (!data) {
    2530               0 :         if (_retval)
    2531               0 :             *_retval = NULL;
    2532               0 :         return NS_ERROR_FAILURE;
    2533                 :     }
    2534                 : 
    2535          239307 :     JSContext *cx = data->GetJSContextStack()->Pop();
    2536          239307 :     if (_retval)
    2537            3119 :         *_retval = cx;
    2538          239307 :     return NS_OK;
    2539                 : }
    2540                 : 
    2541                 : /* void Push (in JSContext cx); */
    2542                 : NS_IMETHODIMP
    2543          239307 : nsXPConnect::Push(JSContext * cx)
    2544                 : {
    2545          239307 :     XPCPerThreadData* data = XPCPerThreadData::GetData(cx);
    2546                 : 
    2547          239307 :     if (!data)
    2548               0 :         return NS_ERROR_FAILURE;
    2549                 : 
    2550          239307 :      if (gDebugMode != gDesiredDebugMode && NS_IsMainThread()) {
    2551               0 :          const InfallibleTArray<XPCJSContextInfo>* stack = data->GetJSContextStack()->GetStack();
    2552               0 :          if (!gDesiredDebugMode) {
    2553                 :              /* Turn off debug mode immediately, even if JS code is currently running */
    2554               0 :              CheckForDebugMode(mRuntime->GetJSRuntime());
    2555                 :          } else {
    2556               0 :              bool runningJS = false;
    2557               0 :              for (PRUint32 i = 0; i < stack->Length(); ++i) {
    2558               0 :                  JSContext *cx = (*stack)[i].cx;
    2559               0 :                  if (cx && js::IsContextRunningJS(cx)) {
    2560               0 :                      runningJS = true;
    2561               0 :                      break;
    2562                 :                  }
    2563                 :              }
    2564               0 :              if (!runningJS)
    2565               0 :                  CheckForDebugMode(mRuntime->GetJSRuntime());
    2566                 :          }
    2567                 :      }
    2568                 : 
    2569          239307 :      return data->GetJSContextStack()->Push(cx) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
    2570                 : }
    2571                 : 
    2572                 : /* attribute JSContext SafeJSContext; */
    2573                 : NS_IMETHODIMP
    2574            5922 : nsXPConnect::GetSafeJSContext(JSContext * *aSafeJSContext)
    2575                 : {
    2576            5922 :     NS_ASSERTION(aSafeJSContext, "loser!");
    2577                 : 
    2578            5922 :     XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
    2579                 : 
    2580            5922 :     if (!data) {
    2581               0 :         *aSafeJSContext = nsnull;
    2582               0 :         return NS_ERROR_FAILURE;
    2583                 :     }
    2584                 : 
    2585            5922 :     *aSafeJSContext = data->GetJSContextStack()->GetSafeJSContext();
    2586            5922 :     return *aSafeJSContext ? NS_OK : NS_ERROR_FAILURE;
    2587                 : }
    2588                 : 
    2589                 : nsIPrincipal*
    2590         3735290 : nsXPConnect::GetPrincipal(JSObject* obj, bool allowShortCircuit) const
    2591                 : {
    2592         3735290 :     NS_ASSERTION(IS_WRAPPER_CLASS(js::GetObjectClass(obj)),
    2593                 :                  "What kind of wrapper is this?");
    2594                 : 
    2595         3735290 :     if (IS_WN_WRAPPER_OBJECT(obj)) {
    2596                 :         XPCWrappedNative *xpcWrapper =
    2597         3735290 :             (XPCWrappedNative *)xpc_GetJSPrivate(obj);
    2598         3735290 :         if (xpcWrapper) {
    2599         3735290 :             if (allowShortCircuit) {
    2600         1867645 :                 nsIPrincipal *result = xpcWrapper->GetObjectPrincipal();
    2601         1867645 :                 if (result) {
    2602         1867645 :                     return result;
    2603                 :                 }
    2604                 :             }
    2605                 : 
    2606                 :             // If not, check if it points to an nsIScriptObjectPrincipal
    2607                 :             nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
    2608         3735290 :                 do_QueryInterface(xpcWrapper->Native());
    2609         1867645 :             if (objPrin) {
    2610         1867645 :                 nsIPrincipal *result = objPrin->GetPrincipal();
    2611         1867645 :                 if (result) {
    2612         1867645 :                     return result;
    2613                 :                 }
    2614                 :             }
    2615                 :         }
    2616                 :     } else {
    2617               0 :         if (allowShortCircuit) {
    2618                 :             nsIPrincipal *result =
    2619               0 :                 GetSlimWrapperProto(obj)->GetScope()->GetPrincipal();
    2620               0 :             if (result) {
    2621               0 :                 return result;
    2622                 :             }
    2623                 :         }
    2624                 : 
    2625                 :         nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
    2626               0 :             do_QueryInterface((nsISupports*)xpc_GetJSPrivate(obj));
    2627               0 :         if (objPrin) {
    2628               0 :             nsIPrincipal *result = objPrin->GetPrincipal();
    2629               0 :             if (result) {
    2630               0 :                 return result;
    2631                 :             }
    2632                 :         }
    2633                 :     }
    2634                 : 
    2635               0 :     return nsnull;
    2636                 : }
    2637                 : 
    2638                 : NS_IMETHODIMP
    2639               0 : nsXPConnect::HoldObject(JSContext *aJSContext, JSObject *aObject,
    2640                 :                         nsIXPConnectJSObjectHolder **aHolder)
    2641                 : {
    2642               0 :     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
    2643               0 :     XPCJSObjectHolder* objHolder = XPCJSObjectHolder::newHolder(ccx, aObject);
    2644               0 :     if (!objHolder)
    2645               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2646                 : 
    2647               0 :     NS_ADDREF(*aHolder = objHolder);
    2648               0 :     return NS_OK;
    2649                 : }
    2650                 : 
    2651                 : NS_IMETHODIMP_(void)
    2652               0 : nsXPConnect::GetCaller(JSContext **aJSContext, JSObject **aObj)
    2653                 : {
    2654               0 :     XPCCallContext *ccx = XPCPerThreadData::GetData(nsnull)->GetCallContext();
    2655               0 :     *aJSContext = ccx->GetJSContext();
    2656                 : 
    2657                 :     // Set to the caller in XPC_WN_Helper_{Call,Construct}
    2658               0 :     *aObj = ccx->GetFlattenedJSObject();
    2659               0 : }
    2660                 : 
    2661                 : namespace xpc {
    2662                 : 
    2663                 : bool
    2664            6763 : Base64Encode(JSContext *cx, JS::Value val, JS::Value *out)
    2665                 : {
    2666            6763 :     MOZ_ASSERT(cx);
    2667            6763 :     MOZ_ASSERT(out);
    2668                 : 
    2669            6763 :     JS::Value root = val;
    2670                 :     xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
    2671           13526 :                                  xpc_qsACString::eStringify);
    2672            6763 :     if (!encodedString.IsValid())
    2673               0 :         return false;
    2674                 : 
    2675           13526 :     nsCAutoString result;
    2676            6763 :     if (NS_FAILED(mozilla::Base64Encode(encodedString, result))) {
    2677               0 :         JS_ReportError(cx, "Failed to encode base64 data!");
    2678               0 :         return false;
    2679                 :     }
    2680                 : 
    2681            6763 :     JSString *str = JS_NewStringCopyN(cx, result.get(), result.Length());
    2682            6763 :     if (!str)
    2683               0 :         return false;
    2684                 : 
    2685            6763 :     *out = STRING_TO_JSVAL(str);
    2686            6763 :     return true;
    2687                 : }
    2688                 : 
    2689                 : bool
    2690            1070 : Base64Decode(JSContext *cx, JS::Value val, JS::Value *out)
    2691                 : {
    2692            1070 :     MOZ_ASSERT(cx);
    2693            1070 :     MOZ_ASSERT(out);
    2694                 : 
    2695            1070 :     JS::Value root = val;
    2696                 :     xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
    2697            2140 :                                  xpc_qsACString::eNull);
    2698            1070 :     if (!encodedString.IsValid())
    2699               0 :         return false;
    2700                 : 
    2701            2140 :     nsCAutoString result;
    2702            1070 :     if (NS_FAILED(mozilla::Base64Decode(encodedString, result))) {
    2703               0 :         JS_ReportError(cx, "Failed to decode base64 string!");
    2704               0 :         return false;
    2705                 :     }
    2706                 : 
    2707            1070 :     JSString *str = JS_NewStringCopyN(cx, result.get(), result.Length());
    2708            1070 :     if (!str)
    2709               0 :         return false;
    2710                 : 
    2711            1070 :     *out = STRING_TO_JSVAL(str);
    2712            1070 :     return true;
    2713                 : }
    2714                 : 
    2715                 : #ifdef DEBUG
    2716                 : void
    2717               0 : DumpJSHeap(FILE* file)
    2718                 : {
    2719               0 :     NS_ABORT_IF_FALSE(NS_IsMainThread(), "Must dump GC heap on main thread.");
    2720               0 :     nsXPConnect* xpc = nsXPConnect::GetXPConnect();
    2721               0 :     if (!xpc) {
    2722               0 :         NS_ERROR("Failed to get nsXPConnect instance!");
    2723               0 :         return;
    2724                 :     }
    2725               0 :     js::DumpHeapComplete(xpc->GetRuntime()->GetJSRuntime(), file);
    2726                 : }
    2727                 : #endif
    2728                 : 
    2729                 : } // namespace xpc
    2730                 : 
    2731                 : NS_IMETHODIMP
    2732             280 : nsXPConnect::SetDebugModeWhenPossible(bool mode, bool allowSyncDisable)
    2733                 : {
    2734             280 :     gDesiredDebugMode = mode;
    2735             280 :     if (!mode && allowSyncDisable)
    2736               0 :         CheckForDebugMode(mRuntime->GetJSRuntime());
    2737             280 :     return NS_OK;
    2738                 : }
    2739                 : 
    2740                 : NS_IMETHODIMP
    2741               3 : nsXPConnect::GetTelemetryValue(JSContext *cx, jsval *rval)
    2742                 : {
    2743               3 :     JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
    2744               3 :     if (!obj)
    2745               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2746                 : 
    2747               3 :     unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
    2748                 : 
    2749               3 :     size_t i = JS_GetE4XObjectsCreated(cx);
    2750               3 :     jsval v = DOUBLE_TO_JSVAL(i);
    2751               3 :     if (!JS_DefineProperty(cx, obj, "e4x", v, NULL, NULL, attrs))
    2752               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2753                 : 
    2754               3 :     i = JS_SetProtoCalled(cx);
    2755               3 :     v = DOUBLE_TO_JSVAL(i);
    2756               3 :     if (!JS_DefineProperty(cx, obj, "setProto", v, NULL, NULL, attrs))
    2757               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2758                 : 
    2759               3 :     i = JS_GetCustomIteratorCount(cx);
    2760               3 :     v = DOUBLE_TO_JSVAL(i);
    2761               3 :     if (!JS_DefineProperty(cx, obj, "customIter", v, NULL, NULL, attrs))
    2762               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2763                 : 
    2764               3 :     *rval = OBJECT_TO_JSVAL(obj);
    2765               3 :     return NS_OK;
    2766                 : }
    2767                 : 
    2768                 : NS_IMETHODIMP
    2769               0 : nsXPConnect::NotifyDidPaint()
    2770                 : {
    2771               0 :     JSRuntime *rt = mRuntime->GetJSRuntime();
    2772               0 :     if (!js::WantGCSlice(rt))
    2773               0 :         return NS_OK;
    2774                 : 
    2775               0 :     XPCCallContext ccx(NATIVE_CALLER);
    2776               0 :     if (!ccx.IsValid())
    2777               0 :         return UnexpectedFailure(NS_ERROR_FAILURE);
    2778                 : 
    2779               0 :     JSContext *cx = ccx.GetJSContext();
    2780                 : 
    2781               0 :     js::NotifyDidPaint(cx);
    2782               0 :     return NS_OK;
    2783                 : }
    2784                 : 
    2785                 : /* These are here to be callable from a debugger */
    2786                 : JS_BEGIN_EXTERN_C
    2787               0 : JS_EXPORT_API(void) DumpJSStack()
    2788                 : {
    2789                 :     nsresult rv;
    2790               0 :     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
    2791               0 :     if (NS_SUCCEEDED(rv) && xpc)
    2792               0 :         xpc->DebugDumpJSStack(true, true, false);
    2793                 :     else
    2794               0 :         printf("failed to get XPConnect service!\n");
    2795               0 : }
    2796                 : 
    2797               0 : JS_EXPORT_API(char*) PrintJSStack()
    2798                 : {
    2799                 :     nsresult rv;
    2800               0 :     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
    2801               0 :     return (NS_SUCCEEDED(rv) && xpc) ?
    2802               0 :         xpc->DebugPrintJSStack(true, true, false) :
    2803               0 :         nsnull;
    2804                 : }
    2805                 : 
    2806               0 : JS_EXPORT_API(void) DumpJSEval(PRUint32 frameno, const char* text)
    2807                 : {
    2808                 :     nsresult rv;
    2809               0 :     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
    2810               0 :     if (NS_SUCCEEDED(rv) && xpc)
    2811               0 :         xpc->DebugDumpEvalInJSStackFrame(frameno, text);
    2812                 :     else
    2813               0 :         printf("failed to get XPConnect service!\n");
    2814               0 : }
    2815                 : 
    2816               0 : JS_EXPORT_API(void) DumpJSObject(JSObject* obj)
    2817                 : {
    2818               0 :     xpc_DumpJSObject(obj);
    2819               0 : }
    2820                 : 
    2821               0 : JS_EXPORT_API(void) DumpJSValue(jsval val)
    2822                 : {
    2823               0 :     printf("Dumping 0x%llu.\n", (long long) JSVAL_TO_IMPL(val).asBits);
    2824               0 :     if (JSVAL_IS_NULL(val)) {
    2825               0 :         printf("Value is null\n");
    2826               0 :     } else if (JSVAL_IS_OBJECT(val) || JSVAL_IS_NULL(val)) {
    2827               0 :         printf("Value is an object\n");
    2828               0 :         JSObject* obj = JSVAL_TO_OBJECT(val);
    2829               0 :         DumpJSObject(obj);
    2830               0 :     } else if (JSVAL_IS_NUMBER(val)) {
    2831               0 :         printf("Value is a number: ");
    2832               0 :         if (JSVAL_IS_INT(val))
    2833               0 :           printf("Integer %i\n", JSVAL_TO_INT(val));
    2834               0 :         else if (JSVAL_IS_DOUBLE(val))
    2835               0 :           printf("Floating-point value %f\n", JSVAL_TO_DOUBLE(val));
    2836               0 :     } else if (JSVAL_IS_STRING(val)) {
    2837               0 :         printf("Value is a string: ");
    2838               0 :         putc('<', stdout);
    2839               0 :         JS_FileEscapedString(stdout, JSVAL_TO_STRING(val), 0);
    2840               0 :         fputs(">\n", stdout);
    2841               0 :     } else if (JSVAL_IS_BOOLEAN(val)) {
    2842               0 :         printf("Value is boolean: ");
    2843               0 :         printf(JSVAL_TO_BOOLEAN(val) ? "true" : "false");
    2844               0 :     } else if (JSVAL_IS_VOID(val)) {
    2845               0 :         printf("Value is undefined\n");
    2846                 :     } else {
    2847               0 :         printf("No idea what this value is.\n");
    2848                 :     }
    2849               0 : }
    2850            4392 : JS_END_EXTERN_C
    2851                 : 

Generated by: LCOV version 1.7