LCOV - code coverage report
Current view: top level - js/xpconnect/src - xpcprivate.h (source / functions) Hit Total Coverage
Test: output.info Lines: 363 504 72.0 %
Date: 2017-07-14 16:53:18 Functions: 201 280 71.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * XPConnect allows JS code to manipulate C++ object and C++ code to manipulate
       9             :  * JS objects. JS manipulation of C++ objects tends to be significantly more
      10             :  * complex. This comment explains how it is orchestrated by XPConnect.
      11             :  *
      12             :  * For each C++ object to be manipulated in JS, there is a corresponding JS
      13             :  * object. This is called the "flattened JS object". By default, there is an
      14             :  * additional C++ object involved of type XPCWrappedNative. The XPCWrappedNative
      15             :  * holds pointers to the C++ object and the flat JS object.
      16             :  *
      17             :  * All XPCWrappedNative objects belong to an XPCWrappedNativeScope. These scopes
      18             :  * are essentially in 1:1 correspondence with JS global objects. The
      19             :  * XPCWrappedNativeScope has a pointer to the JS global object. The parent of a
      20             :  * flattened JS object is, by default, the global JS object corresponding to the
      21             :  * wrapper's XPCWrappedNativeScope (the exception to this rule is when a
      22             :  * PreCreate hook asks for a different parent; see nsIXPCScriptable below).
      23             :  *
      24             :  * Some C++ objects (notably DOM objects) have information associated with them
      25             :  * that lists the interfaces implemented by these objects. A C++ object exposes
      26             :  * this information by implementing nsIClassInfo. If a C++ object implements
      27             :  * nsIClassInfo, then JS code can call its methods without needing to use
      28             :  * QueryInterface first. Typically, all instances of a C++ class share the same
      29             :  * nsIClassInfo instance. (That is, obj->QueryInterface(nsIClassInfo) returns
      30             :  * the same result for every obj of a given class.)
      31             :  *
      32             :  * XPConnect tracks nsIClassInfo information in an XPCWrappedNativeProto object.
      33             :  * A given XPCWrappedNativeScope will have one XPCWrappedNativeProto for each
      34             :  * nsIClassInfo instance being used. The XPCWrappedNativeProto has an associated
      35             :  * JS object, which is used as the prototype of all flattened JS objects created
      36             :  * for C++ objects with the given nsIClassInfo.
      37             :  *
      38             :  * Each XPCWrappedNativeProto has a pointer to its XPCWrappedNativeScope. If an
      39             :  * XPCWrappedNative wraps a C++ object with class info, then it points to its
      40             :  * XPCWrappedNativeProto. Otherwise it points to its XPCWrappedNativeScope. (The
      41             :  * pointers are smooshed together in a tagged union.) Either way it can reach
      42             :  * its scope.
      43             :  *
      44             :  * An XPCWrappedNativeProto keeps track of the set of interfaces implemented by
      45             :  * the C++ object in an XPCNativeSet. (The list of interfaces is obtained by
      46             :  * calling a method on the nsIClassInfo.) An XPCNativeSet is a collection of
      47             :  * XPCNativeInterfaces. Each interface stores the list of members, which can be
      48             :  * methods, constants, getters, or setters.
      49             :  *
      50             :  * An XPCWrappedNative also points to an XPCNativeSet. Initially this starts out
      51             :  * the same as the XPCWrappedNativeProto's set. If there is no proto, it starts
      52             :  * out as a singleton set containing nsISupports. If JS code QI's new interfaces
      53             :  * outside of the existing set, the set will grow. All QueryInterface results
      54             :  * are cached in XPCWrappedNativeTearOff objects, which are linked off of the
      55             :  * XPCWrappedNative.
      56             :  *
      57             :  * Besides having class info, a C++ object may be "scriptable" (i.e., implement
      58             :  * nsIXPCScriptable). This allows it to implement a more DOM-like interface,
      59             :  * besides just exposing XPCOM methods and constants. An nsIXPCScriptable
      60             :  * instance has hooks that correspond to all the normal JSClass hooks. Each
      61             :  * nsIXPCScriptable instance can have pointers from XPCWrappedNativeProto and
      62             :  * XPCWrappedNative (since C++ objects can have scriptable info without having
      63             :  * class info).
      64             :  */
      65             : 
      66             : /* All the XPConnect private declarations - only include locally. */
      67             : 
      68             : #ifndef xpcprivate_h___
      69             : #define xpcprivate_h___
      70             : 
      71             : #include "mozilla/Alignment.h"
      72             : #include "mozilla/ArrayUtils.h"
      73             : #include "mozilla/Assertions.h"
      74             : #include "mozilla/Atomics.h"
      75             : #include "mozilla/Attributes.h"
      76             : #include "mozilla/CycleCollectedJSContext.h"
      77             : #include "mozilla/CycleCollectedJSRuntime.h"
      78             : #include "mozilla/DebugOnly.h"
      79             : #include "mozilla/GuardObjects.h"
      80             : #include "mozilla/Maybe.h"
      81             : #include "mozilla/MemoryReporting.h"
      82             : #include "mozilla/Preferences.h"
      83             : #include "mozilla/TimeStamp.h"
      84             : #include "mozilla/UniquePtr.h"
      85             : 
      86             : #include "mozilla/dom/ScriptSettings.h"
      87             : 
      88             : #include <math.h>
      89             : #include <stdint.h>
      90             : #include <stdlib.h>
      91             : #include <string.h>
      92             : 
      93             : #include "xpcpublic.h"
      94             : #include "js/TracingAPI.h"
      95             : #include "js/WeakMapPtr.h"
      96             : #include "PLDHashTable.h"
      97             : #include "nscore.h"
      98             : #include "nsXPCOM.h"
      99             : #include "nsAutoPtr.h"
     100             : #include "nsCycleCollectionParticipant.h"
     101             : #include "nsDebug.h"
     102             : #include "nsISupports.h"
     103             : #include "nsIServiceManager.h"
     104             : #include "nsIClassInfoImpl.h"
     105             : #include "nsIComponentManager.h"
     106             : #include "nsIComponentRegistrar.h"
     107             : #include "nsISupportsPrimitives.h"
     108             : #include "nsMemory.h"
     109             : #include "nsIXPConnect.h"
     110             : #include "nsIInterfaceInfo.h"
     111             : #include "nsIXPCScriptable.h"
     112             : #include "nsIObserver.h"
     113             : #include "nsWeakReference.h"
     114             : #include "nsCOMPtr.h"
     115             : #include "nsXPTCUtils.h"
     116             : #include "xptinfo.h"
     117             : #include "XPCForwards.h"
     118             : #include "XPCLog.h"
     119             : #include "xpccomponents.h"
     120             : #include "xpcexception.h"
     121             : #include "xpcjsid.h"
     122             : #include "prenv.h"
     123             : #include "prcvar.h"
     124             : #include "nsString.h"
     125             : #include "nsReadableUtils.h"
     126             : #include "nsXPIDLString.h"
     127             : 
     128             : #include "MainThreadUtils.h"
     129             : 
     130             : #include "nsIConsoleService.h"
     131             : #include "nsIException.h"
     132             : 
     133             : #include "nsVariant.h"
     134             : #include "nsIPropertyBag.h"
     135             : #include "nsIProperty.h"
     136             : #include "nsCOMArray.h"
     137             : #include "nsTArray.h"
     138             : #include "nsBaseHashtable.h"
     139             : #include "nsHashKeys.h"
     140             : #include "nsWrapperCache.h"
     141             : #include "nsStringBuffer.h"
     142             : #include "nsDataHashtable.h"
     143             : #include "nsDeque.h"
     144             : 
     145             : #include "nsIScriptSecurityManager.h"
     146             : 
     147             : #include "nsIPrincipal.h"
     148             : #include "nsJSPrincipals.h"
     149             : #include "nsIScriptObjectPrincipal.h"
     150             : #include "xpcObjectHelper.h"
     151             : 
     152             : #include "SandboxPrivate.h"
     153             : #include "BackstagePass.h"
     154             : #include "nsAXPCNativeCallContext.h"
     155             : 
     156             : #ifdef XP_WIN
     157             : // Nasty MS defines
     158             : #ifdef GetClassInfo
     159             : #undef GetClassInfo
     160             : #endif
     161             : #ifdef GetClassName
     162             : #undef GetClassName
     163             : #endif
     164             : #endif /* XP_WIN */
     165             : 
     166             : /***************************************************************************/
     167             : // default initial sizes for maps (hashtables)
     168             : 
     169             : #define XPC_JS_MAP_LENGTH                       32
     170             : #define XPC_JS_CLASS_MAP_LENGTH                 32
     171             : 
     172             : #define XPC_NATIVE_MAP_LENGTH                    8
     173             : #define XPC_NATIVE_PROTO_MAP_LENGTH              8
     174             : #define XPC_DYING_NATIVE_PROTO_MAP_LENGTH        8
     175             : #define XPC_NATIVE_INTERFACE_MAP_LENGTH         32
     176             : #define XPC_NATIVE_SET_MAP_LENGTH               32
     177             : #define XPC_THIS_TRANSLATOR_MAP_LENGTH           4
     178             : #define XPC_WRAPPER_MAP_LENGTH                   8
     179             : 
     180             : /***************************************************************************/
     181             : // data declarations...
     182             : extern const char XPC_CONTEXT_STACK_CONTRACTID[];
     183             : extern const char XPC_EXCEPTION_CONTRACTID[];
     184             : extern const char XPC_CONSOLE_CONTRACTID[];
     185             : extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
     186             : extern const char XPC_ID_CONTRACTID[];
     187             : extern const char XPC_XPCONNECT_CONTRACTID[];
     188             : 
     189             : /***************************************************************************/
     190             : // Useful macros...
     191             : 
     192             : #define XPC_STRING_GETTER_BODY(dest, src)                                     \
     193             :     NS_ENSURE_ARG_POINTER(dest);                                              \
     194             :     char* result;                                                             \
     195             :     if (src)                                                                  \
     196             :         result = (char*) nsMemory::Clone(src,                                 \
     197             :                                          sizeof(char)*(strlen(src)+1));       \
     198             :     else                                                                      \
     199             :         result = nullptr;                                                      \
     200             :     *dest = result;                                                           \
     201             :     return (result || !src) ? NS_OK : NS_ERROR_OUT_OF_MEMORY
     202             : 
     203             : // If IS_WN_CLASS for the JSClass of an object is true, the object is a
     204             : // wrappednative wrapper, holding the XPCWrappedNative in its private slot.
     205      127179 : static inline bool IS_WN_CLASS(const js::Class* clazz)
     206             : {
     207      127179 :     return clazz->isWrappedNative();
     208             : }
     209             : 
     210       86280 : static inline bool IS_WN_REFLECTOR(JSObject* obj)
     211             : {
     212       86280 :     return IS_WN_CLASS(js::GetObjectClass(obj));
     213             : }
     214             : 
     215             : /***************************************************************************
     216             : ****************************************************************************
     217             : *
     218             : * Core runtime and context classes...
     219             : *
     220             : ****************************************************************************
     221             : ***************************************************************************/
     222             : 
     223             : // We have a general rule internally that getters that return addref'd interface
     224             : // pointer generally do so using an 'out' parm. When interface pointers are
     225             : // returned as function call result values they are not addref'd. Exceptions
     226             : // to this rule are noted explicitly.
     227             : 
     228             : class nsXPConnect final : public nsIXPConnect
     229             : {
     230             : public:
     231             :     // all the interface method declarations...
     232             :     NS_DECL_ISUPPORTS
     233             :     NS_DECL_NSIXPCONNECT
     234             : 
     235             :     // non-interface implementation
     236             : public:
     237             :     // These get non-addref'd pointers
     238       55055 :     static nsXPConnect* XPConnect()
     239             :     {
     240             :         // Do a release-mode assert that we're not doing anything significant in
     241             :         // XPConnect off the main thread. If you're an extension developer hitting
     242             :         // this, you need to change your code. See bug 716167.
     243       55055 :         if (!MOZ_LIKELY(NS_IsMainThread()))
     244           0 :             MOZ_CRASH();
     245             : 
     246       55055 :         return gSelf;
     247             :     }
     248             : 
     249             :     static XPCJSRuntime* GetRuntimeInstance();
     250             : 
     251             :     static bool IsISupportsDescendant(nsIInterfaceInfo* info);
     252             : 
     253        8712 :     static nsIScriptSecurityManager* SecurityManager()
     254             :     {
     255        8712 :         MOZ_ASSERT(NS_IsMainThread());
     256        8712 :         MOZ_ASSERT(gScriptSecurityManager);
     257        8712 :         return gScriptSecurityManager;
     258             :     }
     259             : 
     260       32260 :     static nsIPrincipal* SystemPrincipal()
     261             :     {
     262       32260 :         MOZ_ASSERT(NS_IsMainThread());
     263       32260 :         MOZ_ASSERT(gSystemPrincipal);
     264       32260 :         return gSystemPrincipal;
     265             :     }
     266             : 
     267             :     // This returns an AddRef'd pointer. It does not do this with an 'out' param
     268             :     // only because this form is required by the generic module macro:
     269             :     // NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
     270             :     static nsXPConnect* GetSingleton();
     271             : 
     272             :     // Called by module code in dll startup
     273             :     static void InitStatics();
     274             :     // Called by module code on dll shutdown.
     275             :     static void ReleaseXPConnectSingleton();
     276             : 
     277           1 :     bool IsShuttingDown() const {return mShuttingDown;}
     278             : 
     279             :     nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
     280             :     nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
     281             : 
     282             :     virtual nsIPrincipal* GetPrincipal(JSObject* obj,
     283             :                                        bool allowShortCircuit) const override;
     284             : 
     285             :     void RecordTraversal(void* p, nsISupports* s);
     286             :     virtual char* DebugPrintJSStack(bool showArgs,
     287             :                                     bool showLocals,
     288             :                                     bool showThisProps) override;
     289             : 
     290             : protected:
     291             :     virtual ~nsXPConnect();
     292             : 
     293             :     nsXPConnect();
     294             : 
     295             : private:
     296             :     // Singleton instance
     297             :     static nsXPConnect*             gSelf;
     298             :     static bool                     gOnceAliveNowDead;
     299             : 
     300             :     XPCJSRuntime*                   mRuntime;
     301             :     bool                            mShuttingDown;
     302             : 
     303             : public:
     304             :     static nsIScriptSecurityManager* gScriptSecurityManager;
     305             :     static nsIPrincipal* gSystemPrincipal;
     306             : };
     307             : 
     308             : /***************************************************************************/
     309             : 
     310             : class XPCRootSetElem
     311             : {
     312             : public:
     313         941 :     XPCRootSetElem()
     314         941 :     {
     315             : #ifdef DEBUG
     316         941 :         mNext = nullptr;
     317         941 :         mSelfp = nullptr;
     318             : #endif
     319         941 :     }
     320             : 
     321         142 :     ~XPCRootSetElem()
     322         142 :     {
     323         142 :         MOZ_ASSERT(!mNext, "Must be unlinked");
     324         142 :         MOZ_ASSERT(!mSelfp, "Must be unlinked");
     325         142 :     }
     326             : 
     327         481 :     inline XPCRootSetElem* GetNextRoot() { return mNext; }
     328             :     void AddToRootSet(XPCRootSetElem** listHead);
     329             :     void RemoveFromRootSet();
     330             : 
     331             : private:
     332             :     XPCRootSetElem* mNext;
     333             :     XPCRootSetElem** mSelfp;
     334             : };
     335             : 
     336             : /***************************************************************************/
     337             : 
     338             : // In the current xpconnect system there can only be one XPCJSContext.
     339             : // So, xpconnect can only be used on one JSContext within the process.
     340             : 
     341             : class WatchdogManager;
     342             : 
     343             : enum WatchdogTimestampCategory
     344             : {
     345             :     TimestampContextStateChange = 0,
     346             :     TimestampWatchdogWakeup,
     347             :     TimestampWatchdogHibernateStart,
     348             :     TimestampWatchdogHibernateStop,
     349             :     TimestampCount
     350             : };
     351             : 
     352             : class AsyncFreeSnowWhite;
     353             : 
     354             : template <class StringType>
     355           6 : class ShortLivedStringBuffer
     356             : {
     357             : public:
     358        2481 :     StringType* Create()
     359             :     {
     360        3403 :         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
     361        3207 :             if (!mStrings[i]) {
     362        2285 :                 mStrings[i].emplace();
     363        2285 :                 return mStrings[i].ptr();
     364             :             }
     365             :         }
     366             : 
     367             :         // All our internal string wrappers are used, allocate a new string.
     368         196 :         return new StringType();
     369             :     }
     370             : 
     371        2480 :     void Destroy(StringType* string)
     372             :     {
     373        3402 :         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
     374        3206 :             if (mStrings[i] && mStrings[i].ptr() == string) {
     375             :                 // One of our internal strings is no longer in use, mark
     376             :                 // it as such and free its data.
     377        2284 :                 mStrings[i].reset();
     378        2284 :                 return;
     379             :             }
     380             :         }
     381             : 
     382             :         // We're done with a string that's not one of our internal
     383             :         // strings, delete it.
     384         196 :         delete string;
     385             :     }
     386             : 
     387           0 :     ~ShortLivedStringBuffer()
     388             :     {
     389             : #ifdef DEBUG
     390           0 :         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
     391           0 :             MOZ_ASSERT(!mStrings[i], "Short lived string still in use");
     392             :         }
     393             : #endif
     394           0 :     }
     395             : 
     396             : private:
     397             :     mozilla::Maybe<StringType> mStrings[2];
     398             : };
     399             : 
     400             : class XPCJSContext final : public mozilla::CycleCollectedJSContext
     401             : {
     402             : public:
     403             :     static void InitTLS();
     404             :     static XPCJSContext* NewXPCJSContext(XPCJSContext* aPrimaryContext);
     405             :     static XPCJSContext* Get();
     406             : 
     407             :     XPCJSRuntime* Runtime() const;
     408             : 
     409             :     mozilla::CycleCollectedJSRuntime* CreateRuntime(JSContext* aCx) override;
     410             : 
     411          16 :     XPCCallContext*  GetCallContext() const {return mCallContext;}
     412       98262 :     XPCCallContext*  SetCallContext(XPCCallContext* ccx)
     413       98262 :         {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
     414             : 
     415        2505 :     jsid GetResolveName() const {return mResolveName;}
     416       44412 :     jsid SetResolveName(jsid name)
     417       44412 :         {jsid old = mResolveName; mResolveName = name; return old;}
     418             : 
     419        1408 :     XPCWrappedNative* GetResolvingWrapper() const {return mResolvingWrapper;}
     420        6138 :     XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w)
     421        6138 :         {XPCWrappedNative* old = mResolvingWrapper;
     422        6138 :          mResolvingWrapper = w; return old;}
     423             : 
     424             :     bool JSContextInitialized(JSContext* cx);
     425             : 
     426             :     virtual void BeforeProcessTask(bool aMightBlock) override;
     427             :     virtual void AfterProcessTask(uint32_t aNewRecursionDepth) override;
     428             : 
     429             :     ~XPCJSContext();
     430             : 
     431             :     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
     432             : 
     433       23259 :     AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;}
     434             : 
     435        1357 :     nsresult GetPendingResult() { return mPendingResult; }
     436        1357 :     void SetPendingResult(nsresult rv) { mPendingResult = rv; }
     437             : 
     438             :     PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
     439             : 
     440             :     static void ActivityCallback(void* arg, bool active);
     441             :     static bool InterruptCallback(JSContext* cx);
     442             : 
     443             :     // Mapping of often used strings to jsid atoms that live 'forever'.
     444             :     //
     445             :     // To add a new string: add to this list and to XPCJSRuntime::mStrings
     446             :     // at the top of XPCJSRuntime.cpp
     447             :     enum {
     448             :         IDX_CONSTRUCTOR             = 0 ,
     449             :         IDX_TO_STRING               ,
     450             :         IDX_TO_SOURCE               ,
     451             :         IDX_LAST_RESULT             ,
     452             :         IDX_RETURN_CODE             ,
     453             :         IDX_VALUE                   ,
     454             :         IDX_QUERY_INTERFACE         ,
     455             :         IDX_COMPONENTS              ,
     456             :         IDX_WRAPPED_JSOBJECT        ,
     457             :         IDX_OBJECT                  ,
     458             :         IDX_FUNCTION                ,
     459             :         IDX_PROTOTYPE               ,
     460             :         IDX_CREATE_INSTANCE         ,
     461             :         IDX_ITEM                    ,
     462             :         IDX_PROTO                   ,
     463             :         IDX_ITERATOR                ,
     464             :         IDX_EXPOSEDPROPS            ,
     465             :         IDX_EVAL                    ,
     466             :         IDX_CONTROLLERS             ,
     467             :         IDX_CONTROLLERS_CLASS       ,
     468             :         IDX_REALFRAMEELEMENT        ,
     469             :         IDX_LENGTH                  ,
     470             :         IDX_NAME                    ,
     471             :         IDX_UNDEFINED               ,
     472             :         IDX_EMPTYSTRING             ,
     473             :         IDX_FILENAME                ,
     474             :         IDX_LINENUMBER              ,
     475             :         IDX_COLUMNNUMBER            ,
     476             :         IDX_STACK                   ,
     477             :         IDX_MESSAGE                 ,
     478             :         IDX_LASTINDEX               ,
     479             :         IDX_TOTAL_COUNT // just a count of the above
     480             :     };
     481             : 
     482             :     inline JS::HandleId GetStringID(unsigned index) const;
     483             :     inline const char* GetStringName(unsigned index) const;
     484             : 
     485             :     ShortLivedStringBuffer<nsString> mScratchStrings;
     486             :     ShortLivedStringBuffer<nsCString> mScratchCStrings;
     487             : 
     488             : private:
     489             :     XPCJSContext();
     490             : 
     491             :     MOZ_IS_CLASS_INIT
     492             :     nsresult Initialize(XPCJSContext* aPrimaryContext);
     493             : 
     494             :     XPCCallContext*          mCallContext;
     495             :     AutoMarkingPtr*          mAutoRoots;
     496             :     jsid                     mResolveName;
     497             :     XPCWrappedNative*        mResolvingWrapper;
     498             :     RefPtr<WatchdogManager>  mWatchdogManager;
     499             : 
     500             :     // If we spend too much time running JS code in an event handler, then we
     501             :     // want to show the slow script UI. The timeout T is controlled by prefs. We
     502             :     // invoke the interrupt callback once after T/2 seconds and set
     503             :     // mSlowScriptSecondHalf to true. After another T/2 seconds, we invoke the
     504             :     // interrupt callback again. Since mSlowScriptSecondHalf is now true, it
     505             :     // shows the slow script UI. The reason we invoke the callback twice is to
     506             :     // ensure that putting the computer to sleep while running a script doesn't
     507             :     // cause the UI to be shown. If the laptop goes to sleep during one of the
     508             :     // timeout periods, the script still has the other T/2 seconds to complete
     509             :     // before the slow script UI is shown.
     510             :     bool mSlowScriptSecondHalf;
     511             : 
     512             :     // mSlowScriptCheckpoint is set to the time when:
     513             :     // 1. We started processing the current event, or
     514             :     // 2. mSlowScriptSecondHalf was set to true
     515             :     // (whichever comes later). We use it to determine whether the interrupt
     516             :     // callback needs to do anything.
     517             :     mozilla::TimeStamp mSlowScriptCheckpoint;
     518             :     // Accumulates total time we actually waited for telemetry
     519             :     mozilla::TimeDuration mSlowScriptActualWait;
     520             :     bool mTimeoutAccumulated;
     521             : 
     522             :     // mPendingResult is used to implement Components.returnCode.  Only really
     523             :     // meaningful while calling through XPCWrappedJS.
     524             :     nsresult mPendingResult;
     525             : 
     526             :     friend class XPCJSRuntime;
     527             :     friend class Watchdog;
     528             :     friend class AutoLockWatchdog;
     529             : };
     530             : 
     531             : class XPCJSRuntime final : public mozilla::CycleCollectedJSRuntime
     532             : {
     533             : public:
     534             :     static XPCJSRuntime* Get();
     535             : 
     536             :     void RemoveWrappedJS(nsXPCWrappedJS* wrapper);
     537             :     void AssertInvalidWrappedJSNotInTable(nsXPCWrappedJS* wrapper) const;
     538             : 
     539        1851 :     JSObject2WrappedJSMap* GetMultiCompartmentWrappedJSMap() const
     540        1851 :         {return mWrappedJSMap;}
     541             : 
     542        1532 :     IID2WrappedJSClassMap* GetWrappedJSClassMap() const
     543        1532 :         {return mWrappedJSClassMap;}
     544             : 
     545       16953 :     IID2NativeInterfaceMap* GetIID2NativeInterfaceMap() const
     546       16953 :         {return mIID2NativeInterfaceMap;}
     547             : 
     548        1824 :     ClassInfo2NativeSetMap* GetClassInfo2NativeSetMap() const
     549        1824 :         {return mClassInfo2NativeSetMap;}
     550             : 
     551        3013 :     NativeSetMap* GetNativeSetMap() const
     552        3013 :         {return mNativeSetMap;}
     553             : 
     554          47 :     IID2ThisTranslatorMap* GetThisTranslatorMap() const
     555          47 :         {return mThisTranslatorMap;}
     556             : 
     557           0 :     XPCWrappedNativeProtoMap* GetDyingWrappedNativeProtoMap() const
     558           0 :         {return mDyingWrappedNativeProtoMap;}
     559             : 
     560             :     bool InitializeStrings(JSContext* cx);
     561             : 
     562             :     virtual bool
     563             :     DescribeCustomObjects(JSObject* aObject, const js::Class* aClasp,
     564             :                           char (&aName)[72]) const override;
     565             :     virtual bool
     566             :     NoteCustomGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj,
     567             :                                    nsCycleCollectionTraversalCallback& aCb) const override;
     568             : 
     569             :     /**
     570             :      * Infrastructure for classes that need to defer part of the finalization
     571             :      * until after the GC has run, for example for objects that we don't want to
     572             :      * destroy during the GC.
     573             :      */
     574             : 
     575             : public:
     576           0 :     bool GetDoingFinalization() const {return mDoingFinalization;}
     577             : 
     578       30076 :     JS::HandleId GetStringID(unsigned index) const
     579             :     {
     580       30076 :         MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
     581             :         // fromMarkedLocation() is safe because the string is interned.
     582       30076 :         return JS::HandleId::fromMarkedLocation(&mStrIDs[index]);
     583             :     }
     584             :     JS::HandleValue GetStringJSVal(unsigned index) const
     585             :     {
     586             :         MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
     587             :         // fromMarkedLocation() is safe because the string is interned.
     588             :         return JS::HandleValue::fromMarkedLocation(&mStrJSVals[index]);
     589             :     }
     590           3 :     const char* GetStringName(unsigned index) const
     591             :     {
     592           3 :         MOZ_ASSERT(index < XPCJSContext::IDX_TOTAL_COUNT, "index out of range");
     593           3 :         return mStrings[index];
     594             :     }
     595             : 
     596             :     virtual bool UsefulToMergeZones() const override;
     597             :     void TraceNativeBlackRoots(JSTracer* trc) override;
     598             :     void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) override;
     599             :     void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& cb) override;
     600             :     void UnmarkSkippableJSHolders();
     601             :     void PrepareForForgetSkippable() override;
     602             :     void BeginCycleCollectionCallback() override;
     603             :     void EndCycleCollectionCallback(mozilla::CycleCollectorResults& aResults) override;
     604             :     void DispatchDeferredDeletion(bool aContinuation, bool aPurge = false) override;
     605             : 
     606             :     void CustomGCCallback(JSGCStatus status) override;
     607             :     void CustomOutOfMemoryCallback() override;
     608             :     void OnLargeAllocationFailure();
     609             :     static void GCSliceCallback(JSContext* cx,
     610             :                                 JS::GCProgress progress,
     611             :                                 const JS::GCDescription& desc);
     612             :     static void DoCycleCollectionCallback(JSContext* cx);
     613             :     static void FinalizeCallback(JSFreeOp* fop,
     614             :                                  JSFinalizeStatus status,
     615             :                                  bool isZoneGC,
     616             :                                  void* data);
     617             :     static void WeakPointerZonesCallback(JSContext* cx, void* data);
     618             :     static void WeakPointerCompartmentCallback(JSContext* cx, JSCompartment* comp, void* data);
     619             : 
     620             :     inline void AddVariantRoot(XPCTraceableVariant* variant);
     621             :     inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
     622             : 
     623             :     void DebugDump(int16_t depth);
     624             : 
     625        8007 :     bool GCIsRunning() const {return mGCIsRunning;}
     626             : 
     627             :     ~XPCJSRuntime();
     628             : 
     629             :     void AddGCCallback(xpcGCCallback cb);
     630             :     void RemoveGCCallback(xpcGCCallback cb);
     631             : 
     632             :     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
     633             : 
     634         284 :     JSObject* UnprivilegedJunkScope() { return mUnprivilegedJunkScope; }
     635          66 :     JSObject* PrivilegedJunkScope() { return mPrivilegedJunkScope; }
     636        3774 :     JSObject* CompilationScope() { return mCompilationScope; }
     637             : 
     638             :     void InitSingletonScopes();
     639             :     void DeleteSingletonScopes();
     640             : 
     641             : private:
     642             :     explicit XPCJSRuntime(JSContext* aCx);
     643             : 
     644             :     MOZ_IS_CLASS_INIT
     645             :     void Initialize(JSContext* cx);
     646             :     void Shutdown(JSContext* cx) override;
     647             : 
     648             :     void ReleaseIncrementally(nsTArray<nsISupports*>& array);
     649             : 
     650             :     static const char* const mStrings[XPCJSContext::IDX_TOTAL_COUNT];
     651             :     jsid mStrIDs[XPCJSContext::IDX_TOTAL_COUNT];
     652             :     JS::Value mStrJSVals[XPCJSContext::IDX_TOTAL_COUNT];
     653             : 
     654             :     JSObject2WrappedJSMap*   mWrappedJSMap;
     655             :     IID2WrappedJSClassMap*   mWrappedJSClassMap;
     656             :     IID2NativeInterfaceMap*  mIID2NativeInterfaceMap;
     657             :     ClassInfo2NativeSetMap*  mClassInfo2NativeSetMap;
     658             :     NativeSetMap*            mNativeSetMap;
     659             :     IID2ThisTranslatorMap*   mThisTranslatorMap;
     660             :     XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
     661             :     bool mGCIsRunning;
     662             :     nsTArray<nsISupports*> mNativesToReleaseArray;
     663             :     bool mDoingFinalization;
     664             :     XPCRootSetElem* mVariantRoots;
     665             :     XPCRootSetElem* mWrappedJSRoots;
     666             :     nsTArray<xpcGCCallback> extraGCCallbacks;
     667             :     JS::GCSliceCallback mPrevGCSliceCallback;
     668             :     JS::DoCycleCollectionCallback mPrevDoCycleCollectionCallback;
     669             :     JS::PersistentRootedObject mUnprivilegedJunkScope;
     670             :     JS::PersistentRootedObject mPrivilegedJunkScope;
     671             :     JS::PersistentRootedObject mCompilationScope;
     672             :     RefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
     673             : 
     674             :     friend class XPCJSContext;
     675             :     friend class XPCIncrementalReleaseRunnable;
     676             : };
     677             : 
     678             : inline JS::HandleId
     679       24252 : XPCJSContext::GetStringID(unsigned index) const
     680             : {
     681       24252 :     return Runtime()->GetStringID(index);
     682             : }
     683             : 
     684             : inline const char*
     685           3 : XPCJSContext::GetStringName(unsigned index) const
     686             : {
     687           3 :     return Runtime()->GetStringName(index);
     688             : }
     689             : 
     690             : /***************************************************************************/
     691             : 
     692             : // No virtuals
     693             : // XPCCallContext is ALWAYS declared as a local variable in some function;
     694             : // i.e. instance lifetime is always controled by some C++ function returning.
     695             : //
     696             : // These things are created frequently in many places. We *intentionally* do
     697             : // not inialialize all members in order to save on construction overhead.
     698             : // Some constructor pass more valid params than others. We init what must be
     699             : // init'd and leave other members undefined. In debug builds the accessors
     700             : // use a CHECK_STATE macro to track whether or not the object is in a valid
     701             : // state to answer the question a caller might be asking. As long as this
     702             : // class is maintained correctly it can do its job without a bunch of added
     703             : // overhead from useless initializations and non-DEBUG error checking.
     704             : //
     705             : // Note that most accessors are inlined.
     706             : 
     707             : class MOZ_STACK_CLASS XPCCallContext final : public nsAXPCNativeCallContext
     708             : {
     709             : public:
     710             :     NS_IMETHOD GetCallee(nsISupports** aResult);
     711             :     NS_IMETHOD GetCalleeMethodIndex(uint16_t* aResult);
     712             :     NS_IMETHOD GetJSContext(JSContext** aResult);
     713             :     NS_IMETHOD GetArgc(uint32_t* aResult);
     714             :     NS_IMETHOD GetArgvPtr(JS::Value** aResult);
     715             :     NS_IMETHOD GetCalleeInterface(nsIInterfaceInfo** aResult);
     716             :     NS_IMETHOD GetCalleeClassInfo(nsIClassInfo** aResult);
     717             :     NS_IMETHOD GetPreviousCallContext(nsAXPCNativeCallContext** aResult);
     718             : 
     719             :     enum {NO_ARGS = (unsigned) -1};
     720             : 
     721             :     explicit XPCCallContext(JSContext* cx,
     722             :                             JS::HandleObject obj    = nullptr,
     723             :                             JS::HandleObject funobj = nullptr,
     724             :                             JS::HandleId id         = JSID_VOIDHANDLE,
     725             :                             unsigned argc           = NO_ARGS,
     726             :                             JS::Value* argv         = nullptr,
     727             :                             JS::Value* rval         = nullptr);
     728             : 
     729             :     virtual ~XPCCallContext();
     730             : 
     731             :     inline bool                         IsValid() const ;
     732             : 
     733             :     inline XPCJSContext*                GetContext() const ;
     734             :     inline JSContext*                   GetJSContext() const ;
     735             :     inline bool                         GetContextPopRequired() const ;
     736             :     inline XPCCallContext*              GetPrevCallContext() const ;
     737             : 
     738             :     inline JSObject*                    GetFlattenedJSObject() const ;
     739             :     inline nsISupports*                 GetIdentityObject() const ;
     740             :     inline XPCWrappedNative*            GetWrapper() const ;
     741             :     inline XPCWrappedNativeProto*       GetProto() const ;
     742             : 
     743             :     inline bool                         CanGetTearOff() const ;
     744             :     inline XPCWrappedNativeTearOff*     GetTearOff() const ;
     745             : 
     746             :     inline nsIXPCScriptable*            GetScriptable() const ;
     747             :     inline bool                         CanGetSet() const ;
     748             :     inline XPCNativeSet*                GetSet() const ;
     749             :     inline bool                         CanGetInterface() const ;
     750             :     inline XPCNativeInterface*          GetInterface() const ;
     751             :     inline XPCNativeMember*             GetMember() const ;
     752             :     inline bool                         HasInterfaceAndMember() const ;
     753             :     inline jsid                         GetName() const ;
     754             :     inline bool                         GetStaticMemberIsLocal() const ;
     755             :     inline unsigned                     GetArgc() const ;
     756             :     inline JS::Value*                   GetArgv() const ;
     757             :     inline JS::Value*                   GetRetVal() const ;
     758             : 
     759             :     inline uint16_t                     GetMethodIndex() const ;
     760             :     inline void                         SetMethodIndex(uint16_t index) ;
     761             : 
     762             :     inline jsid GetResolveName() const;
     763             :     inline jsid SetResolveName(JS::HandleId name);
     764             : 
     765             :     inline XPCWrappedNative* GetResolvingWrapper() const;
     766             :     inline XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w);
     767             : 
     768             :     inline void SetRetVal(const JS::Value& val);
     769             : 
     770             :     void SetName(jsid name);
     771             :     void SetArgsAndResultPtr(unsigned argc, JS::Value* argv, JS::Value* rval);
     772             :     void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
     773             :                      bool isSetter);
     774             : 
     775             :     nsresult  CanCallNow();
     776             : 
     777             :     void SystemIsBeingShutDown();
     778             : 
     779       82585 :     operator JSContext*() const {return GetJSContext();}
     780             : 
     781             : private:
     782             : 
     783             :     // no copy ctor or assignment allowed
     784             :     XPCCallContext(const XPCCallContext& r) = delete;
     785             :     XPCCallContext& operator= (const XPCCallContext& r) = delete;
     786             : 
     787             : private:
     788             :     // posible values for mState
     789             :     enum State {
     790             :         INIT_FAILED,
     791             :         SYSTEM_SHUTDOWN,
     792             :         HAVE_CONTEXT,
     793             :         HAVE_OBJECT,
     794             :         HAVE_NAME,
     795             :         HAVE_ARGS,
     796             :         READY_TO_CALL,
     797             :         CALL_DONE
     798             :     };
     799             : 
     800             : #ifdef DEBUG
     801      420186 : inline void CHECK_STATE(int s) const {MOZ_ASSERT(mState >= s, "bad state");}
     802             : #else
     803             : #define CHECK_STATE(s) ((void)0)
     804             : #endif
     805             : 
     806             : private:
     807             :     JSAutoRequest                   mAr;
     808             :     State                           mState;
     809             : 
     810             :     RefPtr<nsXPConnect>           mXPC;
     811             : 
     812             :     XPCJSContext*                   mXPCJSContext;
     813             :     JSContext*                      mJSContext;
     814             : 
     815             :     // ctor does not necessarily init the following. BEWARE!
     816             : 
     817             :     XPCCallContext*                 mPrevCallContext;
     818             : 
     819             :     XPCWrappedNative*               mWrapper;
     820             :     XPCWrappedNativeTearOff*        mTearOff;
     821             : 
     822             :     nsCOMPtr<nsIXPCScriptable>      mScriptable;
     823             : 
     824             :     RefPtr<XPCNativeSet>            mSet;
     825             :     RefPtr<XPCNativeInterface>      mInterface;
     826             :     XPCNativeMember*                mMember;
     827             : 
     828             :     JS::RootedId                    mName;
     829             :     bool                            mStaticMemberIsLocal;
     830             : 
     831             :     unsigned                        mArgc;
     832             :     JS::Value*                      mArgv;
     833             :     JS::Value*                      mRetVal;
     834             : 
     835             :     uint16_t                        mMethodIndex;
     836             : };
     837             : 
     838             : /***************************************************************************
     839             : ****************************************************************************
     840             : *
     841             : * Core classes for wrapped native objects for use from JavaScript...
     842             : *
     843             : ****************************************************************************
     844             : ***************************************************************************/
     845             : 
     846             : // These are the various JSClasses and callbacks whose use that required
     847             : // visibility from more than one .cpp file.
     848             : 
     849             : extern const js::Class XPC_WN_NoHelper_JSClass;
     850             : extern const js::Class XPC_WN_NoMods_Proto_JSClass;
     851             : extern const js::Class XPC_WN_ModsAllowed_Proto_JSClass;
     852             : extern const js::Class XPC_WN_Tearoff_JSClass;
     853             : #define XPC_WN_TEAROFF_RESERVED_SLOTS 1
     854             : #define XPC_WN_TEAROFF_FLAT_OBJECT_SLOT 0
     855             : extern const js::Class XPC_WN_NoHelper_Proto_JSClass;
     856             : 
     857             : extern bool
     858             : XPC_WN_CallMethod(JSContext* cx, unsigned argc, JS::Value* vp);
     859             : 
     860             : extern bool
     861             : XPC_WN_GetterSetter(JSContext* cx, unsigned argc, JS::Value* vp);
     862             : 
     863             : // Maybe this macro should check for class->enumerate ==
     864             : // XPC_WN_Shared_Proto_Enumerate or something rather than checking for
     865             : // 4 classes?
     866           0 : static inline bool IS_PROTO_CLASS(const js::Class* clazz)
     867             : {
     868           0 :     return clazz == &XPC_WN_NoMods_Proto_JSClass ||
     869           0 :            clazz == &XPC_WN_ModsAllowed_Proto_JSClass;
     870             : }
     871             : 
     872             : typedef js::HashSet<size_t,
     873             :                     js::DefaultHasher<size_t>,
     874             :                     js::SystemAllocPolicy> InterpositionWhitelist;
     875             : 
     876           0 : struct InterpositionWhitelistPair {
     877             :     nsIAddonInterposition* interposition;
     878             :     InterpositionWhitelist whitelist;
     879             : };
     880             : 
     881             : typedef nsTArray<InterpositionWhitelistPair> InterpositionWhitelistArray;
     882             : 
     883             : /***************************************************************************/
     884             : // XPCWrappedNativeScope is one-to-one with a JS global object.
     885             : 
     886             : class nsIAddonInterposition;
     887             : class nsXPCComponentsBase;
     888             : class XPCWrappedNativeScope final
     889             : {
     890             : public:
     891             : 
     892             :     XPCJSRuntime*
     893        8007 :     GetRuntime() const {return XPCJSRuntime::Get();}
     894             : 
     895             :     Native2WrappedNativeMap*
     896       13718 :     GetWrappedNativeMap() const {return mWrappedNativeMap;}
     897             : 
     898             :     ClassInfo2WrappedNativeProtoMap*
     899        4378 :     GetWrappedNativeProtoMap() const {return mWrappedNativeProtoMap;}
     900             : 
     901             :     nsXPCComponentsBase*
     902          10 :     GetComponents() const {return mComponents;}
     903             : 
     904             :     // Forces the creation of a privileged |Components| object, even in
     905             :     // content scopes. This will crash if used outside of automation.
     906             :     void
     907             :     ForcePrivilegedComponents();
     908             : 
     909             :     bool AttachComponentsObject(JSContext* aCx);
     910             : 
     911             :     // Returns the JS object reflection of the Components object.
     912             :     bool
     913             :     GetComponentsJSObject(JS::MutableHandleObject obj);
     914             : 
     915             :     JSObject*
     916       10769 :     GetGlobalJSObject() const {
     917       10769 :         return mGlobalJSObject;
     918             :     }
     919             : 
     920             :     JSObject*
     921       24462 :     GetGlobalJSObjectPreserveColor() const {return mGlobalJSObject.unbarrieredGet();}
     922             : 
     923             :     nsIPrincipal*
     924         801 :     GetPrincipal() const {
     925         801 :         JSCompartment* c = js::GetObjectCompartment(mGlobalJSObject);
     926         801 :         return nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
     927             :     }
     928             : 
     929             :     JSObject*
     930             :     GetExpandoChain(JS::HandleObject target);
     931             : 
     932             :     bool
     933             :     SetExpandoChain(JSContext* cx, JS::HandleObject target, JS::HandleObject chain);
     934             : 
     935             :     static void
     936             :     SystemIsBeingShutDown();
     937             : 
     938             :     static void
     939             :     TraceWrappedNativesInAllScopes(JSTracer* trc);
     940             : 
     941          34 :     void TraceSelf(JSTracer* trc) {
     942          34 :         MOZ_ASSERT(mGlobalJSObject);
     943          34 :         mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject");
     944          34 :     }
     945             : 
     946          26 :     void TraceInside(JSTracer* trc) {
     947          26 :         if (mContentXBLScope)
     948           0 :             mContentXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope");
     949          26 :         for (size_t i = 0; i < mAddonScopes.Length(); i++)
     950           0 :             mAddonScopes[i].trace(trc, "XPCWrappedNativeScope::mAddonScopes");
     951          26 :         if (mXrayExpandos.initialized())
     952           0 :             mXrayExpandos.trace(trc);
     953          26 :     }
     954             : 
     955             :     static void
     956             :     SuspectAllWrappers(nsCycleCollectionNoteRootCallback& cb);
     957             : 
     958             :     static void
     959             :     SweepAllWrappedNativeTearOffs();
     960             : 
     961             :     static void
     962             :     UpdateWeakPointersInAllScopesAfterGC();
     963             : 
     964             :     void
     965             :     UpdateWeakPointersAfterGC();
     966             : 
     967             :     static void
     968             :     KillDyingScopes();
     969             : 
     970             :     static void
     971             :     DebugDumpAllScopes(int16_t depth);
     972             : 
     973             :     void
     974             :     DebugDump(int16_t depth);
     975             : 
     976             :     struct ScopeSizeInfo {
     977           0 :         explicit ScopeSizeInfo(mozilla::MallocSizeOf mallocSizeOf)
     978           0 :             : mMallocSizeOf(mallocSizeOf),
     979             :               mScopeAndMapSize(0),
     980           0 :               mProtoAndIfaceCacheSize(0)
     981           0 :         {}
     982             : 
     983             :         mozilla::MallocSizeOf mMallocSizeOf;
     984             :         size_t mScopeAndMapSize;
     985             :         size_t mProtoAndIfaceCacheSize;
     986             :     };
     987             : 
     988             :     static void
     989             :     AddSizeOfAllScopesIncludingThis(ScopeSizeInfo* scopeSizeInfo);
     990             : 
     991             :     void
     992             :     AddSizeOfIncludingThis(ScopeSizeInfo* scopeSizeInfo);
     993             : 
     994             :     static bool
     995             :     IsDyingScope(XPCWrappedNativeScope* scope);
     996             : 
     997             :     typedef js::HashMap<JSAddonId*,
     998             :                         nsCOMPtr<nsIAddonInterposition>,
     999             :                         js::PointerHasher<JSAddonId*, 3>,
    1000             :                         js::SystemAllocPolicy> InterpositionMap;
    1001             : 
    1002             :     typedef js::HashSet<JSAddonId*,
    1003             :                         js::PointerHasher<JSAddonId*, 3>,
    1004             :                         js::SystemAllocPolicy> AddonSet;
    1005             : 
    1006             :     // Gets the appropriate scope object for XBL in this scope. The context
    1007             :     // must be same-compartment with the global upon entering, and the scope
    1008             :     // object is wrapped into the compartment of the global.
    1009             :     JSObject* EnsureContentXBLScope(JSContext* cx);
    1010             : 
    1011             :     JSObject* EnsureAddonScope(JSContext* cx, JSAddonId* addonId);
    1012             : 
    1013             :     XPCWrappedNativeScope(JSContext* cx, JS::HandleObject aGlobal);
    1014             : 
    1015             :     nsAutoPtr<JSObject2JSObjectMap> mWaiverWrapperMap;
    1016             : 
    1017        3627 :     bool IsContentXBLScope() { return mIsContentXBLScope; }
    1018             :     bool AllowContentXBLScope();
    1019         868 :     bool UseContentXBLScope() { return mUseContentXBLScope; }
    1020           1 :     void ClearContentXBLScope() { mContentXBLScope = nullptr; }
    1021             : 
    1022        3716 :     bool IsAddonScope() { return mIsAddonScope; }
    1023             : 
    1024       12063 :     bool HasInterposition() { return mInterposition; }
    1025             :     nsCOMPtr<nsIAddonInterposition> GetInterposition();
    1026             : 
    1027             :     static bool SetAddonInterposition(JSContext* cx,
    1028             :                                       JSAddonId* addonId,
    1029             :                                       nsIAddonInterposition* interp);
    1030             : 
    1031             :     static InterpositionWhitelist* GetInterpositionWhitelist(nsIAddonInterposition* interposition);
    1032             :     static bool UpdateInterpositionWhitelist(JSContext* cx,
    1033             :                                              nsIAddonInterposition* interposition);
    1034             : 
    1035           0 :     void SetAddonCallInterposition() { mHasCallInterpositions = true; }
    1036           0 :     bool HasCallInterposition() { return mHasCallInterpositions; };
    1037             : 
    1038             :     static bool AllowCPOWsInAddon(JSContext* cx, JSAddonId* addonId, bool allow);
    1039             : 
    1040             : protected:
    1041             :     virtual ~XPCWrappedNativeScope();
    1042             : 
    1043             :     XPCWrappedNativeScope() = delete;
    1044             : 
    1045             : private:
    1046           0 :     class ClearInterpositionsObserver final : public nsIObserver {
    1047           0 :         ~ClearInterpositionsObserver() {}
    1048             : 
    1049             :       public:
    1050             :         NS_DECL_ISUPPORTS
    1051             :         NS_DECL_NSIOBSERVER
    1052             :     };
    1053             : 
    1054             :     static XPCWrappedNativeScope* gScopes;
    1055             :     static XPCWrappedNativeScope* gDyingScopes;
    1056             : 
    1057             :     static bool                      gShutdownObserverInitialized;
    1058             :     static InterpositionMap*         gInterpositionMap;
    1059             :     static AddonSet*                 gAllowCPOWAddonSet;
    1060             : 
    1061             :     static InterpositionWhitelistArray* gInterpositionWhitelists;
    1062             : 
    1063             :     Native2WrappedNativeMap*         mWrappedNativeMap;
    1064             :     ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap;
    1065             :     RefPtr<nsXPCComponentsBase>    mComponents;
    1066             :     XPCWrappedNativeScope*           mNext;
    1067             :     // The JS global object for this scope.  If non-null, this will be the
    1068             :     // default parent for the XPCWrappedNatives that have us as the scope,
    1069             :     // unless a PreCreate hook overrides it.  Note that this _may_ be null (see
    1070             :     // constructor).
    1071             :     JS::ObjectPtr                    mGlobalJSObject;
    1072             : 
    1073             :     // XBL Scope. This is is a lazily-created sandbox for non-system scopes.
    1074             :     // EnsureContentXBLScope() decides whether it needs to be created or not.
    1075             :     // This reference is wrapped into the compartment of mGlobalJSObject.
    1076             :     JS::ObjectPtr                    mContentXBLScope;
    1077             : 
    1078             :     // Lazily created sandboxes for addon code.
    1079             :     nsTArray<JS::ObjectPtr>          mAddonScopes;
    1080             : 
    1081             :     // This is a service that will be use to interpose on some property accesses on
    1082             :     // objects from other scope, for add-on compatibility reasons.
    1083             :     nsCOMPtr<nsIAddonInterposition>  mInterposition;
    1084             : 
    1085             :     // If this flag is set, we intercept function calls on vanilla JS function objects
    1086             :     // from this scope if the caller scope has mInterposition set.
    1087             :     bool mHasCallInterpositions;
    1088             : 
    1089             :     JS::WeakMapPtr<JSObject*, JSObject*> mXrayExpandos;
    1090             : 
    1091             :     bool mIsContentXBLScope;
    1092             :     bool mIsAddonScope;
    1093             : 
    1094             :     // For remote XUL domains, we run all XBL in the content scope for compat
    1095             :     // reasons (though we sometimes pref this off for automation). We separately
    1096             :     // track the result of this decision (mAllowContentXBLScope), from the decision
    1097             :     // of whether to actually _use_ an XBL scope (mUseContentXBLScope), which depends
    1098             :     // on the type of global and whether the compartment is system principal
    1099             :     // or not.
    1100             :     //
    1101             :     // This distinction is useful primarily because, if true, we know that we
    1102             :     // have no way of distinguishing XBL script from content script for the
    1103             :     // given scope. In these (unsupported) situations, we just always claim to
    1104             :     // be XBL.
    1105             :     bool mAllowContentXBLScope;
    1106             :     bool mUseContentXBLScope;
    1107             : };
    1108             : 
    1109             : /***************************************************************************/
    1110             : // Slots we use for our functions
    1111             : #define XPC_FUNCTION_NATIVE_MEMBER_SLOT 0
    1112             : #define XPC_FUNCTION_PARENT_OBJECT_SLOT 1
    1113             : 
    1114             : /***************************************************************************/
    1115             : // XPCNativeMember represents a single idl declared method, attribute or
    1116             : // constant.
    1117             : 
    1118             : // Tight. No virtual methods. Can be bitwise copied (until any resolution done).
    1119             : 
    1120             : class XPCNativeMember final
    1121             : {
    1122             : public:
    1123             :     static bool GetCallInfo(JSObject* funobj,
    1124             :                             RefPtr<XPCNativeInterface>* pInterface,
    1125             :                             XPCNativeMember** pMember);
    1126             : 
    1127      137145 :     jsid   GetName() const {return mName;}
    1128             : 
    1129       16233 :     uint16_t GetIndex() const {return mIndex;}
    1130             : 
    1131         199 :     bool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
    1132             :                           JS::Value* pval)
    1133         199 :         {MOZ_ASSERT(IsConstant(),
    1134             :                     "Only call this if you're sure this is a constant!");
    1135         199 :          return Resolve(ccx, iface, nullptr, pval);}
    1136             : 
    1137             :     bool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface,
    1138             :                            JS::HandleObject parent, JS::Value* pval);
    1139             : 
    1140        6354 :     bool IsMethod() const
    1141        6354 :         {return 0 != (mFlags & METHOD);}
    1142             : 
    1143       13536 :     bool IsConstant() const
    1144       13536 :         {return 0 != (mFlags & CONSTANT);}
    1145             : 
    1146        1926 :     bool IsAttribute() const
    1147        1926 :         {return 0 != (mFlags & GETTER);}
    1148             : 
    1149        1964 :     bool IsWritableAttribute() const
    1150        1964 :         {return 0 != (mFlags & SETTER_TOO);}
    1151             : 
    1152         550 :     bool IsReadOnlyAttribute() const
    1153         550 :         {return IsAttribute() && !IsWritableAttribute();}
    1154             : 
    1155             : 
    1156       13315 :     void SetName(jsid a) {mName = a;}
    1157             : 
    1158        7597 :     void SetMethod(uint16_t index)
    1159        7597 :         {mFlags = METHOD; mIndex = index;}
    1160             : 
    1161        3815 :     void SetConstant(uint16_t index)
    1162        3815 :         {mFlags = CONSTANT; mIndex = index;}
    1163             : 
    1164        1903 :     void SetReadOnlyAttribute(uint16_t index)
    1165        1903 :         {mFlags = GETTER; mIndex = index;}
    1166             : 
    1167         550 :     void SetWritableAttribute()
    1168         550 :         {MOZ_ASSERT(mFlags == GETTER,"bad"); mFlags = GETTER | SETTER_TOO;}
    1169             : 
    1170       13315 :     static uint16_t GetMaxIndexInInterface()
    1171       13315 :         {return (1<<12) - 1;}
    1172             : 
    1173             :     inline XPCNativeInterface* GetInterface() const;
    1174             : 
    1175       13315 :     void SetIndexInInterface(uint16_t index)
    1176       13315 :         {mIndexInInterface = index;}
    1177             : 
    1178             :     /* default ctor - leave random contents */
    1179       40187 :     XPCNativeMember()  {MOZ_COUNT_CTOR(XPCNativeMember);}
    1180       39919 :     ~XPCNativeMember() {MOZ_COUNT_DTOR(XPCNativeMember);}
    1181             : 
    1182             : private:
    1183             :     bool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
    1184             :                  JS::HandleObject parent, JS::Value* vp);
    1185             : 
    1186             :     enum {
    1187             :         METHOD      = 0x01,
    1188             :         CONSTANT    = 0x02,
    1189             :         GETTER      = 0x04,
    1190             :         SETTER_TOO  = 0x08
    1191             :         // If you add a flag here, you may need to make mFlags wider and either
    1192             :         // make mIndexInInterface narrower (and adjust
    1193             :         // XPCNativeInterface::NewInstance accordingly) or make this object
    1194             :         // bigger.
    1195             :     };
    1196             : 
    1197             : private:
    1198             :     // our only data...
    1199             :     jsid     mName;
    1200             :     uint16_t mIndex;
    1201             :     // mFlags needs to be wide enogh to hold the flags in the above enum.
    1202             :     uint16_t mFlags : 4;
    1203             :     // mIndexInInterface is the index of this in our XPCNativeInterface's
    1204             :     // mMembers.  In theory our XPCNativeInterface could have as many as 2^15-1
    1205             :     // members (since mMemberCount is 15-bit) but in practice we prevent
    1206             :     // creation of XPCNativeInterfaces which have more than 2^12 members.
    1207             :     // If the width of this field changes, update GetMaxIndexInInterface.
    1208             :     uint16_t mIndexInInterface : 12;
    1209             : } JS_HAZ_NON_GC_POINTER; // Only stores a pinned string
    1210             : 
    1211             : /***************************************************************************/
    1212             : // XPCNativeInterface represents a single idl declared interface. This is
    1213             : // primarily the set of XPCNativeMembers.
    1214             : 
    1215             : // Tight. No virtual methods.
    1216             : 
    1217             : class XPCNativeInterface final
    1218             : {
    1219             :   public:
    1220       99850 :     NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeInterface,
    1221             :                                             DestroyInstance(this))
    1222             : 
    1223             :     static already_AddRefed<XPCNativeInterface> GetNewOrUsed(const nsIID* iid);
    1224             :     static already_AddRefed<XPCNativeInterface> GetNewOrUsed(nsIInterfaceInfo* info);
    1225             :     static already_AddRefed<XPCNativeInterface> GetNewOrUsed(const char* name);
    1226             :     static already_AddRefed<XPCNativeInterface> GetISupports();
    1227             : 
    1228       13576 :     inline nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo.get();}
    1229       21517 :     inline jsid              GetName()          const {return mName;}
    1230             : 
    1231             :     inline const nsIID* GetIID() const;
    1232             :     inline const char*  GetNameString() const;
    1233             :     inline XPCNativeMember* FindMember(jsid name) const;
    1234             : 
    1235             :     inline bool HasAncestor(const nsIID* iid) const;
    1236             :     static inline size_t OffsetOfMembers();
    1237             : 
    1238         992 :     uint16_t GetMemberCount() const {
    1239         992 :         return mMemberCount;
    1240             :     }
    1241         132 :     XPCNativeMember* GetMemberAt(uint16_t i) {
    1242         132 :         MOZ_ASSERT(i < mMemberCount, "bad index");
    1243         132 :         return &mMembers[i];
    1244             :     }
    1245             : 
    1246             :     void DebugDump(int16_t depth);
    1247             : 
    1248             :     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
    1249             : 
    1250             :   protected:
    1251             :     static already_AddRefed<XPCNativeInterface> NewInstance(nsIInterfaceInfo* aInfo);
    1252             : 
    1253             :     XPCNativeInterface() = delete;
    1254        1825 :     XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName)
    1255        1825 :       : mInfo(aInfo), mName(aName), mMemberCount(0)
    1256        1825 :     {}
    1257             :     ~XPCNativeInterface();
    1258             : 
    1259        1825 :     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
    1260             : 
    1261             :     XPCNativeInterface(const XPCNativeInterface& r) = delete;
    1262             :     XPCNativeInterface& operator= (const XPCNativeInterface& r) = delete;
    1263             : 
    1264             :     static void DestroyInstance(XPCNativeInterface* inst);
    1265             : 
    1266             : private:
    1267             :     nsCOMPtr<nsIInterfaceInfo> mInfo;
    1268             :     jsid                       mName;
    1269             :     uint16_t                   mMemberCount;
    1270             :     XPCNativeMember            mMembers[1]; // always last - object sized for array
    1271             : };
    1272             : 
    1273             : /***************************************************************************/
    1274             : // XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap.
    1275             : // It represents a new XPCNativeSet we are considering constructing, without
    1276             : // requiring that the set actually be built.
    1277             : 
    1278             : class MOZ_STACK_CLASS XPCNativeSetKey final
    1279             : {
    1280             : public:
    1281             :     // This represents an existing set |baseSet|.
    1282        1316 :     explicit XPCNativeSetKey(XPCNativeSet* baseSet)
    1283        1316 :         : mBaseSet(baseSet), mAddition(nullptr)
    1284             :     {
    1285        1316 :         MOZ_ASSERT(baseSet);
    1286        1316 :     }
    1287             : 
    1288             :     // This represents a new set containing only nsISupports and
    1289             :     // |addition|.
    1290        1707 :     explicit XPCNativeSetKey(XPCNativeInterface* addition)
    1291        1707 :         : mBaseSet(nullptr), mAddition(addition)
    1292             :     {
    1293        1707 :         MOZ_ASSERT(addition);
    1294        1707 :     }
    1295             : 
    1296             :     // This represents the existing set |baseSet| with the interface
    1297             :     // |addition| inserted after existing interfaces. |addition| must
    1298             :     // not already be present in |baseSet|.
    1299             :     explicit XPCNativeSetKey(XPCNativeSet* baseSet,
    1300             :                              XPCNativeInterface* addition);
    1301        3258 :     ~XPCNativeSetKey() {}
    1302             : 
    1303        2706 :     XPCNativeSet* GetBaseSet() const {return mBaseSet;}
    1304        2649 :     XPCNativeInterface* GetAddition() const {return mAddition;}
    1305             : 
    1306             :     PLDHashNumber Hash() const;
    1307             : 
    1308             :     // Allow shallow copy
    1309             : 
    1310             : private:
    1311             :     RefPtr<XPCNativeSet> mBaseSet;
    1312             :     RefPtr<XPCNativeInterface> mAddition;
    1313             : };
    1314             : 
    1315             : /***************************************************************************/
    1316             : // XPCNativeSet represents an ordered collection of XPCNativeInterface pointers.
    1317             : 
    1318             : class XPCNativeSet final
    1319             : {
    1320             :   public:
    1321       51906 :     NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeSet,
    1322             :                                             DestroyInstance(this))
    1323             : 
    1324             :     static already_AddRefed<XPCNativeSet> GetNewOrUsed(const nsIID* iid);
    1325             :     static already_AddRefed<XPCNativeSet> GetNewOrUsed(nsIClassInfo* classInfo);
    1326             :     static already_AddRefed<XPCNativeSet> GetNewOrUsed(XPCNativeSetKey* key);
    1327             : 
    1328             :     // This generates a union set.
    1329             :     //
    1330             :     // If preserveFirstSetOrder is true, the elements from |firstSet| come first,
    1331             :     // followed by any non-duplicate items from |secondSet|. If false, the same
    1332             :     // algorithm is applied; but if we detect that |secondSet| is a superset of
    1333             :     // |firstSet|, we return |secondSet| without worrying about whether the
    1334             :     // ordering might differ from |firstSet|.
    1335             :     static already_AddRefed<XPCNativeSet> GetNewOrUsed(XPCNativeSet* firstSet,
    1336             :                                                        XPCNativeSet* secondSet,
    1337             :                                                        bool preserveFirstSetOrder);
    1338             : 
    1339             :     static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
    1340             : 
    1341             :     inline bool FindMember(jsid name, XPCNativeMember** pMember,
    1342             :                            uint16_t* pInterfaceIndex) const;
    1343             : 
    1344             :     inline bool FindMember(jsid name, XPCNativeMember** pMember,
    1345             :                            RefPtr<XPCNativeInterface>* pInterface) const;
    1346             : 
    1347             :     inline bool FindMember(JS::HandleId name,
    1348             :                            XPCNativeMember** pMember,
    1349             :                            RefPtr<XPCNativeInterface>* pInterface,
    1350             :                            XPCNativeSet* protoSet,
    1351             :                            bool* pIsLocal) const;
    1352             : 
    1353             :     inline bool HasInterface(XPCNativeInterface* aInterface) const;
    1354             :     inline bool HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const;
    1355             :     inline bool HasInterfaceWithAncestor(const nsIID* iid) const;
    1356             : 
    1357             :     inline XPCNativeInterface* FindInterfaceWithIID(const nsIID& iid) const;
    1358             : 
    1359             :     inline XPCNativeInterface* FindNamedInterface(jsid name) const;
    1360             : 
    1361          57 :     uint16_t GetMemberCount() const {
    1362          57 :         return mMemberCount;
    1363             :     }
    1364        5631 :     uint16_t GetInterfaceCount() const {
    1365        5631 :         return mInterfaceCount;
    1366             :     }
    1367        3357 :     XPCNativeInterface** GetInterfaceArray() {
    1368        3357 :         return mInterfaces;
    1369             :     }
    1370             : 
    1371        1519 :     XPCNativeInterface* GetInterfaceAt(uint16_t i)
    1372        1519 :         {MOZ_ASSERT(i < mInterfaceCount, "bad index"); return mInterfaces[i];}
    1373             : 
    1374             :     inline bool MatchesSetUpToInterface(const XPCNativeSet* other,
    1375             :                                           XPCNativeInterface* iface) const;
    1376             : 
    1377             :     void DebugDump(int16_t depth);
    1378             : 
    1379             :     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
    1380             : 
    1381             :   protected:
    1382             :     static already_AddRefed<XPCNativeSet> NewInstance(nsTArray<RefPtr<XPCNativeInterface>>&& array);
    1383             :     static already_AddRefed<XPCNativeSet> NewInstanceMutate(XPCNativeSetKey* key);
    1384             : 
    1385         940 :     XPCNativeSet()
    1386         940 :       : mMemberCount(0), mInterfaceCount(0)
    1387         940 :     {}
    1388             :     ~XPCNativeSet();
    1389         940 :     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
    1390             : 
    1391             :     static void DestroyInstance(XPCNativeSet* inst);
    1392             : 
    1393             :   private:
    1394             :     uint16_t                mMemberCount;
    1395             :     uint16_t                mInterfaceCount;
    1396             :     // Always last - object sized for array.
    1397             :     // These are strong references.
    1398             :     XPCNativeInterface*     mInterfaces[1];
    1399             : };
    1400             : 
    1401             : /***********************************************/
    1402             : // XPCWrappedNativeProto hold the additional shared wrapper data
    1403             : // for XPCWrappedNative whose native objects expose nsIClassInfo.
    1404             : 
    1405             : class XPCWrappedNativeProto final
    1406             : {
    1407             : public:
    1408             :     static XPCWrappedNativeProto*
    1409             :     GetNewOrUsed(XPCWrappedNativeScope* scope,
    1410             :                  nsIClassInfo* classInfo,
    1411             :                  nsIXPCScriptable* scriptable,
    1412             :                  bool callPostCreatePrototype = true);
    1413             : 
    1414             :     XPCWrappedNativeScope*
    1415        4092 :     GetScope()   const {return mScope;}
    1416             : 
    1417             :     XPCJSRuntime*
    1418           0 :     GetRuntime() const {return mScope->GetRuntime();}
    1419             : 
    1420             :     JSObject*
    1421        4638 :     GetJSProtoObject() const { return mJSProtoObject; }
    1422             : 
    1423             :     JSObject*
    1424           0 :     GetJSProtoObjectPreserveColor() const { return mJSProtoObject.unbarrieredGet(); }
    1425             : 
    1426             :     nsIClassInfo*
    1427        5905 :     GetClassInfo()     const {return mClassInfo;}
    1428             : 
    1429             :     XPCNativeSet*
    1430       28285 :     GetSet()           const {return mSet;}
    1431             : 
    1432             :     nsIXPCScriptable*
    1433        3891 :     GetScriptable() const { return mScriptable; }
    1434             : 
    1435             :     bool CallPostCreatePrototype();
    1436             :     void JSProtoObjectFinalized(js::FreeOp* fop, JSObject* obj);
    1437             :     void JSProtoObjectMoved(JSObject* obj, const JSObject* old);
    1438             : 
    1439             :     void SystemIsBeingShutDown();
    1440             : 
    1441             :     void DebugDump(int16_t depth);
    1442             : 
    1443         173 :     void TraceSelf(JSTracer* trc) {
    1444         173 :         if (mJSProtoObject)
    1445         173 :             mJSProtoObject.trace(trc, "XPCWrappedNativeProto::mJSProtoObject");
    1446         173 :     }
    1447             : 
    1448          24 :     void TraceInside(JSTracer* trc) {
    1449          24 :         GetScope()->TraceSelf(trc);
    1450          24 :     }
    1451             : 
    1452           0 :     void TraceJS(JSTracer* trc) {
    1453           0 :         TraceSelf(trc);
    1454           0 :         TraceInside(trc);
    1455           0 :     }
    1456             : 
    1457             :     void WriteBarrierPre(JSContext* cx)
    1458             :     {
    1459             :         if (JS::IsIncrementalBarrierNeeded(cx) && mJSProtoObject)
    1460             :             mJSProtoObject.writeBarrierPre(cx);
    1461             :     }
    1462             : 
    1463             :     // NOP. This is just here to make the AutoMarkingPtr code compile.
    1464           0 :     void Mark() const {}
    1465           0 :     inline void AutoTrace(JSTracer* trc) {}
    1466             : 
    1467             :     ~XPCWrappedNativeProto();
    1468             : 
    1469             : protected:
    1470             :     // disable copy ctor and assignment
    1471             :     XPCWrappedNativeProto(const XPCWrappedNativeProto& r) = delete;
    1472             :     XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r) = delete;
    1473             : 
    1474             :     // hide ctor
    1475             :     XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
    1476             :                           nsIClassInfo* ClassInfo,
    1477             :                           already_AddRefed<XPCNativeSet>&& Set);
    1478             : 
    1479             :     bool Init(nsIXPCScriptable* scriptable, bool callPostCreatePrototype);
    1480             : 
    1481             : private:
    1482             : #ifdef DEBUG
    1483             :     static int32_t gDEBUG_LiveProtoCount;
    1484             : #endif
    1485             : 
    1486             : private:
    1487             :     XPCWrappedNativeScope*   mScope;
    1488             :     JS::ObjectPtr            mJSProtoObject;
    1489             :     nsCOMPtr<nsIClassInfo>   mClassInfo;
    1490             :     RefPtr<XPCNativeSet>     mSet;
    1491             :     nsCOMPtr<nsIXPCScriptable> mScriptable;
    1492             : };
    1493             : 
    1494             : /***********************************************/
    1495             : // XPCWrappedNativeTearOff represents the info needed to make calls to one
    1496             : // interface on the underlying native object of a XPCWrappedNative.
    1497             : 
    1498             : class XPCWrappedNativeTearOff final
    1499             : {
    1500             : public:
    1501       18093 :     bool IsAvailable() const {return mInterface == nullptr;}
    1502             :     bool IsReserved()  const {return mInterface == (XPCNativeInterface*)1;}
    1503             :     bool IsValid()     const {return !IsAvailable() && !IsReserved();}
    1504        7716 :     void   SetReserved()       {mInterface = (XPCNativeInterface*)1;}
    1505             : 
    1506       42708 :     XPCNativeInterface* GetInterface() const {return mInterface;}
    1507       11998 :     nsISupports*        GetNative()    const {return mNative;}
    1508             :     JSObject*           GetJSObject();
    1509             :     JSObject*           GetJSObjectPreserveColor() const;
    1510        7716 :     void SetInterface(XPCNativeInterface*  Interface) {mInterface = Interface;}
    1511        7707 :     void SetNative(nsISupports*  Native)              {mNative = Native;}
    1512           0 :     already_AddRefed<nsISupports> TakeNative() { return mNative.forget(); }
    1513             :     void SetJSObject(JSObject*  JSObj);
    1514             : 
    1515           0 :     void JSObjectFinalized() {SetJSObject(nullptr);}
    1516             :     void JSObjectMoved(JSObject* obj, const JSObject* old);
    1517             : 
    1518        7716 :     XPCWrappedNativeTearOff()
    1519        7716 :         : mInterface(nullptr), mJSObject(nullptr)
    1520             :     {
    1521        7716 :         MOZ_COUNT_CTOR(XPCWrappedNativeTearOff);
    1522        7716 :     }
    1523             :     ~XPCWrappedNativeTearOff();
    1524             : 
    1525             :     // NOP. This is just here to make the AutoMarkingPtr code compile.
    1526           0 :     inline void TraceJS(JSTracer* trc) {}
    1527           0 :     inline void AutoTrace(JSTracer* trc) {}
    1528             : 
    1529           0 :     void Mark()       {mJSObject.setFlags(1);}
    1530        7719 :     void Unmark()     {mJSObject.unsetFlags(1);}
    1531           0 :     bool IsMarked() const {return mJSObject.hasFlag(1);}
    1532             : 
    1533        2005 :     XPCWrappedNativeTearOff* AddTearOff()
    1534             :     {
    1535        2005 :         MOZ_ASSERT(!mNextTearOff);
    1536        2005 :         mNextTearOff = mozilla::MakeUnique<XPCWrappedNativeTearOff>();
    1537        2005 :         return mNextTearOff.get();
    1538             :     }
    1539             : 
    1540       18093 :     XPCWrappedNativeTearOff* GetNextTearOff() {return mNextTearOff.get();}
    1541             : 
    1542             : private:
    1543             :     XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) = delete;
    1544             :     XPCWrappedNativeTearOff& operator= (const XPCWrappedNativeTearOff& r) = delete;
    1545             : 
    1546             : private:
    1547             :     XPCNativeInterface* mInterface;
    1548             :     // mNative is an nsRefPtr not an nsCOMPtr because it may not be the canonical
    1549             :     // nsISupports pointer.
    1550             :     RefPtr<nsISupports> mNative;
    1551             :     JS::TenuredHeap<JSObject*> mJSObject;
    1552             :     mozilla::UniquePtr<XPCWrappedNativeTearOff> mNextTearOff;
    1553             : };
    1554             : 
    1555             : 
    1556             : /***************************************************************************/
    1557             : // XPCWrappedNative the wrapper around one instance of a native xpcom object
    1558             : // to be used from JavaScript.
    1559             : 
    1560             : class XPCWrappedNative final : public nsIXPConnectWrappedNative
    1561             : {
    1562             : public:
    1563             :     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    1564             :     NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
    1565             :     NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
    1566             : 
    1567       48048 :     NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
    1568             : 
    1569             :     nsIPrincipal* GetObjectPrincipal() const;
    1570             : 
    1571             :     bool
    1572       62850 :     IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); }
    1573             : 
    1574             : #define XPC_SCOPE_WORD(s)   (intptr_t(s))
    1575             : #define XPC_SCOPE_MASK      (intptr_t(0x3))
    1576             : #define XPC_SCOPE_TAG       (intptr_t(0x1))
    1577             : #define XPC_WRAPPER_EXPIRED (intptr_t(0x2))
    1578             : 
    1579             :     static inline bool
    1580       69797 :     IsTaggedScope(XPCWrappedNativeScope* s)
    1581       69797 :         {return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;}
    1582             : 
    1583             :     static inline XPCWrappedNativeScope*
    1584        1333 :     TagScope(XPCWrappedNativeScope* s)
    1585        1333 :         {MOZ_ASSERT(!IsTaggedScope(s), "bad pointer!");
    1586        1333 :          return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) | XPC_SCOPE_TAG);}
    1587             : 
    1588             :     static inline XPCWrappedNativeScope*
    1589             :     UnTagScope(XPCWrappedNativeScope* s)
    1590             :         {return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) & ~XPC_SCOPE_TAG);}
    1591             : 
    1592             :     inline bool
    1593           2 :     IsWrapperExpired() const
    1594           2 :         {return XPC_SCOPE_WORD(mMaybeScope) & XPC_WRAPPER_EXPIRED;}
    1595             : 
    1596             :     bool
    1597       68464 :     HasProto() const {return !IsTaggedScope(mMaybeScope);}
    1598             : 
    1599             :     XPCWrappedNativeProto*
    1600       32083 :     GetProto() const
    1601       62648 :         {return HasProto() ?
    1602             :          (XPCWrappedNativeProto*)
    1603       62648 :          (XPC_SCOPE_WORD(mMaybeProto) & ~XPC_SCOPE_MASK) : nullptr;}
    1604             : 
    1605             :     XPCWrappedNativeScope*
    1606        1695 :     GetScope() const
    1607        3213 :         {return GetProto() ? GetProto()->GetScope() :
    1608             :          (XPCWrappedNativeScope*)
    1609        3213 :          (XPC_SCOPE_WORD(mMaybeScope) & ~XPC_SCOPE_MASK);}
    1610             : 
    1611             :     nsISupports*
    1612       17937 :     GetIdentityObject() const {return mIdentity;}
    1613             : 
    1614             :     /**
    1615             :      * This getter clears the gray bit before handing out the JSObject which
    1616             :      * means that the object is guaranteed to be kept alive past the next CC.
    1617             :      */
    1618       33427 :     JSObject* GetFlatJSObject() const { return mFlatJSObject; }
    1619             : 
    1620             :     /**
    1621             :      * This getter does not change the color of the JSObject meaning that the
    1622             :      * object returned is not guaranteed to be kept alive past the next CC.
    1623             :      *
    1624             :      * This should only be called if you are certain that the return value won't
    1625             :      * be passed into a JS API function and that it won't be stored without
    1626             :      * being rooted (or otherwise signaling the stored value to the CC).
    1627             :      */
    1628             :     JSObject*
    1629           0 :     GetFlatJSObjectPreserveColor() const {
    1630           0 :         return mFlatJSObject.unbarrieredGetPtr();
    1631             :     }
    1632             : 
    1633             :     XPCNativeSet*
    1634       43169 :     GetSet() const {return mSet;}
    1635             : 
    1636             :     void
    1637        2768 :     SetSet(already_AddRefed<XPCNativeSet> set) {mSet = set;}
    1638             : 
    1639       50779 :     static XPCWrappedNative* Get(JSObject* obj) {
    1640       50779 :         MOZ_ASSERT(IS_WN_REFLECTOR(obj));
    1641       50779 :         return (XPCWrappedNative*)js::GetObjectPrivate(obj);
    1642             :     }
    1643             : 
    1644             : private:
    1645             :     inline void
    1646           0 :     ExpireWrapper()
    1647           0 :         {mMaybeScope = (XPCWrappedNativeScope*)
    1648           0 :                        (XPC_SCOPE_WORD(mMaybeScope) | XPC_WRAPPER_EXPIRED);}
    1649             : 
    1650             : public:
    1651             : 
    1652             :     nsIXPCScriptable*
    1653       59460 :     GetScriptable() const { return mScriptable; }
    1654             : 
    1655             :     nsIClassInfo*
    1656       13616 :     GetClassInfo() const {return IsValid() && HasProto() ?
    1657       13616 :                             GetProto()->GetClassInfo() : nullptr;}
    1658             : 
    1659             :     bool
    1660       36230 :     HasMutatedSet() const {return IsValid() &&
    1661       35632 :                                   (!HasProto() ||
    1662       35632 :                                    GetSet() != GetProto()->GetSet());}
    1663             : 
    1664             :     XPCJSRuntime*
    1665           0 :     GetRuntime() const {XPCWrappedNativeScope* scope = GetScope();
    1666           0 :                         return scope ? scope->GetRuntime() : nullptr;}
    1667             : 
    1668             :     static nsresult
    1669             :     WrapNewGlobal(xpcObjectHelper& nativeHelper,
    1670             :                   nsIPrincipal* principal, bool initStandardClasses,
    1671             :                   JS::CompartmentOptions& aOptions,
    1672             :                   XPCWrappedNative** wrappedGlobal);
    1673             : 
    1674             :     static nsresult
    1675             :     GetNewOrUsed(xpcObjectHelper& helper,
    1676             :                  XPCWrappedNativeScope* Scope,
    1677             :                  XPCNativeInterface* Interface,
    1678             :                  XPCWrappedNative** wrapper);
    1679             : 
    1680             :     static nsresult
    1681             :     GetUsedOnly(nsISupports* Object,
    1682             :                 XPCWrappedNativeScope* Scope,
    1683             :                 XPCNativeInterface* Interface,
    1684             :                 XPCWrappedNative** wrapper);
    1685             : 
    1686             :     void FlatJSObjectFinalized();
    1687             :     void FlatJSObjectMoved(JSObject* obj, const JSObject* old);
    1688             : 
    1689             :     void SystemIsBeingShutDown();
    1690             : 
    1691             :     enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
    1692             : 
    1693             :     static bool CallMethod(XPCCallContext& ccx,
    1694             :                            CallMode mode = CALL_METHOD);
    1695             : 
    1696        2865 :     static bool GetAttribute(XPCCallContext& ccx)
    1697        2865 :         {return CallMethod(ccx, CALL_GETTER);}
    1698             : 
    1699          38 :     static bool SetAttribute(XPCCallContext& ccx)
    1700          38 :         {return CallMethod(ccx, CALL_SETTER);}
    1701             : 
    1702             :     inline bool HasInterfaceNoQI(const nsIID& iid);
    1703             : 
    1704             :     XPCWrappedNativeTearOff* FindTearOff(XPCNativeInterface* aInterface,
    1705             :                                          bool needJSObject = false,
    1706             :                                          nsresult* pError = nullptr);
    1707             :     XPCWrappedNativeTearOff* FindTearOff(const nsIID& iid);
    1708             : 
    1709           0 :     void Mark() const {}
    1710             : 
    1711         183 :     inline void TraceInside(JSTracer* trc) {
    1712         183 :         if (HasProto())
    1713         173 :             GetProto()->TraceSelf(trc);
    1714             :         else
    1715          10 :             GetScope()->TraceSelf(trc);
    1716             : 
    1717         183 :         JSObject* obj = mFlatJSObject.unbarrieredGetPtr();
    1718         183 :         if (obj && JS_IsGlobalObject(obj)) {
    1719           0 :             xpc::TraceXPCGlobal(trc, obj);
    1720             :         }
    1721         183 :     }
    1722             : 
    1723           0 :     void TraceJS(JSTracer* trc) {
    1724           0 :         TraceInside(trc);
    1725           0 :     }
    1726             : 
    1727           2 :     void TraceSelf(JSTracer* trc) {
    1728             :         // If this got called, we're being kept alive by someone who really
    1729             :         // needs us alive and whole.  Do not let our mFlatJSObject go away.
    1730             :         // This is the only time we should be tracing our mFlatJSObject,
    1731             :         // normally somebody else is doing that.
    1732           2 :         JS::TraceEdge(trc, &mFlatJSObject, "XPCWrappedNative::mFlatJSObject");
    1733           2 :     }
    1734             : 
    1735             :     static void Trace(JSTracer* trc, JSObject* obj);
    1736             : 
    1737           0 :     void AutoTrace(JSTracer* trc) {
    1738           0 :         TraceSelf(trc);
    1739           0 :     }
    1740             : 
    1741             :     inline void SweepTearOffs();
    1742             : 
    1743             :     // Returns a string that shuld be free'd using JS_smprintf_free (or null).
    1744             :     char* ToString(XPCWrappedNativeTearOff* to = nullptr) const;
    1745             : 
    1746             :     static nsIXPCScriptable* GatherProtoScriptable(nsIClassInfo* classInfo);
    1747             : 
    1748        4476 :     bool HasExternalReference() const {return mRefCnt > 1;}
    1749             : 
    1750             :     void Suspect(nsCycleCollectionNoteRootCallback& cb);
    1751             :     void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
    1752             : 
    1753             :     // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
    1754             : protected:
    1755             :     XPCWrappedNative() = delete;
    1756             : 
    1757             :     // This ctor is used if this object will have a proto.
    1758             :     XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
    1759             :                      XPCWrappedNativeProto* aProto);
    1760             : 
    1761             :     // This ctor is used if this object will NOT have a proto.
    1762             :     XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
    1763             :                      XPCWrappedNativeScope* aScope,
    1764             :                      already_AddRefed<XPCNativeSet>&& aSet);
    1765             : 
    1766             :     virtual ~XPCWrappedNative();
    1767             :     void Destroy();
    1768             : 
    1769             : private:
    1770             :     enum {
    1771             :         // Flags bits for mFlatJSObject:
    1772             :         FLAT_JS_OBJECT_VALID = JS_BIT(0)
    1773             :     };
    1774             : 
    1775             :     bool Init(nsIXPCScriptable* scriptable);
    1776             :     bool FinishInit();
    1777             : 
    1778             :     bool ExtendSet(XPCNativeInterface* aInterface);
    1779             : 
    1780             :     nsresult InitTearOff(XPCWrappedNativeTearOff* aTearOff,
    1781             :                          XPCNativeInterface* aInterface,
    1782             :                          bool needJSObject);
    1783             : 
    1784             :     bool InitTearOffJSObject(XPCWrappedNativeTearOff* to);
    1785             : 
    1786             : public:
    1787             :     static void GatherScriptable(nsISupports* obj,
    1788             :                                  nsIClassInfo* classInfo,
    1789             :                                  nsIXPCScriptable** scrProto,
    1790             :                                  nsIXPCScriptable** scrWrapper);
    1791             : 
    1792             : private:
    1793             :     union
    1794             :     {
    1795             :         XPCWrappedNativeScope* mMaybeScope;
    1796             :         XPCWrappedNativeProto* mMaybeProto;
    1797             :     };
    1798             :     RefPtr<XPCNativeSet> mSet;
    1799             :     JS::TenuredHeap<JSObject*> mFlatJSObject;
    1800             :     nsCOMPtr<nsIXPCScriptable> mScriptable;
    1801             :     XPCWrappedNativeTearOff mFirstTearOff;
    1802             : };
    1803             : 
    1804             : /***************************************************************************
    1805             : ****************************************************************************
    1806             : *
    1807             : * Core classes for wrapped JSObject for use from native code...
    1808             : *
    1809             : ****************************************************************************
    1810             : ***************************************************************************/
    1811             : 
    1812             : // this interfaces exists so we can refcount nsXPCWrappedJSClass
    1813             : // {2453EBA0-A9B8-11d2-BA64-00805F8A5DD7}
    1814             : #define NS_IXPCONNECT_WRAPPED_JS_CLASS_IID                                    \
    1815             : { 0x2453eba0, 0xa9b8, 0x11d2,                                                 \
    1816             :   { 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
    1817             : 
    1818          92 : class nsIXPCWrappedJSClass : public nsISupports
    1819             : {
    1820             : public:
    1821             :     NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
    1822             :     NS_IMETHOD DebugDump(int16_t depth) = 0;
    1823             : };
    1824             : 
    1825             : NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPCWrappedJSClass,
    1826             :                               NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
    1827             : 
    1828             : /*************************/
    1829             : // nsXPCWrappedJSClass represents the sharable factored out common code and
    1830             : // data for nsXPCWrappedJS instances for the same interface type.
    1831             : 
    1832             : class nsXPCWrappedJSClass final : public nsIXPCWrappedJSClass
    1833             : {
    1834             :     // all the interface method declarations...
    1835             :     NS_DECL_ISUPPORTS
    1836             :     NS_IMETHOD DebugDump(int16_t depth) override;
    1837             : public:
    1838             : 
    1839             :     static already_AddRefed<nsXPCWrappedJSClass>
    1840             :     GetNewOrUsed(JSContext* cx,
    1841             :                  REFNSIID aIID,
    1842             :                  bool allowNonScriptable = false);
    1843             : 
    1844        3875 :     REFNSIID GetIID() const {return mIID;}
    1845         976 :     XPCJSRuntime* GetRuntime() const {return mRuntime;}
    1846        1057 :     nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
    1847             :     const char* GetInterfaceName();
    1848             : 
    1849             :     static bool IsWrappedJS(nsISupports* aPtr);
    1850             : 
    1851             :     NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
    1852             :                                        void** aInstancePtr);
    1853             : 
    1854             :     JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj);
    1855             : 
    1856             :     NS_IMETHOD CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
    1857             :                           const XPTMethodDescriptor* info,
    1858             :                           nsXPTCMiniVariant* params);
    1859             : 
    1860             :     JSObject*  CallQueryInterfaceOnJSObject(JSContext* cx,
    1861             :                                             JSObject* jsobj, REFNSIID aIID);
    1862             : 
    1863             :     static nsresult BuildPropertyEnumerator(XPCCallContext& ccx,
    1864             :                                             JSObject* aJSObj,
    1865             :                                             nsISimpleEnumerator** aEnumerate);
    1866             : 
    1867             :     static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
    1868             :                                               JSObject* aJSObj,
    1869             :                                               const nsAString& aName,
    1870             :                                               nsIVariant** aResult);
    1871             : 
    1872             : private:
    1873             :     // aSyntheticException, if not null, is the exception we should be using.
    1874             :     // If null, look for an exception on the JSContext hanging off the
    1875             :     // XPCCallContext.
    1876             :     static nsresult CheckForException(XPCCallContext & ccx,
    1877             :                                       mozilla::dom::AutoEntryScript& aes,
    1878             :                                       const char * aPropertyName,
    1879             :                                       const char * anInterfaceName,
    1880             :                                       nsIException* aSyntheticException = nullptr);
    1881             :     virtual ~nsXPCWrappedJSClass();
    1882             : 
    1883             :     nsXPCWrappedJSClass() = delete;
    1884             :     nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID,
    1885             :                         nsIInterfaceInfo* aInfo);
    1886             : 
    1887         679 :     bool IsReflectable(uint16_t i) const
    1888         679 :         {return (bool)(mDescriptors[i/32] & (1 << (i%32)));}
    1889         679 :     void SetReflectable(uint16_t i, bool b)
    1890         679 :         {if (b) mDescriptors[i/32] |= (1 << (i%32));
    1891         184 :          else mDescriptors[i/32] &= ~(1 << (i%32));}
    1892             : 
    1893             :     bool GetArraySizeFromParam(JSContext* cx,
    1894             :                                const XPTMethodDescriptor* method,
    1895             :                                const nsXPTParamInfo& param,
    1896             :                                uint16_t methodIndex,
    1897             :                                uint8_t paramIndex,
    1898             :                                nsXPTCMiniVariant* params,
    1899             :                                uint32_t* result) const;
    1900             : 
    1901             :     bool GetInterfaceTypeFromParam(JSContext* cx,
    1902             :                                    const XPTMethodDescriptor* method,
    1903             :                                    const nsXPTParamInfo& param,
    1904             :                                    uint16_t methodIndex,
    1905             :                                    const nsXPTType& type,
    1906             :                                    nsXPTCMiniVariant* params,
    1907             :                                    nsID* result) const;
    1908             : 
    1909             :     static void CleanupPointerArray(const nsXPTType& datum_type,
    1910             :                                     uint32_t array_count,
    1911             :                                     void** arrayp);
    1912             : 
    1913             :     static void CleanupPointerTypeObject(const nsXPTType& type,
    1914             :                                          void** pp);
    1915             : 
    1916             :     void CleanupOutparams(JSContext* cx, uint16_t methodIndex, const nsXPTMethodInfo* info,
    1917             :                           nsXPTCMiniVariant* nativeParams, bool inOutOnly, uint8_t n) const;
    1918             : 
    1919             : private:
    1920             :     XPCJSRuntime* mRuntime;
    1921             :     nsCOMPtr<nsIInterfaceInfo> mInfo;
    1922             :     char* mName;
    1923             :     nsIID mIID;
    1924             :     uint32_t* mDescriptors;
    1925             : };
    1926             : 
    1927             : /*************************/
    1928             : // nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
    1929             : // nsXPCWrappedJS objects are chained together to represent the various
    1930             : // interface on the single underlying (possibly aggregate) JSObject.
    1931             : 
    1932             : class nsXPCWrappedJS final : protected nsAutoXPTCStub,
    1933             :                              public nsIXPConnectWrappedJSUnmarkGray,
    1934             :                              public nsSupportsWeakReference,
    1935             :                              public nsIPropertyBag,
    1936             :                              public XPCRootSetElem
    1937             : {
    1938             : public:
    1939             :     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    1940             :     NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
    1941             :     NS_DECL_NSIXPCONNECTWRAPPEDJS
    1942             :     NS_DECL_NSIXPCONNECTWRAPPEDJSUNMARKGRAY
    1943             :     NS_DECL_NSISUPPORTSWEAKREFERENCE
    1944             :     NS_DECL_NSIPROPERTYBAG
    1945             : 
    1946       16122 :     NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
    1947             : 
    1948             :     NS_IMETHOD CallMethod(uint16_t methodIndex,
    1949             :                           const XPTMethodDescriptor* info,
    1950             :                           nsXPTCMiniVariant* params) override;
    1951             : 
    1952             :     /*
    1953             :     * This is rarely called directly. Instead one usually calls
    1954             :     * XPCConvert::JSObject2NativeInterface which will handles cases where the
    1955             :     * JS object is already a wrapped native or a DOM object.
    1956             :     */
    1957             : 
    1958             :     static nsresult
    1959             :     GetNewOrUsed(JS::HandleObject aJSObj,
    1960             :                  REFNSIID aIID,
    1961             :                  nsXPCWrappedJS** wrapper);
    1962             : 
    1963        1680 :     nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
    1964             : 
    1965             :     /**
    1966             :      * This getter does not change the color of the JSObject meaning that the
    1967             :      * object returned is not guaranteed to be kept alive past the next CC.
    1968             :      *
    1969             :      * This should only be called if you are certain that the return value won't
    1970             :      * be passed into a JS API function and that it won't be stored without
    1971             :      * being rooted (or otherwise signaling the stored value to the CC).
    1972             :      */
    1973        1574 :     JSObject* GetJSObjectPreserveColor() const { return mJSObj.unbarrieredGet(); }
    1974             : 
    1975             :     // Returns true if the wrapper chain contains references to multiple
    1976             :     // compartments. If the wrapper chain contains references to multiple
    1977             :     // compartments, then it must be registered on the XPCJSContext. Otherwise,
    1978             :     // it should be registered in the CompartmentPrivate for the compartment of
    1979             :     // the root's JS object. This will only return correct results when called
    1980             :     // on the root wrapper and will assert if not called on a root wrapper.
    1981             :     bool IsMultiCompartment() const;
    1982             : 
    1983        4941 :     nsXPCWrappedJSClass*  GetClass() const {return mClass;}
    1984        2819 :     REFNSIID GetIID() const {return GetClass()->GetIID();}
    1985         111 :     nsXPCWrappedJS* GetRootWrapper() const {return mRoot;}
    1986           0 :     nsXPCWrappedJS* GetNextWrapper() const {return mNext;}
    1987             : 
    1988             :     nsXPCWrappedJS* Find(REFNSIID aIID);
    1989             :     nsXPCWrappedJS* FindInherited(REFNSIID aIID);
    1990        2535 :     nsXPCWrappedJS* FindOrFindInherited(REFNSIID aIID) {
    1991        2535 :         nsXPCWrappedJS* wrapper = Find(aIID);
    1992        2535 :         if (wrapper)
    1993        2137 :             return wrapper;
    1994         398 :         return FindInherited(aIID);
    1995             :     }
    1996             : 
    1997        2932 :     bool IsRootWrapper() const { return mRoot == this; }
    1998        6262 :     bool IsValid() const { return bool(mJSObj); }
    1999             :     void SystemIsBeingShutDown();
    2000             : 
    2001             :     // These two methods are used by JSObject2WrappedJSMap::FindDyingJSObjects
    2002             :     // to find non-rooting wrappers for dying JS objects. See the top of
    2003             :     // XPCWrappedJS.cpp for more details.
    2004           0 :     bool IsSubjectToFinalization() const {return IsValid() && mRefCnt == 1;}
    2005           0 :     void UpdateObjectPointerAfterGC() {JS_UpdateWeakPointerAfterGC(&mJSObj);}
    2006             : 
    2007          66 :     bool IsAggregatedToNative() const {return mRoot->mOuter != nullptr;}
    2008        2123 :     nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
    2009          18 :     void SetAggregatedNativeObject(nsISupports* aNative) {
    2010          18 :         MOZ_ASSERT(aNative);
    2011          18 :         if (mRoot->mOuter) {
    2012           2 :             MOZ_ASSERT(mRoot->mOuter == aNative,
    2013             :                        "Only one aggregated native can be set");
    2014           2 :             return;
    2015             :         }
    2016          16 :         mRoot->mOuter = aNative;
    2017             :     }
    2018             : 
    2019             :     void TraceJS(JSTracer* trc);
    2020             : 
    2021             :     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    2022             : 
    2023             :     virtual ~nsXPCWrappedJS();
    2024             : protected:
    2025             :     nsXPCWrappedJS() = delete;
    2026             :     nsXPCWrappedJS(JSContext* cx,
    2027             :                    JSObject* aJSObj,
    2028             :                    nsXPCWrappedJSClass* aClass,
    2029             :                    nsXPCWrappedJS* root,
    2030             :                    nsresult* rv);
    2031             : 
    2032             :     bool CanSkip();
    2033             :     void Destroy();
    2034             :     void Unlink();
    2035             : 
    2036             : private:
    2037        1394 :     JSCompartment* Compartment() const {
    2038        1394 :         return js::GetObjectCompartment(mJSObj.unbarrieredGet());
    2039             :     }
    2040             : 
    2041             :     JS::Heap<JSObject*> mJSObj;
    2042             :     RefPtr<nsXPCWrappedJSClass> mClass;
    2043             :     nsXPCWrappedJS* mRoot;    // If mRoot != this, it is an owning pointer.
    2044             :     nsXPCWrappedJS* mNext;
    2045             :     nsCOMPtr<nsISupports> mOuter;    // only set in root
    2046             : };
    2047             : 
    2048             : /***************************************************************************/
    2049             : 
    2050             : class XPCJSObjectHolder final : public nsIXPConnectJSObjectHolder
    2051             : {
    2052             : public:
    2053             :     // all the interface method declarations...
    2054             :     NS_DECL_ISUPPORTS
    2055             :     NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
    2056             : 
    2057             :     // non-interface implementation
    2058             : 
    2059             : public:
    2060             :     XPCJSObjectHolder(JSContext* cx, JSObject* obj);
    2061             : 
    2062             : private:
    2063           0 :     virtual ~XPCJSObjectHolder() {}
    2064             :     XPCJSObjectHolder() = delete;
    2065             : 
    2066             :     JS::PersistentRooted<JSObject*> mJSObj;
    2067             : };
    2068             : 
    2069             : /***************************************************************************
    2070             : ****************************************************************************
    2071             : *
    2072             : * All manner of utility classes follow...
    2073             : *
    2074             : ****************************************************************************
    2075             : ***************************************************************************/
    2076             : 
    2077             : class xpcProperty : public nsIProperty
    2078             : {
    2079             : public:
    2080             :   NS_DECL_ISUPPORTS
    2081             :   NS_DECL_NSIPROPERTY
    2082             : 
    2083             :   xpcProperty(const char16_t* aName, uint32_t aNameLen, nsIVariant* aValue);
    2084             : 
    2085             : private:
    2086           0 :     virtual ~xpcProperty() {}
    2087             : 
    2088             :     nsString             mName;
    2089             :     nsCOMPtr<nsIVariant> mValue;
    2090             : };
    2091             : 
    2092             : /***************************************************************************/
    2093             : // class here just for static methods
    2094             : class XPCConvert
    2095             : {
    2096             : public:
    2097             :     static bool IsMethodReflectable(const XPTMethodDescriptor& info);
    2098             : 
    2099             :     /**
    2100             :      * Convert a native object into a JS::Value.
    2101             :      *
    2102             :      * @param d [out] the resulting JS::Value
    2103             :      * @param s the native object we're working with
    2104             :      * @param type the type of object that s is
    2105             :      * @param iid the interface of s that we want
    2106             :      * @param scope the default scope to put on the new JSObject's parent
    2107             :      *        chain
    2108             :      * @param pErr [out] relevant error code, if any.
    2109             :      */
    2110             : 
    2111             :     static bool NativeData2JS(JS::MutableHandleValue d,
    2112             :                               const void* s, const nsXPTType& type,
    2113             :                               const nsID* iid, nsresult* pErr);
    2114             : 
    2115             :     static bool JSData2Native(void* d, JS::HandleValue s,
    2116             :                               const nsXPTType& type,
    2117             :                               const nsID* iid,
    2118             :                               nsresult* pErr);
    2119             : 
    2120             :     /**
    2121             :      * Convert a native nsISupports into a JSObject.
    2122             :      *
    2123             :      * @param dest [out] the resulting JSObject
    2124             :      * @param src the native object we're working with
    2125             :      * @param iid the interface of src that we want (may be null)
    2126             :      * @param cache the wrapper cache for src (may be null, in which case src
    2127             :      *              will be QI'ed to get the cache)
    2128             :      * @param allowNativeWrapper if true, this method may wrap the resulting
    2129             :      *        JSObject in an XPCNativeWrapper and return that, as needed.
    2130             :      * @param pErr [out] relevant error code, if any.
    2131             :      * @param src_is_identity optional performance hint. Set to true only
    2132             :      *                        if src is the identity pointer.
    2133             :      */
    2134             :     static bool NativeInterface2JSObject(JS::MutableHandleValue d,
    2135             :                                          nsIXPConnectJSObjectHolder** dest,
    2136             :                                          xpcObjectHelper& aHelper,
    2137             :                                          const nsID* iid,
    2138             :                                          bool allowNativeWrapper,
    2139             :                                          nsresult* pErr);
    2140             : 
    2141             :     static bool GetNativeInterfaceFromJSObject(void** dest, JSObject* src,
    2142             :                                                const nsID* iid,
    2143             :                                                nsresult* pErr);
    2144             :     static bool JSObject2NativeInterface(void** dest, JS::HandleObject src,
    2145             :                                          const nsID* iid,
    2146             :                                          nsISupports* aOuter,
    2147             :                                          nsresult* pErr);
    2148             : 
    2149             :     // Note - This return the XPCWrappedNative, rather than the native itself,
    2150             :     // for the WN case. You probably want UnwrapReflectorToISupports.
    2151             :     static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
    2152             : 
    2153             :     /**
    2154             :      * Convert a native array into a JS::Value.
    2155             :      *
    2156             :      * @param d [out] the resulting JS::Value
    2157             :      * @param s the native array we're working with
    2158             :      * @param type the type of objects in the array
    2159             :      * @param iid the interface of each object in the array that we want
    2160             :      * @param count the number of items in the array
    2161             :      * @param scope the default scope to put on the new JSObjects' parent chain
    2162             :      * @param pErr [out] relevant error code, if any.
    2163             :      */
    2164             :     static bool NativeArray2JS(JS::MutableHandleValue d, const void** s,
    2165             :                                const nsXPTType& type, const nsID* iid,
    2166             :                                uint32_t count, nsresult* pErr);
    2167             : 
    2168             :     static bool JSArray2Native(void** d, JS::HandleValue s,
    2169             :                                uint32_t count, const nsXPTType& type,
    2170             :                                const nsID* iid, nsresult* pErr);
    2171             : 
    2172             :     static bool JSTypedArray2Native(void** d,
    2173             :                                     JSObject* jsarray,
    2174             :                                     uint32_t count,
    2175             :                                     const nsXPTType& type,
    2176             :                                     nsresult* pErr);
    2177             : 
    2178             :     static bool NativeStringWithSize2JS(JS::MutableHandleValue d, const void* s,
    2179             :                                         const nsXPTType& type,
    2180             :                                         uint32_t count,
    2181             :                                         nsresult* pErr);
    2182             : 
    2183             :     static bool JSStringWithSize2Native(void* d, JS::HandleValue s,
    2184             :                                         uint32_t count, const nsXPTType& type,
    2185             :                                         nsresult* pErr);
    2186             : 
    2187             :     static nsresult JSValToXPCException(JS::MutableHandleValue s,
    2188             :                                         const char* ifaceName,
    2189             :                                         const char* methodName,
    2190             :                                         nsIException** exception);
    2191             : 
    2192             :     static nsresult ConstructException(nsresult rv, const char* message,
    2193             :                                        const char* ifaceName,
    2194             :                                        const char* methodName,
    2195             :                                        nsISupports* data,
    2196             :                                        nsIException** exception,
    2197             :                                        JSContext* cx,
    2198             :                                        JS::Value* jsExceptionPtr);
    2199             : 
    2200             : private:
    2201             :     XPCConvert() = delete;
    2202             : 
    2203             : };
    2204             : 
    2205             : /***************************************************************************/
    2206             : // code for throwing exceptions into JS
    2207             : 
    2208             : class nsXPCException;
    2209             : 
    2210             : class XPCThrower
    2211             : {
    2212             : public:
    2213             :     static void Throw(nsresult rv, JSContext* cx);
    2214             :     static void Throw(nsresult rv, XPCCallContext& ccx);
    2215             :     static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
    2216             :     static void ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx);
    2217             :     static bool SetVerbosity(bool state)
    2218             :         {bool old = sVerbose; sVerbose = state; return old;}
    2219             : 
    2220             :     static bool CheckForPendingException(nsresult result, JSContext* cx);
    2221             : 
    2222             : private:
    2223             :     static void Verbosify(XPCCallContext& ccx,
    2224             :                           char** psz, bool own);
    2225             : 
    2226             : private:
    2227             :     static bool sVerbose;
    2228             : };
    2229             : 
    2230             : /***************************************************************************/
    2231             : 
    2232             : class nsXPCException
    2233             : {
    2234             : public:
    2235             :     static bool NameAndFormatForNSResult(nsresult rv,
    2236             :                                          const char** name,
    2237             :                                          const char** format);
    2238             : 
    2239             :     static const void* IterateNSResults(nsresult* rv,
    2240             :                                         const char** name,
    2241             :                                         const char** format,
    2242             :                                         const void** iterp);
    2243             : 
    2244             :     static uint32_t GetNSResultCount();
    2245             : };
    2246             : 
    2247             : /***************************************************************************/
    2248             : /*
    2249             : * nsJSID implements nsIJSID. It is also used by nsJSIID and nsJSCID as a
    2250             : * member (as a hidden implementaion detail) to which they delegate many calls.
    2251             : */
    2252             : 
    2253             : // Initialization is done on demand, and calling the destructor below is always
    2254             : // safe.
    2255             : extern void xpc_DestroyJSxIDClassObjects();
    2256             : 
    2257             : class nsJSID final : public nsIJSID
    2258             : {
    2259             : public:
    2260          78 :     NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID)
    2261             : 
    2262             :     NS_DECL_ISUPPORTS
    2263             :     NS_DECL_NSIJSID
    2264             : 
    2265             :     bool InitWithName(const nsID& id, const char* nameString);
    2266             :     bool SetName(const char* name);
    2267           0 :     void   SetNameToNoString()
    2268           0 :         {MOZ_ASSERT(!mName, "name already set"); mName = const_cast<char*>(gNoString);}
    2269           0 :     bool NameIsSet() const {return nullptr != mName;}
    2270         662 :     const nsID& ID() const {return mID;}
    2271         331 :     bool IsValid() const {return !mID.Equals(GetInvalidIID());}
    2272             : 
    2273             :     static already_AddRefed<nsJSID> NewID(const char* str);
    2274             :     static already_AddRefed<nsJSID> NewID(const nsID& id);
    2275             : 
    2276             :     nsJSID();
    2277             : 
    2278             :     void Reset();
    2279             :     const nsID& GetInvalidIID() const;
    2280             : 
    2281             : protected:
    2282             :     virtual ~nsJSID();
    2283             :     static const char gNoString[];
    2284             :     nsID    mID;
    2285             :     char*   mNumber;
    2286             :     char*   mName;
    2287             : };
    2288             : 
    2289             : 
    2290             : // nsJSIID
    2291             : 
    2292             : class nsJSIID : public nsIJSIID,
    2293             :                 public nsIXPCScriptable
    2294             : {
    2295             : public:
    2296             :     NS_DECL_ISUPPORTS
    2297             : 
    2298             :     // we manually delegate these to nsJSID
    2299             :     NS_DECL_NSIJSID
    2300             : 
    2301             :     // we implement the rest...
    2302             :     NS_DECL_NSIJSIID
    2303             :     NS_DECL_NSIXPCSCRIPTABLE
    2304             : 
    2305             :     static already_AddRefed<nsJSIID> NewID(nsIInterfaceInfo* aInfo);
    2306             : 
    2307             :     explicit nsJSIID(nsIInterfaceInfo* aInfo);
    2308             :     nsJSIID() = delete;
    2309             : 
    2310             : private:
    2311             :     virtual ~nsJSIID();
    2312             : 
    2313             :     nsCOMPtr<nsIInterfaceInfo> mInfo;
    2314             : };
    2315             : 
    2316             : // nsJSCID
    2317             : 
    2318             : class nsJSCID : public nsIJSCID, public nsIXPCScriptable
    2319             : {
    2320             : public:
    2321             :     NS_DECL_ISUPPORTS
    2322             : 
    2323             :     // we manually delegate these to nsJSID
    2324             :     NS_DECL_NSIJSID
    2325             : 
    2326             :     // we implement the rest...
    2327             :     NS_DECL_NSIJSCID
    2328             :     NS_DECL_NSIXPCSCRIPTABLE
    2329             : 
    2330             :     static already_AddRefed<nsJSCID> NewID(const char* str);
    2331             : 
    2332             :     nsJSCID();
    2333             : 
    2334             : private:
    2335             :     virtual ~nsJSCID();
    2336             : 
    2337             :     void ResolveName();
    2338             : 
    2339             : private:
    2340             :     RefPtr<nsJSID> mDetails;
    2341             : };
    2342             : 
    2343             : 
    2344             : /***************************************************************************/
    2345             : // 'Components' object implementations. nsXPCComponentsBase has the
    2346             : // less-privileged stuff that we're willing to expose to XBL.
    2347             : 
    2348             : class nsXPCComponentsBase : public nsIXPCComponentsBase
    2349             : {
    2350             : public:
    2351             :     NS_DECL_ISUPPORTS
    2352             :     NS_DECL_NSIXPCCOMPONENTSBASE
    2353             : 
    2354             : public:
    2355           0 :     void SystemIsBeingShutDown() { ClearMembers(); }
    2356             : 
    2357         562 :     XPCWrappedNativeScope* GetScope() { return mScope; }
    2358             : 
    2359             : protected:
    2360             :     virtual ~nsXPCComponentsBase();
    2361             : 
    2362             :     explicit nsXPCComponentsBase(XPCWrappedNativeScope* aScope);
    2363             :     virtual void ClearMembers();
    2364             : 
    2365             :     XPCWrappedNativeScope*                   mScope;
    2366             : 
    2367             :     // Unprivileged members from nsIXPCComponentsBase.
    2368             :     RefPtr<nsXPCComponents_Interfaces>     mInterfaces;
    2369             :     RefPtr<nsXPCComponents_InterfacesByID> mInterfacesByID;
    2370             :     RefPtr<nsXPCComponents_Results>        mResults;
    2371             : 
    2372             :     friend class XPCWrappedNativeScope;
    2373             : };
    2374             : 
    2375             : class nsXPCComponents : public nsXPCComponentsBase,
    2376             :                         public nsIXPCComponents
    2377             : {
    2378             : public:
    2379             :     NS_DECL_ISUPPORTS_INHERITED
    2380         613 :     NS_FORWARD_NSIXPCCOMPONENTSBASE(nsXPCComponentsBase::)
    2381             :     NS_DECL_NSIXPCCOMPONENTS
    2382             : 
    2383             : protected:
    2384             :     explicit nsXPCComponents(XPCWrappedNativeScope* aScope);
    2385             :     virtual ~nsXPCComponents();
    2386             :     virtual void ClearMembers() override;
    2387             : 
    2388             :     // Privileged members added by nsIXPCComponents.
    2389             :     RefPtr<nsXPCComponents_Classes>     mClasses;
    2390             :     RefPtr<nsXPCComponents_ClassesByID> mClassesByID;
    2391             :     RefPtr<nsXPCComponents_ID>          mID;
    2392             :     RefPtr<nsXPCComponents_Exception>   mException;
    2393             :     RefPtr<nsXPCComponents_Constructor> mConstructor;
    2394             :     RefPtr<nsXPCComponents_Utils>       mUtils;
    2395             : 
    2396             :     friend class XPCWrappedNativeScope;
    2397             : };
    2398             : 
    2399             : 
    2400             : /***************************************************************************/
    2401             : 
    2402             : extern JSObject*
    2403             : xpc_NewIDObject(JSContext* cx, JS::HandleObject jsobj, const nsID& aID);
    2404             : 
    2405             : extern const nsID*
    2406             : xpc_JSObjectToID(JSContext* cx, JSObject* obj);
    2407             : 
    2408             : extern bool
    2409             : xpc_JSObjectIsID(JSContext* cx, JSObject* obj);
    2410             : 
    2411             : /***************************************************************************/
    2412             : // in XPCDebug.cpp
    2413             : 
    2414             : extern bool
    2415             : xpc_DumpJSStack(bool showArgs, bool showLocals, bool showThisProps);
    2416             : 
    2417             : // Return a newly-allocated string containing a representation of the
    2418             : // current JS stack.
    2419             : extern JS::UniqueChars
    2420             : xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
    2421             :                  bool showThisProps);
    2422             : 
    2423             : /******************************************************************************
    2424             :  * Handles pre/post script processing.
    2425             :  */
    2426             : class MOZ_RAII AutoScriptEvaluate
    2427             : {
    2428             : public:
    2429             :     /**
    2430             :      * Saves the JSContext as well as initializing our state
    2431             :      * @param cx The JSContext, this can be null, we don't do anything then
    2432             :      */
    2433        2341 :     explicit AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    2434        2341 :          : mJSContext(cx), mEvaluated(false) {
    2435        2341 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    2436        2341 :     }
    2437             : 
    2438             :     /**
    2439             :      * Does the pre script evaluation.
    2440             :      * This function should only be called once, and will assert if called
    2441             :      * more than once
    2442             :      */
    2443             : 
    2444             :     bool StartEvaluating(JS::HandleObject scope);
    2445             : 
    2446             :     /**
    2447             :      * Does the post script evaluation.
    2448             :      */
    2449             :     ~AutoScriptEvaluate();
    2450             : private:
    2451             :     JSContext* mJSContext;
    2452             :     mozilla::Maybe<JS::AutoSaveExceptionState> mState;
    2453             :     bool mEvaluated;
    2454             :     mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
    2455             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    2456             : 
    2457             :     // No copying or assignment allowed
    2458             :     AutoScriptEvaluate(const AutoScriptEvaluate&) = delete;
    2459             :     AutoScriptEvaluate & operator =(const AutoScriptEvaluate&) = delete;
    2460             : };
    2461             : 
    2462             : /***************************************************************************/
    2463             : class MOZ_RAII AutoResolveName
    2464             : {
    2465             : public:
    2466        2876 :     AutoResolveName(XPCCallContext& ccx, JS::HandleId name
    2467             :                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    2468        2876 :         : mContext(ccx.GetContext())
    2469        5752 :         , mOld(ccx, mContext->SetResolveName(name))
    2470             : #ifdef DEBUG
    2471        8628 :         , mCheck(ccx, name)
    2472             : #endif
    2473             :     {
    2474        2876 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    2475        2876 :     }
    2476             : 
    2477        2876 :     ~AutoResolveName()
    2478        2876 :     {
    2479             :         mozilla::DebugOnly<jsid> old =
    2480        5752 :             mContext->SetResolveName(mOld);
    2481        2876 :         MOZ_ASSERT(old == mCheck, "Bad Nesting!");
    2482        2876 :     }
    2483             : 
    2484             : private:
    2485             :     XPCJSContext* mContext;
    2486             :     JS::RootedId mOld;
    2487             : #ifdef DEBUG
    2488             :     JS::RootedId mCheck;
    2489             : #endif
    2490             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    2491             : };
    2492             : 
    2493             : /***************************************************************************/
    2494             : // AutoMarkingPtr is the base class for the various AutoMarking pointer types
    2495             : // below. This system allows us to temporarily protect instances of our garbage
    2496             : // collected types after they are constructed but before they are safely
    2497             : // attached to other rooted objects.
    2498             : // This base class has pure virtual support for marking.
    2499             : 
    2500             : class AutoMarkingPtr
    2501             : {
    2502             :   public:
    2503       23259 :     explicit AutoMarkingPtr(JSContext* cx) {
    2504       23259 :         mRoot = XPCJSContext::Get()->GetAutoRootsAdr();
    2505       23259 :         mNext = *mRoot;
    2506       23259 :         *mRoot = this;
    2507       23259 :     }
    2508             : 
    2509       46518 :     virtual ~AutoMarkingPtr() {
    2510       23259 :         if (mRoot) {
    2511       23259 :             MOZ_ASSERT(*mRoot == this);
    2512       23259 :             *mRoot = mNext;
    2513             :         }
    2514       23259 :     }
    2515             : 
    2516           0 :     void TraceJSAll(JSTracer* trc) {
    2517           0 :         for (AutoMarkingPtr* cur = this; cur; cur = cur->mNext)
    2518           0 :             cur->TraceJS(trc);
    2519           0 :     }
    2520             : 
    2521           0 :     void MarkAfterJSFinalizeAll() {
    2522           0 :         for (AutoMarkingPtr* cur = this; cur; cur = cur->mNext)
    2523           0 :             cur->MarkAfterJSFinalize();
    2524           0 :     }
    2525             : 
    2526             :   protected:
    2527             :     virtual void TraceJS(JSTracer* trc) = 0;
    2528             :     virtual void MarkAfterJSFinalize() = 0;
    2529             : 
    2530             :   private:
    2531             :     AutoMarkingPtr** mRoot;
    2532             :     AutoMarkingPtr* mNext;
    2533             : };
    2534             : 
    2535             : template<class T>
    2536       23258 : class TypedAutoMarkingPtr : public AutoMarkingPtr
    2537             : {
    2538             :   public:
    2539        9829 :     explicit TypedAutoMarkingPtr(JSContext* cx) : AutoMarkingPtr(cx), mPtr(nullptr) {}
    2540       13430 :     TypedAutoMarkingPtr(JSContext* cx, T* ptr) : AutoMarkingPtr(cx), mPtr(ptr) {}
    2541             : 
    2542           0 :     T* get() const { return mPtr; }
    2543       20640 :     operator T*() const { return mPtr; }
    2544        1824 :     T* operator->() const { return mPtr; }
    2545             : 
    2546       10320 :     TypedAutoMarkingPtr<T>& operator =(T* ptr) { mPtr = ptr; return *this; }
    2547             : 
    2548             :   protected:
    2549           0 :     virtual void TraceJS(JSTracer* trc)
    2550             :     {
    2551           0 :         if (mPtr) {
    2552           0 :             mPtr->TraceJS(trc);
    2553           0 :             mPtr->AutoTrace(trc);
    2554             :         }
    2555           0 :     }
    2556             : 
    2557           0 :     virtual void MarkAfterJSFinalize()
    2558             :     {
    2559           0 :         if (mPtr)
    2560           0 :             mPtr->Mark();
    2561           0 :     }
    2562             : 
    2563             :   private:
    2564             :     T* mPtr;
    2565             : };
    2566             : 
    2567             : typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr;
    2568             : typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr;
    2569             : typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
    2570             : 
    2571             : /***************************************************************************/
    2572             : namespace xpc {
    2573             : // Allocates a string that grants all access ("AllAccess")
    2574             : char*
    2575             : CloneAllAccess();
    2576             : 
    2577             : // Returns access if wideName is in list
    2578             : char*
    2579             : CheckAccessList(const char16_t* wideName, const char* const list[]);
    2580             : } /* namespace xpc */
    2581             : 
    2582             : /***************************************************************************/
    2583             : // in xpcvariant.cpp...
    2584             : 
    2585             : // {1809FD50-91E8-11d5-90F9-0010A4E73D9A}
    2586             : #define XPCVARIANT_IID                                                        \
    2587             :     {0x1809fd50, 0x91e8, 0x11d5,                                              \
    2588             :       { 0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
    2589             : 
    2590             : // {DC524540-487E-4501-9AC7-AAA784B17C1C}
    2591             : #define XPCVARIANT_CID                                                        \
    2592             :     {0xdc524540, 0x487e, 0x4501,                                              \
    2593             :       { 0x9a, 0xc7, 0xaa, 0xa7, 0x84, 0xb1, 0x7c, 0x1c } }
    2594             : 
    2595             : class XPCVariant : public nsIVariant
    2596             : {
    2597             : public:
    2598             :     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    2599             :     NS_DECL_NSIVARIANT
    2600          36 :     NS_DECL_CYCLE_COLLECTION_CLASS(XPCVariant)
    2601             : 
    2602             :     // If this class ever implements nsIWritableVariant, take special care with
    2603             :     // the case when mJSVal is JSVAL_STRING, since we don't own the data in
    2604             :     // that case.
    2605             : 
    2606             :     // We #define and iid so that out module local code can use QI to detect
    2607             :     // if a given nsIVariant is in fact an XPCVariant.
    2608             :     NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
    2609             : 
    2610             :     static already_AddRefed<XPCVariant> newVariant(JSContext* cx, const JS::Value& aJSVal);
    2611             : 
    2612             :     /**
    2613             :      * This getter clears the gray bit before handing out the Value if the Value
    2614             :      * represents a JSObject. That means that the object is guaranteed to be
    2615             :      * kept alive past the next CC.
    2616             :      */
    2617           3 :     JS::Value GetJSVal() const {
    2618           3 :         return mJSVal;
    2619             :     }
    2620             : 
    2621             :     /**
    2622             :      * This getter does not change the color of the Value (if it represents a
    2623             :      * JSObject) meaning that the value returned is not guaranteed to be kept
    2624             :      * alive past the next CC.
    2625             :      *
    2626             :      * This should only be called if you are certain that the return value won't
    2627             :      * be passed into a JS API function and that it won't be stored without
    2628             :      * being rooted (or otherwise signaling the stored value to the CC).
    2629             :      */
    2630           4 :     JS::Value GetJSValPreserveColor() const { return mJSVal.unbarrieredGet(); }
    2631             : 
    2632             :     XPCVariant(JSContext* cx, const JS::Value& aJSVal);
    2633             : 
    2634             :     /**
    2635             :      * Convert a variant into a JS::Value.
    2636             :      *
    2637             :      * @param ccx the context for the whole procedure
    2638             :      * @param variant the variant to convert
    2639             :      * @param scope the default scope to put on the new JSObject's parent chain
    2640             :      * @param pErr [out] relevant error code, if any.
    2641             :      * @param pJSVal [out] the resulting jsval.
    2642             :      */
    2643             :     static bool VariantDataToJS(nsIVariant* variant,
    2644             :                                 nsresult* pErr, JS::MutableHandleValue pJSVal);
    2645             : 
    2646           0 :     bool IsPurple()
    2647             :     {
    2648           0 :         return mRefCnt.IsPurple();
    2649             :     }
    2650             : 
    2651           0 :     void RemovePurple()
    2652             :     {
    2653           0 :         mRefCnt.RemovePurple();
    2654           0 :     }
    2655             : 
    2656           0 :     void SetCCGeneration(uint32_t aGen)
    2657             :     {
    2658           0 :         mCCGeneration = aGen;
    2659           0 :     }
    2660             : 
    2661           0 :     uint32_t CCGeneration() { return mCCGeneration; }
    2662             : protected:
    2663           5 :     virtual ~XPCVariant() { }
    2664             : 
    2665             :     bool InitializeData(JSContext* cx);
    2666             : 
    2667             : protected:
    2668             :     nsDiscriminatedUnion mData;
    2669             :     JS::Heap<JS::Value>  mJSVal;
    2670             :     bool                 mReturnRawObject : 1;
    2671             :     uint32_t             mCCGeneration : 31;
    2672             : };
    2673             : 
    2674             : NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID)
    2675             : 
    2676             : class XPCTraceableVariant: public XPCVariant,
    2677             :                            public XPCRootSetElem
    2678             : {
    2679             : public:
    2680           2 :     XPCTraceableVariant(JSContext* cx, const JS::Value& aJSVal)
    2681           2 :         : XPCVariant(cx, aJSVal)
    2682             :     {
    2683           2 :         nsXPConnect::GetRuntimeInstance()->AddVariantRoot(this);
    2684           2 :     }
    2685             : 
    2686             :     virtual ~XPCTraceableVariant();
    2687             : 
    2688             :     void TraceJS(JSTracer* trc);
    2689             : };
    2690             : 
    2691             : /***************************************************************************/
    2692             : // Utilities
    2693             : 
    2694             : inline void*
    2695        5034 : xpc_GetJSPrivate(JSObject* obj)
    2696             : {
    2697        5034 :     return js::GetObjectPrivate(obj);
    2698             : }
    2699             : 
    2700             : inline JSContext*
    2701           9 : xpc_GetSafeJSContext()
    2702             : {
    2703           9 :     return XPCJSContext::Get()->Context();
    2704             : }
    2705             : 
    2706             : namespace xpc {
    2707             : 
    2708             : JSAddonId*
    2709             : NewAddonId(JSContext* cx, const nsACString& id);
    2710             : 
    2711             : // JSNatives to expose atob and btoa in various non-DOM XPConnect scopes.
    2712             : bool
    2713             : Atob(JSContext* cx, unsigned argc, JS::Value* vp);
    2714             : 
    2715             : bool
    2716             : Btoa(JSContext* cx, unsigned argc, JS::Value* vp);
    2717             : 
    2718             : // Helper function that creates a JSFunction that wraps a native function that
    2719             : // forwards the call to the original 'callable'.
    2720             : class FunctionForwarderOptions;
    2721             : bool
    2722             : NewFunctionForwarder(JSContext* cx, JS::HandleId id, JS::HandleObject callable,
    2723             :                      FunctionForwarderOptions& options, JS::MutableHandleValue vp);
    2724             : 
    2725             : // Old fashioned xpc error reporter. Try to use JS_ReportError instead.
    2726             : nsresult
    2727             : ThrowAndFail(nsresult errNum, JSContext* cx, bool* retval);
    2728             : 
    2729             : struct GlobalProperties {
    2730          45 :     GlobalProperties() {
    2731          45 :       mozilla::PodZero(this);
    2732             : 
    2733          45 :     }
    2734             :     bool Parse(JSContext* cx, JS::HandleObject obj);
    2735             :     bool DefineInXPCComponents(JSContext* cx, JS::HandleObject obj);
    2736             :     bool DefineInSandbox(JSContext* cx, JS::HandleObject obj);
    2737             :     bool CSS : 1;
    2738             :     bool indexedDB : 1;
    2739             :     bool XMLHttpRequest : 1;
    2740             :     bool TextDecoder : 1;
    2741             :     bool TextEncoder : 1;
    2742             :     bool URL : 1;
    2743             :     bool URLSearchParams : 1;
    2744             :     bool atob : 1;
    2745             :     bool btoa : 1;
    2746             :     bool Blob : 1;
    2747             :     bool Directory : 1;
    2748             :     bool File : 1;
    2749             :     bool crypto : 1;
    2750             :     bool rtcIdentityProvider : 1;
    2751             :     bool fetch : 1;
    2752             :     bool caches : 1;
    2753             :     bool fileReader: 1;
    2754             :     bool messageChannel: 1;
    2755             : private:
    2756             :     bool Define(JSContext* cx, JS::HandleObject obj);
    2757             : };
    2758             : 
    2759             : // Infallible.
    2760             : already_AddRefed<nsIXPCComponents_utils_Sandbox>
    2761             : NewSandboxConstructor();
    2762             : 
    2763             : // Returns true if class of 'obj' is SandboxClass.
    2764             : bool
    2765             : IsSandbox(JSObject* obj);
    2766             : 
    2767          62 : class MOZ_STACK_CLASS OptionsBase {
    2768             : public:
    2769          62 :     explicit OptionsBase(JSContext* cx = xpc_GetSafeJSContext(),
    2770             :                          JSObject* options = nullptr)
    2771          62 :         : mCx(cx)
    2772          62 :         , mObject(cx, options)
    2773          62 :     { }
    2774             : 
    2775             :     virtual bool Parse() = 0;
    2776             : 
    2777             : protected:
    2778             :     bool ParseValue(const char* name, JS::MutableHandleValue prop, bool* found = nullptr);
    2779             :     bool ParseBoolean(const char* name, bool* prop);
    2780             :     bool ParseObject(const char* name, JS::MutableHandleObject prop);
    2781             :     bool ParseJSString(const char* name, JS::MutableHandleString prop);
    2782             :     bool ParseString(const char* name, nsCString& prop);
    2783             :     bool ParseString(const char* name, nsString& prop);
    2784             :     bool ParseId(const char* name, JS::MutableHandleId id);
    2785             :     bool ParseUInt32(const char* name, uint32_t* prop);
    2786             : 
    2787             :     JSContext* mCx;
    2788             :     JS::RootedObject mObject;
    2789             : };
    2790             : 
    2791          25 : class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
    2792             : public:
    2793          25 :     explicit SandboxOptions(JSContext* cx = xpc_GetSafeJSContext(),
    2794             :                             JSObject* options = nullptr)
    2795          25 :         : OptionsBase(cx, options)
    2796             :         , wantXrays(true)
    2797             :         , allowWaivers(true)
    2798             :         , wantComponents(true)
    2799             :         , wantExportHelpers(false)
    2800             :         , isWebExtensionContentScript(false)
    2801             :         , waiveInterposition(false)
    2802             :         , proto(cx)
    2803             :         , addonId(cx)
    2804             :         , writeToGlobalPrototype(false)
    2805             :         , sameZoneAs(cx)
    2806             :         , freshZone(false)
    2807             :         , invisibleToDebugger(false)
    2808             :         , discardSource(false)
    2809             :         , metadata(cx)
    2810             :         , userContextId(0)
    2811          25 :         , originAttributes(cx)
    2812          25 :     { }
    2813             : 
    2814             :     virtual bool Parse();
    2815             : 
    2816             :     bool wantXrays;
    2817             :     bool allowWaivers;
    2818             :     bool wantComponents;
    2819             :     bool wantExportHelpers;
    2820             :     bool isWebExtensionContentScript;
    2821             :     bool waiveInterposition;
    2822             :     JS::RootedObject proto;
    2823             :     nsCString sandboxName;
    2824             :     JS::RootedString addonId;
    2825             :     bool writeToGlobalPrototype;
    2826             :     JS::RootedObject sameZoneAs;
    2827             :     bool freshZone;
    2828             :     bool invisibleToDebugger;
    2829             :     bool discardSource;
    2830             :     GlobalProperties globalProperties;
    2831             :     JS::RootedValue metadata;
    2832             :     uint32_t userContextId;
    2833             :     JS::RootedObject originAttributes;
    2834             : 
    2835             : protected:
    2836             :     bool ParseGlobalProperties();
    2837             : };
    2838             : 
    2839           0 : class MOZ_STACK_CLASS CreateObjectInOptions : public OptionsBase {
    2840             : public:
    2841           0 :     explicit CreateObjectInOptions(JSContext* cx = xpc_GetSafeJSContext(),
    2842             :                                    JSObject* options = nullptr)
    2843           0 :         : OptionsBase(cx, options)
    2844           0 :         , defineAs(cx, JSID_VOID)
    2845           0 :     { }
    2846             : 
    2847           0 :     virtual bool Parse() { return ParseId("defineAs", &defineAs); }
    2848             : 
    2849             :     JS::RootedId defineAs;
    2850             : };
    2851             : 
    2852           0 : class MOZ_STACK_CLASS ExportFunctionOptions : public OptionsBase {
    2853             : public:
    2854           0 :     explicit ExportFunctionOptions(JSContext* cx = xpc_GetSafeJSContext(),
    2855             :                                    JSObject* options = nullptr)
    2856           0 :         : OptionsBase(cx, options)
    2857             :         , defineAs(cx, JSID_VOID)
    2858           0 :         , allowCrossOriginArguments(false)
    2859           0 :     { }
    2860             : 
    2861           0 :     virtual bool Parse() {
    2862           0 :         return ParseId("defineAs", &defineAs) &&
    2863           0 :                ParseBoolean("allowCrossOriginArguments", &allowCrossOriginArguments);
    2864             :     }
    2865             : 
    2866             :     JS::RootedId defineAs;
    2867             :     bool allowCrossOriginArguments;
    2868             : };
    2869             : 
    2870           0 : class MOZ_STACK_CLASS FunctionForwarderOptions : public OptionsBase {
    2871             : public:
    2872           0 :     explicit FunctionForwarderOptions(JSContext* cx = xpc_GetSafeJSContext(),
    2873             :                                       JSObject* options = nullptr)
    2874           0 :         : OptionsBase(cx, options)
    2875           0 :         , allowCrossOriginArguments(false)
    2876           0 :     { }
    2877             : 
    2878           0 :     JSObject* ToJSObject(JSContext* cx) {
    2879           0 :         JS::RootedObject obj(cx, JS_NewObjectWithGivenProto(cx, nullptr, nullptr));
    2880           0 :         if (!obj)
    2881           0 :             return nullptr;
    2882             : 
    2883           0 :         JS::RootedValue val(cx);
    2884           0 :         unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
    2885           0 :         val = JS::BooleanValue(allowCrossOriginArguments);
    2886           0 :         if (!JS_DefineProperty(cx, obj, "allowCrossOriginArguments", val, attrs))
    2887           0 :             return nullptr;
    2888             : 
    2889           0 :         return obj;
    2890             :     }
    2891             : 
    2892           0 :     virtual bool Parse() {
    2893           0 :         return ParseBoolean("allowCrossOriginArguments", &allowCrossOriginArguments);
    2894             :     }
    2895             : 
    2896             :     bool allowCrossOriginArguments;
    2897             : };
    2898             : 
    2899           4 : class MOZ_STACK_CLASS StackScopedCloneOptions : public OptionsBase {
    2900             : public:
    2901           4 :     explicit StackScopedCloneOptions(JSContext* cx = xpc_GetSafeJSContext(),
    2902             :                                      JSObject* options = nullptr)
    2903           4 :         : OptionsBase(cx, options)
    2904             :         , wrapReflectors(false)
    2905             :         , cloneFunctions(false)
    2906           4 :         , deepFreeze(false)
    2907           4 :     { }
    2908             : 
    2909           0 :     virtual bool Parse() {
    2910           0 :         return ParseBoolean("wrapReflectors", &wrapReflectors) &&
    2911           0 :                ParseBoolean("cloneFunctions", &cloneFunctions) &&
    2912           0 :                ParseBoolean("deepFreeze", &deepFreeze);
    2913             :     }
    2914             : 
    2915             :     // When a reflector is encountered, wrap it rather than aborting the clone.
    2916             :     bool wrapReflectors;
    2917             : 
    2918             :     // When a function is encountered, clone it (exportFunction-style) rather than
    2919             :     // aborting the clone.
    2920             :     bool cloneFunctions;
    2921             : 
    2922             :     // If true, the resulting object is deep-frozen after being cloned.
    2923             :     bool deepFreeze;
    2924             : };
    2925             : 
    2926             : JSObject*
    2927             : CreateGlobalObject(JSContext* cx, const JSClass* clasp, nsIPrincipal* principal,
    2928             :                    JS::CompartmentOptions& aOptions);
    2929             : 
    2930             : // Modify the provided compartment options, consistent with |aPrincipal| and
    2931             : // with globally-cached values of various preferences.
    2932             : //
    2933             : // Call this function *before* |aOptions| is used to create the corresponding
    2934             : // global object, as not all of the options it sets can be modified on an
    2935             : // existing global object.  (The type system should make this obvious, because
    2936             : // you can't get a *mutable* JS::CompartmentOptions& from an existing global
    2937             : // object.)
    2938             : void
    2939             : InitGlobalObjectOptions(JS::CompartmentOptions& aOptions,
    2940             :                         nsIPrincipal* aPrincipal);
    2941             : 
    2942             : // Finish initializing an already-created, not-yet-exposed-to-script global
    2943             : // object.  This will attach a Components object (if necessary) and call
    2944             : // |JS_FireOnNewGlobalObject| (if necessary).
    2945             : //
    2946             : // If you must modify compartment options, see InitGlobalObjectOptions above.
    2947             : bool
    2948             : InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal,
    2949             :                  uint32_t aFlags);
    2950             : 
    2951             : // Helper for creating a sandbox object to use for evaluating
    2952             : // untrusted code completely separated from all other code in the
    2953             : // system using EvalInSandbox(). Takes the JSContext on which to
    2954             : // do setup etc on, puts the sandbox object in *vp (which must be
    2955             : // rooted by the caller), and uses the principal that's either
    2956             : // directly passed in prinOrSop or indirectly as an
    2957             : // nsIScriptObjectPrincipal holding the principal. If no principal is
    2958             : // reachable through prinOrSop, a new null principal will be created
    2959             : // and used.
    2960             : nsresult
    2961             : CreateSandboxObject(JSContext* cx, JS::MutableHandleValue vp, nsISupports* prinOrSop,
    2962             :                     xpc::SandboxOptions& options);
    2963             : // Helper for evaluating scripts in a sandbox object created with
    2964             : // CreateSandboxObject(). The caller is responsible of ensuring
    2965             : // that *rval doesn't get collected during the call or usage after the
    2966             : // call. This helper will use filename and lineNo for error reporting,
    2967             : // and if no filename is provided it will use the codebase from the
    2968             : // principal and line number 1 as a fallback.
    2969             : nsresult
    2970             : EvalInSandbox(JSContext* cx, JS::HandleObject sandbox, const nsAString& source,
    2971             :               const nsACString& filename, int32_t lineNo,
    2972             :               JSVersion jsVersion, JS::MutableHandleValue rval);
    2973             : 
    2974             : nsresult
    2975             : GetSandboxAddonId(JSContext* cx, JS::HandleObject sandboxArg,
    2976             :                   JS::MutableHandleValue rval);
    2977             : 
    2978             : // Helper for retrieving metadata stored in a reserved slot. The metadata
    2979             : // is set during the sandbox creation using the "metadata" option.
    2980             : nsresult
    2981             : GetSandboxMetadata(JSContext* cx, JS::HandleObject sandboxArg,
    2982             :                    JS::MutableHandleValue rval);
    2983             : 
    2984             : nsresult
    2985             : SetSandboxMetadata(JSContext* cx, JS::HandleObject sandboxArg,
    2986             :                    JS::HandleValue metadata);
    2987             : 
    2988             : bool
    2989             : CreateObjectIn(JSContext* cx, JS::HandleValue vobj, CreateObjectInOptions& options,
    2990             :                JS::MutableHandleValue rval);
    2991             : 
    2992             : bool
    2993             : EvalInWindow(JSContext* cx, const nsAString& source, JS::HandleObject scope,
    2994             :              JS::MutableHandleValue rval);
    2995             : 
    2996             : bool
    2997             : ExportFunction(JSContext* cx, JS::HandleValue vscope, JS::HandleValue vfunction,
    2998             :                JS::HandleValue voptions, JS::MutableHandleValue rval);
    2999             : 
    3000             : bool
    3001             : CloneInto(JSContext* cx, JS::HandleValue vobj, JS::HandleValue vscope,
    3002             :           JS::HandleValue voptions, JS::MutableHandleValue rval);
    3003             : 
    3004             : bool
    3005             : StackScopedClone(JSContext* cx, StackScopedCloneOptions& options, JS::MutableHandleValue val);
    3006             : 
    3007             : } /* namespace xpc */
    3008             : 
    3009             : 
    3010             : /***************************************************************************/
    3011             : // Inlined utilities.
    3012             : 
    3013             : inline bool
    3014             : xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid id);
    3015             : 
    3016             : inline jsid
    3017             : GetJSIDByIndex(JSContext* cx, unsigned index);
    3018             : 
    3019             : namespace xpc {
    3020             : 
    3021             : enum WrapperDenialType {
    3022             :     WrapperDenialForXray = 0,
    3023             :     WrapperDenialForCOW,
    3024             :     WrapperDenialTypeCount
    3025             : };
    3026             : bool ReportWrapperDenial(JSContext* cx, JS::HandleId id, WrapperDenialType type, const char* reason);
    3027             : 
    3028             : class CompartmentPrivate
    3029             : {
    3030             : public:
    3031             :     enum LocationHint {
    3032             :         LocationHintRegular,
    3033             :         LocationHintAddon
    3034             :     };
    3035             : 
    3036             :     explicit CompartmentPrivate(JSCompartment* c);
    3037             : 
    3038             :     ~CompartmentPrivate();
    3039             : 
    3040      153444 :     static CompartmentPrivate* Get(JSCompartment* compartment)
    3041             :     {
    3042      153444 :         MOZ_ASSERT(compartment);
    3043      153444 :         void* priv = JS_GetCompartmentPrivate(compartment);
    3044      153444 :         return static_cast<CompartmentPrivate*>(priv);
    3045             :     }
    3046             : 
    3047       21737 :     static CompartmentPrivate* Get(JSObject* object)
    3048             :     {
    3049       21737 :         JSCompartment* compartment = js::GetObjectCompartment(object);
    3050       21737 :         return Get(compartment);
    3051             :     }
    3052             : 
    3053             :     // Controls whether this compartment gets Xrays to same-origin. This behavior
    3054             :     // is deprecated, but is still the default for sandboxes for compatibity
    3055             :     // reasons.
    3056             :     bool wantXrays;
    3057             : 
    3058             :     // Controls whether this compartment is allowed to waive Xrays to content
    3059             :     // that it subsumes. This should generally be true, except in cases where we
    3060             :     // want to prevent code from depending on Xray Waivers (which might make it
    3061             :     // more portable to other browser architectures).
    3062             :     bool allowWaivers;
    3063             : 
    3064             :     // This flag is intended for a very specific use, internal to Gecko. It may
    3065             :     // go away or change behavior at any time. It should not be added to any
    3066             :     // documentation and it should not be used without consulting the XPConnect
    3067             :     // module owner.
    3068             :     bool writeToGlobalPrototype;
    3069             : 
    3070             :     // When writeToGlobalPrototype is true, we use this flag to temporarily
    3071             :     // disable the writeToGlobalPrototype behavior (when resolving standard
    3072             :     // classes, for example).
    3073             :     bool skipWriteToGlobalPrototype;
    3074             : 
    3075             :     // This scope corresponds to a WebExtension content script, and receives
    3076             :     // various bits of special compatibility behavior.
    3077             :     bool isWebExtensionContentScript;
    3078             : 
    3079             :     // Even if an add-on needs interposition, it does not necessary need it
    3080             :     // for every scope. If this flag is set we waive interposition for this
    3081             :     // scope.
    3082             :     bool waiveInterposition;
    3083             : 
    3084             :     // If CPOWs are disabled for browser code via the
    3085             :     // dom.ipc.cpows.forbid-unsafe-from-browser preferences, then only
    3086             :     // add-ons can use CPOWs. This flag allows a non-addon scope
    3087             :     // to opt into CPOWs. It's necessary for the implementation of
    3088             :     // RemoteAddonsParent.jsm.
    3089             :     bool allowCPOWs;
    3090             : 
    3091             :     // This is only ever set during mochitest runs when enablePrivilege is called.
    3092             :     // It's intended as a temporary stopgap measure until we can finish ripping out
    3093             :     // enablePrivilege. Once set, this value is never unset (i.e., it doesn't follow
    3094             :     // the old scoping rules of enablePrivilege).
    3095             :     //
    3096             :     // Using it in production is inherently unsafe.
    3097             :     bool universalXPConnectEnabled;
    3098             : 
    3099             :     // This is only ever set during mochitest runs when enablePrivilege is called.
    3100             :     // It allows the SpecialPowers scope to waive the normal chrome security
    3101             :     // wrappers and expose properties directly to content. This lets us avoid a
    3102             :     // bunch of overhead and complexity in our SpecialPowers automation glue.
    3103             :     //
    3104             :     // Using it in production is inherently unsafe.
    3105             :     bool forcePermissiveCOWs;
    3106             : 
    3107             :     // True if this compartment has been nuked. If true, any wrappers into or
    3108             :     // out of it should be considered invalid.
    3109             :     bool wasNuked;
    3110             : 
    3111             :     // Whether we've emitted a warning about a property that was filtered out
    3112             :     // by a security wrapper. See XrayWrapper.cpp.
    3113             :     bool wrapperDenialWarnings[WrapperDenialTypeCount];
    3114             : 
    3115             :     // The scriptability of this compartment.
    3116             :     Scriptability scriptability;
    3117             : 
    3118             :     // Our XPCWrappedNativeScope. This is non-null if and only if this is an
    3119             :     // XPConnect compartment.
    3120             :     XPCWrappedNativeScope* scope;
    3121             : 
    3122           0 :     const nsACString& GetLocation() {
    3123           0 :         if (location.IsEmpty() && locationURI) {
    3124             : 
    3125             :             nsCOMPtr<nsIXPConnectWrappedJS> jsLocationURI =
    3126           0 :                  do_QueryInterface(locationURI);
    3127           0 :             if (jsLocationURI) {
    3128             :                 // We cannot call into JS-implemented nsIURI objects, because
    3129             :                 // we are iterating over the JS heap at this point.
    3130             :                 location =
    3131           0 :                     NS_LITERAL_CSTRING("<JS-implemented nsIURI location>");
    3132           0 :             } else if (NS_FAILED(locationURI->GetSpec(location))) {
    3133           0 :                 location = NS_LITERAL_CSTRING("<unknown location>");
    3134             :             }
    3135             :         }
    3136           0 :         return location;
    3137             :     }
    3138             :     bool GetLocationURI(nsIURI** aURI) {
    3139             :         return GetLocationURI(LocationHintRegular, aURI);
    3140             :     }
    3141           0 :     bool GetLocationURI(LocationHint aLocationHint, nsIURI** aURI) {
    3142           0 :         if (locationURI) {
    3143           0 :             nsCOMPtr<nsIURI> rval = locationURI;
    3144           0 :             rval.forget(aURI);
    3145           0 :             return true;
    3146             :         }
    3147           0 :         return TryParseLocationURI(aLocationHint, aURI);
    3148             :     }
    3149         285 :     void SetLocation(const nsACString& aLocation) {
    3150         285 :         if (aLocation.IsEmpty())
    3151           0 :             return;
    3152         285 :         if (!location.IsEmpty() || locationURI)
    3153           0 :             return;
    3154         285 :         location = aLocation;
    3155             :     }
    3156           7 :     void SetLocationURI(nsIURI* aLocationURI) {
    3157           7 :         if (!aLocationURI)
    3158           0 :             return;
    3159           7 :         if (locationURI)
    3160           0 :             return;
    3161           7 :         locationURI = aLocationURI;
    3162             :     }
    3163             : 
    3164       51288 :     JSObject2WrappedJSMap* GetWrappedJSMap() const { return mWrappedJSMap; }
    3165             :     void UpdateWeakPointersAfterGC();
    3166             : 
    3167             :     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
    3168             : 
    3169             : private:
    3170             :     nsCString location;
    3171             :     nsCOMPtr<nsIURI> locationURI;
    3172             :     JSObject2WrappedJSMap* mWrappedJSMap;
    3173             : 
    3174             :     bool TryParseLocationURI(LocationHint aType, nsIURI** aURI);
    3175             : };
    3176             : 
    3177             : bool IsUniversalXPConnectEnabled(JSCompartment* compartment);
    3178             : bool IsUniversalXPConnectEnabled(JSContext* cx);
    3179             : bool EnableUniversalXPConnect(JSContext* cx);
    3180             : 
    3181             : inline void
    3182           2 : CrashIfNotInAutomation()
    3183             : {
    3184           2 :     MOZ_RELEASE_ASSERT(IsInAutomation());
    3185           2 : }
    3186             : 
    3187             : inline XPCWrappedNativeScope*
    3188       15039 : ObjectScope(JSObject* obj)
    3189             : {
    3190       15039 :     return CompartmentPrivate::Get(obj)->scope;
    3191             : }
    3192             : 
    3193             : JSObject* NewOutObject(JSContext* cx);
    3194             : bool IsOutObject(JSContext* cx, JSObject* obj);
    3195             : 
    3196             : nsresult HasInstance(JSContext* cx, JS::HandleObject objArg, const nsID* iid, bool* bp);
    3197             : 
    3198             : nsIPrincipal* GetObjectPrincipal(JSObject* obj);
    3199             : 
    3200             : } // namespace xpc
    3201             : 
    3202             : namespace mozilla {
    3203             : namespace dom {
    3204             : extern bool
    3205             : DefineStaticJSVals(JSContext* cx);
    3206             : } // namespace dom
    3207             : } // namespace mozilla
    3208             : 
    3209             : bool
    3210             : xpc_LocalizeContext(JSContext* cx);
    3211             : void
    3212             : xpc_DelocalizeContext(JSContext* cx);
    3213             : 
    3214             : /***************************************************************************/
    3215             : // Inlines use the above - include last.
    3216             : 
    3217             : #include "XPCInlines.h"
    3218             : 
    3219             : /***************************************************************************/
    3220             : // Maps have inlines that use the above - include last.
    3221             : 
    3222             : #include "XPCMaps.h"
    3223             : 
    3224             : /***************************************************************************/
    3225             : 
    3226             : #endif /* xpcprivate_h___ */

Generated by: LCOV version 1.13