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

Generated by: LCOV version 1.13-14-ga5dd952