js/xpconnect/src/xpcprivate.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/xpconnect/src/xpcprivate.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3650 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=99: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/*
    1.11 + * XPConnect allows JS code to manipulate C++ object and C++ code to manipulate
    1.12 + * JS objects. JS manipulation of C++ objects tends to be significantly more
    1.13 + * complex. This comment explains how it is orchestrated by XPConnect.
    1.14 + *
    1.15 + * For each C++ object to be manipulated in JS, there is a corresponding JS
    1.16 + * object. This is called the "flattened JS object". By default, there is an
    1.17 + * additional C++ object involved of type XPCWrappedNative. The XPCWrappedNative
    1.18 + * holds pointers to the C++ object and the flat JS object.
    1.19 + *
    1.20 + * All XPCWrappedNative objects belong to an XPCWrappedNativeScope. These scopes
    1.21 + * are essentially in 1:1 correspondence with JS global objects. The
    1.22 + * XPCWrappedNativeScope has a pointer to the JS global object. The parent of a
    1.23 + * flattened JS object is, by default, the global JS object corresponding to the
    1.24 + * wrapper's XPCWrappedNativeScope (the exception to this rule is when a
    1.25 + * PreCreate hook asks for a different parent; see nsIXPCScriptable below).
    1.26 + *
    1.27 + * Some C++ objects (notably DOM objects) have information associated with them
    1.28 + * that lists the interfaces implemented by these objects. A C++ object exposes
    1.29 + * this information by implementing nsIClassInfo. If a C++ object implements
    1.30 + * nsIClassInfo, then JS code can call its methods without needing to use
    1.31 + * QueryInterface first. Typically, all instances of a C++ class share the same
    1.32 + * nsIClassInfo instance. (That is, obj->QueryInterface(nsIClassInfo) returns
    1.33 + * the same result for every obj of a given class.)
    1.34 + *
    1.35 + * XPConnect tracks nsIClassInfo information in an XPCWrappedNativeProto object.
    1.36 + * A given XPCWrappedNativeScope will have one XPCWrappedNativeProto for each
    1.37 + * nsIClassInfo instance being used. The XPCWrappedNativeProto has an associated
    1.38 + * JS object, which is used as the prototype of all flattened JS objects created
    1.39 + * for C++ objects with the given nsIClassInfo.
    1.40 + *
    1.41 + * Each XPCWrappedNativeProto has a pointer to its XPCWrappedNativeScope. If an
    1.42 + * XPCWrappedNative wraps a C++ object with class info, then it points to its
    1.43 + * XPCWrappedNativeProto. Otherwise it points to its XPCWrappedNativeScope. (The
    1.44 + * pointers are smooshed together in a tagged union.) Either way it can reach
    1.45 + * its scope.
    1.46 + *
    1.47 + * An XPCWrappedNativeProto keeps track of the set of interfaces implemented by
    1.48 + * the C++ object in an XPCNativeSet. (The list of interfaces is obtained by
    1.49 + * calling a method on the nsIClassInfo.) An XPCNativeSet is a collection of
    1.50 + * XPCNativeInterfaces. Each interface stores the list of members, which can be
    1.51 + * methods, constants, getters, or setters.
    1.52 + *
    1.53 + * An XPCWrappedNative also points to an XPCNativeSet. Initially this starts out
    1.54 + * the same as the XPCWrappedNativeProto's set. If there is no proto, it starts
    1.55 + * out as a singleton set containing nsISupports. If JS code QI's new interfaces
    1.56 + * outside of the existing set, the set will grow. All QueryInterface results
    1.57 + * are cached in XPCWrappedNativeTearOff objects, which are linked off of the
    1.58 + * XPCWrappedNative.
    1.59 + *
    1.60 + * Besides having class info, a C++ object may be "scriptable" (i.e., implement
    1.61 + * nsIXPCScriptable). This allows it to implement a more DOM-like interface,
    1.62 + * besides just exposing XPCOM methods and constants. An nsIXPCScriptable
    1.63 + * instance has hooks that correspond to all the normal JSClass hooks. Each
    1.64 + * nsIXPCScriptable instance is mirrored by an XPCNativeScriptableInfo in
    1.65 + * XPConnect. These can have pointers from XPCWrappedNativeProto and
    1.66 + * XPCWrappedNative (since C++ objects can have scriptable info without having
    1.67 + * class info).
    1.68 + *
    1.69 + * Most data in an XPCNativeScriptableInfo is shared between instances. The
    1.70 + * shared data is stored in an XPCNativeScriptableShared object. This type is
    1.71 + * important because it holds the JSClass of the flattened JS objects with the
    1.72 + * given scriptable info.
    1.73 + */
    1.74 +
    1.75 +/* All the XPConnect private declarations - only include locally. */
    1.76 +
    1.77 +#ifndef xpcprivate_h___
    1.78 +#define xpcprivate_h___
    1.79 +
    1.80 +#include "mozilla/Alignment.h"
    1.81 +#include "mozilla/Assertions.h"
    1.82 +#include "mozilla/Attributes.h"
    1.83 +#include "mozilla/CycleCollectedJSRuntime.h"
    1.84 +#include "mozilla/GuardObjects.h"
    1.85 +#include "mozilla/Maybe.h"
    1.86 +#include "mozilla/MemoryReporting.h"
    1.87 +#include "mozilla/TimeStamp.h"
    1.88 +
    1.89 +#include <math.h>
    1.90 +#include <stdint.h>
    1.91 +#include <stdlib.h>
    1.92 +#include <string.h>
    1.93 +
    1.94 +#include "xpcpublic.h"
    1.95 +#include "js/TracingAPI.h"
    1.96 +#include "js/WeakMapPtr.h"
    1.97 +#include "pldhash.h"
    1.98 +#include "nscore.h"
    1.99 +#include "nsXPCOM.h"
   1.100 +#include "nsAutoPtr.h"
   1.101 +#include "nsCycleCollectionParticipant.h"
   1.102 +#include "nsDebug.h"
   1.103 +#include "nsISupports.h"
   1.104 +#include "nsIServiceManager.h"
   1.105 +#include "nsIClassInfoImpl.h"
   1.106 +#include "nsIComponentManager.h"
   1.107 +#include "nsIComponentRegistrar.h"
   1.108 +#include "nsISupportsPrimitives.h"
   1.109 +#include "nsMemory.h"
   1.110 +#include "nsIXPConnect.h"
   1.111 +#include "nsIInterfaceInfo.h"
   1.112 +#include "nsIXPCScriptable.h"
   1.113 +#include "nsIXPCSecurityManager.h"
   1.114 +#include "nsIJSRuntimeService.h"
   1.115 +#include "nsWeakReference.h"
   1.116 +#include "nsCOMPtr.h"
   1.117 +#include "nsXPTCUtils.h"
   1.118 +#include "xptinfo.h"
   1.119 +#include "XPCForwards.h"
   1.120 +#include "XPCLog.h"
   1.121 +#include "xpccomponents.h"
   1.122 +#include "xpcexception.h"
   1.123 +#include "xpcjsid.h"
   1.124 +#include "prenv.h"
   1.125 +#include "prclist.h"
   1.126 +#include "prcvar.h"
   1.127 +#include "nsString.h"
   1.128 +#include "nsReadableUtils.h"
   1.129 +#include "nsXPIDLString.h"
   1.130 +#include "nsAutoJSValHolder.h"
   1.131 +
   1.132 +#include "MainThreadUtils.h"
   1.133 +
   1.134 +#include "nsIConsoleService.h"
   1.135 +#include "nsIScriptError.h"
   1.136 +#include "nsIException.h"
   1.137 +
   1.138 +#include "nsVariant.h"
   1.139 +#include "nsIPropertyBag.h"
   1.140 +#include "nsIProperty.h"
   1.141 +#include "nsCOMArray.h"
   1.142 +#include "nsTArray.h"
   1.143 +#include "nsBaseHashtable.h"
   1.144 +#include "nsHashKeys.h"
   1.145 +#include "nsWrapperCache.h"
   1.146 +#include "nsStringBuffer.h"
   1.147 +#include "nsDataHashtable.h"
   1.148 +#include "nsDeque.h"
   1.149 +
   1.150 +#include "nsIScriptSecurityManager.h"
   1.151 +#include "nsNetUtil.h"
   1.152 +
   1.153 +#include "nsIPrincipal.h"
   1.154 +#include "nsJSPrincipals.h"
   1.155 +#include "nsIScriptObjectPrincipal.h"
   1.156 +#include "xpcObjectHelper.h"
   1.157 +#include "nsIThreadInternal.h"
   1.158 +
   1.159 +#include "SandboxPrivate.h"
   1.160 +#include "BackstagePass.h"
   1.161 +#include "nsCxPusher.h"
   1.162 +#include "nsAXPCNativeCallContext.h"
   1.163 +
   1.164 +#ifdef XP_WIN
   1.165 +// Nasty MS defines
   1.166 +#ifdef GetClassInfo
   1.167 +#undef GetClassInfo
   1.168 +#endif
   1.169 +#ifdef GetClassName
   1.170 +#undef GetClassName
   1.171 +#endif
   1.172 +#endif /* XP_WIN */
   1.173 +
   1.174 +#include "nsINode.h"
   1.175 +
   1.176 +/***************************************************************************/
   1.177 +// default initial sizes for maps (hashtables)
   1.178 +
   1.179 +#define XPC_CONTEXT_MAP_SIZE                16
   1.180 +#define XPC_JS_MAP_SIZE                     64
   1.181 +#define XPC_JS_CLASS_MAP_SIZE               64
   1.182 +
   1.183 +#define XPC_NATIVE_MAP_SIZE                 64
   1.184 +#define XPC_NATIVE_PROTO_MAP_SIZE           16
   1.185 +#define XPC_DYING_NATIVE_PROTO_MAP_SIZE     16
   1.186 +#define XPC_DETACHED_NATIVE_PROTO_MAP_SIZE  32
   1.187 +#define XPC_NATIVE_INTERFACE_MAP_SIZE       64
   1.188 +#define XPC_NATIVE_SET_MAP_SIZE             64
   1.189 +#define XPC_NATIVE_JSCLASS_MAP_SIZE         32
   1.190 +#define XPC_THIS_TRANSLATOR_MAP_SIZE         8
   1.191 +#define XPC_NATIVE_WRAPPER_MAP_SIZE         16
   1.192 +#define XPC_WRAPPER_MAP_SIZE                16
   1.193 +
   1.194 +/***************************************************************************/
   1.195 +// data declarations...
   1.196 +extern const char XPC_CONTEXT_STACK_CONTRACTID[];
   1.197 +extern const char XPC_RUNTIME_CONTRACTID[];
   1.198 +extern const char XPC_EXCEPTION_CONTRACTID[];
   1.199 +extern const char XPC_CONSOLE_CONTRACTID[];
   1.200 +extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
   1.201 +extern const char XPC_ID_CONTRACTID[];
   1.202 +extern const char XPC_XPCONNECT_CONTRACTID[];
   1.203 +
   1.204 +/***************************************************************************/
   1.205 +// Useful macros...
   1.206 +
   1.207 +#define XPC_STRING_GETTER_BODY(dest, src)                                     \
   1.208 +    NS_ENSURE_ARG_POINTER(dest);                                              \
   1.209 +    char* result;                                                             \
   1.210 +    if (src)                                                                  \
   1.211 +        result = (char*) nsMemory::Clone(src,                                 \
   1.212 +                                         sizeof(char)*(strlen(src)+1));       \
   1.213 +    else                                                                      \
   1.214 +        result = nullptr;                                                      \
   1.215 +    *dest = result;                                                           \
   1.216 +    return (result || !src) ? NS_OK : NS_ERROR_OUT_OF_MEMORY
   1.217 +
   1.218 +
   1.219 +#define WRAPPER_SLOTS (JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS )
   1.220 +
   1.221 +#define INVALID_OBJECT ((JSObject *)1)
   1.222 +
   1.223 +// If IS_WN_CLASS for the JSClass of an object is true, the object is a
   1.224 +// wrappednative wrapper, holding the XPCWrappedNative in its private slot.
   1.225 +static inline bool IS_WN_CLASS(const js::Class* clazz)
   1.226 +{
   1.227 +    return clazz->ext.isWrappedNative;
   1.228 +}
   1.229 +
   1.230 +static inline bool IS_WN_REFLECTOR(JSObject *obj)
   1.231 +{
   1.232 +    return IS_WN_CLASS(js::GetObjectClass(obj));
   1.233 +}
   1.234 +
   1.235 +/***************************************************************************
   1.236 +****************************************************************************
   1.237 +*
   1.238 +* Core runtime and context classes...
   1.239 +*
   1.240 +****************************************************************************
   1.241 +***************************************************************************/
   1.242 +
   1.243 +// We have a general rule internally that getters that return addref'd interface
   1.244 +// pointer generally do so using an 'out' parm. When interface pointers are
   1.245 +// returned as function call result values they are not addref'd. Exceptions
   1.246 +// to this rule are noted explicitly.
   1.247 +
   1.248 +inline bool
   1.249 +AddToCCKind(JSGCTraceKind kind)
   1.250 +{
   1.251 +    return kind == JSTRACE_OBJECT || kind == JSTRACE_SCRIPT;
   1.252 +}
   1.253 +
   1.254 +class nsXPConnect : public nsIXPConnect,
   1.255 +                    public nsIThreadObserver,
   1.256 +                    public nsSupportsWeakReference,
   1.257 +                    public nsIJSRuntimeService
   1.258 +{
   1.259 +public:
   1.260 +    // all the interface method declarations...
   1.261 +    NS_DECL_ISUPPORTS
   1.262 +    NS_DECL_NSIXPCONNECT
   1.263 +    NS_DECL_NSITHREADOBSERVER
   1.264 +    NS_DECL_NSIJSRUNTIMESERVICE
   1.265 +
   1.266 +    // non-interface implementation
   1.267 +public:
   1.268 +    // These get non-addref'd pointers
   1.269 +    static nsXPConnect*  XPConnect()
   1.270 +    {
   1.271 +        // Do a release-mode assert that we're not doing anything significant in
   1.272 +        // XPConnect off the main thread. If you're an extension developer hitting
   1.273 +        // this, you need to change your code. See bug 716167.
   1.274 +        if (!MOZ_LIKELY(NS_IsMainThread()))
   1.275 +            MOZ_CRASH();
   1.276 +
   1.277 +        return gSelf;
   1.278 +    }
   1.279 +
   1.280 +    static XPCJSRuntime* GetRuntimeInstance();
   1.281 +    XPCJSRuntime* GetRuntime() {return mRuntime;}
   1.282 +
   1.283 +    static bool IsISupportsDescendant(nsIInterfaceInfo* info);
   1.284 +
   1.285 +    nsIXPCSecurityManager* GetDefaultSecurityManager() const
   1.286 +    {
   1.287 +        // mDefaultSecurityManager is main-thread only.
   1.288 +        if (!NS_IsMainThread()) {
   1.289 +            return nullptr;
   1.290 +        }
   1.291 +        return mDefaultSecurityManager;
   1.292 +    }
   1.293 +
   1.294 +    // This returns an AddRef'd pointer. It does not do this with an 'out' param
   1.295 +    // only because this form is required by the generic module macro:
   1.296 +    // NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
   1.297 +    static nsXPConnect* GetSingleton();
   1.298 +
   1.299 +    // Called by module code in dll startup
   1.300 +    static void InitStatics();
   1.301 +    // Called by module code on dll shutdown.
   1.302 +    static void ReleaseXPConnectSingleton();
   1.303 +
   1.304 +    virtual ~nsXPConnect();
   1.305 +
   1.306 +    bool IsShuttingDown() const {return mShuttingDown;}
   1.307 +
   1.308 +    nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
   1.309 +    nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
   1.310 +
   1.311 +    virtual nsIPrincipal* GetPrincipal(JSObject* obj,
   1.312 +                                       bool allowShortCircuit) const;
   1.313 +
   1.314 +    void RecordTraversal(void *p, nsISupports *s);
   1.315 +    virtual char* DebugPrintJSStack(bool showArgs,
   1.316 +                                    bool showLocals,
   1.317 +                                    bool showThisProps);
   1.318 +
   1.319 +
   1.320 +    static bool ReportAllJSExceptions()
   1.321 +    {
   1.322 +      return gReportAllJSExceptions > 0;
   1.323 +    }
   1.324 +
   1.325 +    static void CheckForDebugMode(JSRuntime *rt);
   1.326 +
   1.327 +protected:
   1.328 +    nsXPConnect();
   1.329 +
   1.330 +private:
   1.331 +    // Singleton instance
   1.332 +    static nsXPConnect*             gSelf;
   1.333 +    static bool                     gOnceAliveNowDead;
   1.334 +
   1.335 +    XPCJSRuntime*                   mRuntime;
   1.336 +    nsRefPtr<nsIXPCSecurityManager> mDefaultSecurityManager;
   1.337 +    bool                            mShuttingDown;
   1.338 +
   1.339 +    // nsIThreadInternal doesn't remember which observers it called
   1.340 +    // OnProcessNextEvent on when it gets around to calling AfterProcessNextEvent.
   1.341 +    // So if XPConnect gets initialized mid-event (which can happen), we'll get
   1.342 +    // an 'after' notification without getting an 'on' notification. If we don't
   1.343 +    // watch out for this, we'll do an unmatched |pop| on the context stack.
   1.344 +    uint16_t                 mEventDepth;
   1.345 +
   1.346 +    static uint32_t gReportAllJSExceptions;
   1.347 +
   1.348 +public:
   1.349 +    static nsIScriptSecurityManager *gScriptSecurityManager;
   1.350 +};
   1.351 +
   1.352 +/***************************************************************************/
   1.353 +
   1.354 +class XPCRootSetElem
   1.355 +{
   1.356 +public:
   1.357 +    XPCRootSetElem()
   1.358 +    {
   1.359 +#ifdef DEBUG
   1.360 +        mNext = nullptr;
   1.361 +        mSelfp = nullptr;
   1.362 +#endif
   1.363 +    }
   1.364 +
   1.365 +    ~XPCRootSetElem()
   1.366 +    {
   1.367 +        MOZ_ASSERT(!mNext, "Must be unlinked");
   1.368 +        MOZ_ASSERT(!mSelfp, "Must be unlinked");
   1.369 +    }
   1.370 +
   1.371 +    inline XPCRootSetElem* GetNextRoot() { return mNext; }
   1.372 +    void AddToRootSet(XPCRootSetElem **listHead);
   1.373 +    void RemoveFromRootSet();
   1.374 +
   1.375 +private:
   1.376 +    XPCRootSetElem *mNext;
   1.377 +    XPCRootSetElem **mSelfp;
   1.378 +};
   1.379 +
   1.380 +/***************************************************************************/
   1.381 +
   1.382 +// In the current xpconnect system there can only be one XPCJSRuntime.
   1.383 +// So, xpconnect can only be used on one JSRuntime within the process.
   1.384 +
   1.385 +class XPCJSContextStack;
   1.386 +class WatchdogManager;
   1.387 +
   1.388 +enum WatchdogTimestampCategory
   1.389 +{
   1.390 +    TimestampRuntimeStateChange = 0,
   1.391 +    TimestampWatchdogWakeup,
   1.392 +    TimestampWatchdogHibernateStart,
   1.393 +    TimestampWatchdogHibernateStop,
   1.394 +    TimestampCount
   1.395 +};
   1.396 +
   1.397 +class AsyncFreeSnowWhite;
   1.398 +
   1.399 +class XPCJSRuntime : public mozilla::CycleCollectedJSRuntime
   1.400 +{
   1.401 +public:
   1.402 +    static XPCJSRuntime* newXPCJSRuntime(nsXPConnect* aXPConnect);
   1.403 +    static XPCJSRuntime* Get() { return nsXPConnect::XPConnect()->GetRuntime(); }
   1.404 +
   1.405 +    XPCJSContextStack* GetJSContextStack() {return mJSContextStack;}
   1.406 +    void DestroyJSContextStack();
   1.407 +
   1.408 +    XPCCallContext*  GetCallContext() const {return mCallContext;}
   1.409 +    XPCCallContext*  SetCallContext(XPCCallContext* ccx)
   1.410 +        {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
   1.411 +
   1.412 +    jsid GetResolveName() const {return mResolveName;}
   1.413 +    jsid SetResolveName(jsid name)
   1.414 +        {jsid old = mResolveName; mResolveName = name; return old;}
   1.415 +
   1.416 +    XPCWrappedNative* GetResolvingWrapper() const {return mResolvingWrapper;}
   1.417 +    XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w)
   1.418 +        {XPCWrappedNative* old = mResolvingWrapper;
   1.419 +         mResolvingWrapper = w; return old;}
   1.420 +
   1.421 +    JSObject2WrappedJSMap*     GetWrappedJSMap()        const
   1.422 +        {return mWrappedJSMap;}
   1.423 +
   1.424 +    IID2WrappedJSClassMap*     GetWrappedJSClassMap()   const
   1.425 +        {return mWrappedJSClassMap;}
   1.426 +
   1.427 +    IID2NativeInterfaceMap* GetIID2NativeInterfaceMap() const
   1.428 +        {return mIID2NativeInterfaceMap;}
   1.429 +
   1.430 +    ClassInfo2NativeSetMap* GetClassInfo2NativeSetMap() const
   1.431 +        {return mClassInfo2NativeSetMap;}
   1.432 +
   1.433 +    NativeSetMap* GetNativeSetMap() const
   1.434 +        {return mNativeSetMap;}
   1.435 +
   1.436 +    IID2ThisTranslatorMap* GetThisTranslatorMap() const
   1.437 +        {return mThisTranslatorMap;}
   1.438 +
   1.439 +    XPCNativeScriptableSharedMap* GetNativeScriptableSharedMap() const
   1.440 +        {return mNativeScriptableSharedMap;}
   1.441 +
   1.442 +    XPCWrappedNativeProtoMap* GetDyingWrappedNativeProtoMap() const
   1.443 +        {return mDyingWrappedNativeProtoMap;}
   1.444 +
   1.445 +    XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const
   1.446 +        {return mDetachedWrappedNativeProtoMap;}
   1.447 +
   1.448 +    bool OnJSContextNew(JSContext* cx);
   1.449 +
   1.450 +    virtual bool
   1.451 +    DescribeCustomObjects(JSObject* aObject, const js::Class* aClasp,
   1.452 +                          char (&aName)[72]) const MOZ_OVERRIDE;
   1.453 +    virtual bool
   1.454 +    NoteCustomGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj,
   1.455 +                                   nsCycleCollectionTraversalCallback& aCb) const MOZ_OVERRIDE;
   1.456 +
   1.457 +    /**
   1.458 +     * Infrastructure for classes that need to defer part of the finalization
   1.459 +     * until after the GC has run, for example for objects that we don't want to
   1.460 +     * destroy during the GC.
   1.461 +     */
   1.462 +
   1.463 +public:
   1.464 +    bool GetDoingFinalization() const {return mDoingFinalization;}
   1.465 +
   1.466 +    // Mapping of often used strings to jsid atoms that live 'forever'.
   1.467 +    //
   1.468 +    // To add a new string: add to this list and to XPCJSRuntime::mStrings
   1.469 +    // at the top of xpcjsruntime.cpp
   1.470 +    enum {
   1.471 +        IDX_CONSTRUCTOR             = 0 ,
   1.472 +        IDX_TO_STRING               ,
   1.473 +        IDX_TO_SOURCE               ,
   1.474 +        IDX_LAST_RESULT             ,
   1.475 +        IDX_RETURN_CODE             ,
   1.476 +        IDX_VALUE                   ,
   1.477 +        IDX_QUERY_INTERFACE         ,
   1.478 +        IDX_COMPONENTS              ,
   1.479 +        IDX_WRAPPED_JSOBJECT        ,
   1.480 +        IDX_OBJECT                  ,
   1.481 +        IDX_FUNCTION                ,
   1.482 +        IDX_PROTOTYPE               ,
   1.483 +        IDX_CREATE_INSTANCE         ,
   1.484 +        IDX_ITEM                    ,
   1.485 +        IDX_PROTO                   ,
   1.486 +        IDX_ITERATOR                ,
   1.487 +        IDX_EXPOSEDPROPS            ,
   1.488 +        IDX_EVAL                    ,
   1.489 +        IDX_CONTROLLERS             ,
   1.490 +        IDX_TOTAL_COUNT // just a count of the above
   1.491 +    };
   1.492 +
   1.493 +    JS::HandleId GetStringID(unsigned index) const
   1.494 +    {
   1.495 +        MOZ_ASSERT(index < IDX_TOTAL_COUNT, "index out of range");
   1.496 +        // fromMarkedLocation() is safe because the string is interned.
   1.497 +        return JS::HandleId::fromMarkedLocation(&mStrIDs[index]);
   1.498 +    }
   1.499 +    JS::HandleValue GetStringJSVal(unsigned index) const
   1.500 +    {
   1.501 +        MOZ_ASSERT(index < IDX_TOTAL_COUNT, "index out of range");
   1.502 +        // fromMarkedLocation() is safe because the string is interned.
   1.503 +        return JS::HandleValue::fromMarkedLocation(&mStrJSVals[index]);
   1.504 +    }
   1.505 +    const char* GetStringName(unsigned index) const
   1.506 +    {
   1.507 +        MOZ_ASSERT(index < IDX_TOTAL_COUNT, "index out of range");
   1.508 +        return mStrings[index];
   1.509 +    }
   1.510 +
   1.511 +    void TraceNativeBlackRoots(JSTracer* trc) MOZ_OVERRIDE;
   1.512 +    void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) MOZ_OVERRIDE;
   1.513 +    void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& cb) MOZ_OVERRIDE;
   1.514 +    void UnmarkSkippableJSHolders();
   1.515 +    void PrepareForForgetSkippable() MOZ_OVERRIDE;
   1.516 +    void BeginCycleCollectionCallback() MOZ_OVERRIDE;
   1.517 +    void EndCycleCollectionCallback(mozilla::CycleCollectorResults &aResults) MOZ_OVERRIDE;
   1.518 +    void DispatchDeferredDeletion(bool continuation) MOZ_OVERRIDE;
   1.519 +
   1.520 +    void CustomGCCallback(JSGCStatus status) MOZ_OVERRIDE;
   1.521 +    bool CustomContextCallback(JSContext *cx, unsigned operation) MOZ_OVERRIDE;
   1.522 +    static void GCSliceCallback(JSRuntime *rt,
   1.523 +                                JS::GCProgress progress,
   1.524 +                                const JS::GCDescription &desc);
   1.525 +    static void FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCompartmentGC);
   1.526 +
   1.527 +    inline void AddVariantRoot(XPCTraceableVariant* variant);
   1.528 +    inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
   1.529 +    inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
   1.530 +
   1.531 +    static void SuspectWrappedNative(XPCWrappedNative *wrapper,
   1.532 +                                     nsCycleCollectionNoteRootCallback &cb);
   1.533 +
   1.534 +    void DebugDump(int16_t depth);
   1.535 +
   1.536 +    void SystemIsBeingShutDown();
   1.537 +
   1.538 +    bool GCIsRunning() const {return mGCIsRunning;}
   1.539 +
   1.540 +    ~XPCJSRuntime();
   1.541 +
   1.542 +    nsString* NewShortLivedString();
   1.543 +    void DeleteShortLivedString(nsString *string);
   1.544 +
   1.545 +    void AddGCCallback(xpcGCCallback cb);
   1.546 +    void RemoveGCCallback(xpcGCCallback cb);
   1.547 +    void AddContextCallback(xpcContextCallback cb);
   1.548 +    void RemoveContextCallback(xpcContextCallback cb);
   1.549 +
   1.550 +    static JSContext* DefaultJSContextCallback(JSRuntime *rt);
   1.551 +    static void ActivityCallback(void *arg, bool active);
   1.552 +    static void CTypesActivityCallback(JSContext *cx,
   1.553 +                                       js::CTypesActivityType type);
   1.554 +    static bool InterruptCallback(JSContext *cx);
   1.555 +    static void OutOfMemoryCallback(JSContext *cx);
   1.556 +
   1.557 +    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
   1.558 +
   1.559 +    AutoMarkingPtr**  GetAutoRootsAdr() {return &mAutoRoots;}
   1.560 +
   1.561 +    JSObject* GetJunkScope();
   1.562 +    JSObject* GetCompilationScope();
   1.563 +    void DeleteSingletonScopes();
   1.564 +
   1.565 +    PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
   1.566 +    void OnAfterProcessNextEvent() { mSlowScriptCheckpoint = mozilla::TimeStamp(); }
   1.567 +
   1.568 +private:
   1.569 +    XPCJSRuntime(); // no implementation
   1.570 +    XPCJSRuntime(nsXPConnect* aXPConnect);
   1.571 +
   1.572 +    void ReleaseIncrementally(nsTArray<nsISupports *> &array);
   1.573 +
   1.574 +    static const char* const mStrings[IDX_TOTAL_COUNT];
   1.575 +    jsid mStrIDs[IDX_TOTAL_COUNT];
   1.576 +    jsval mStrJSVals[IDX_TOTAL_COUNT];
   1.577 +
   1.578 +    XPCJSContextStack*       mJSContextStack;
   1.579 +    XPCCallContext*          mCallContext;
   1.580 +    AutoMarkingPtr*          mAutoRoots;
   1.581 +    jsid                     mResolveName;
   1.582 +    XPCWrappedNative*        mResolvingWrapper;
   1.583 +    JSObject2WrappedJSMap*   mWrappedJSMap;
   1.584 +    IID2WrappedJSClassMap*   mWrappedJSClassMap;
   1.585 +    IID2NativeInterfaceMap*  mIID2NativeInterfaceMap;
   1.586 +    ClassInfo2NativeSetMap*  mClassInfo2NativeSetMap;
   1.587 +    NativeSetMap*            mNativeSetMap;
   1.588 +    IID2ThisTranslatorMap*   mThisTranslatorMap;
   1.589 +    XPCNativeScriptableSharedMap* mNativeScriptableSharedMap;
   1.590 +    XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
   1.591 +    XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap;
   1.592 +    bool mGCIsRunning;
   1.593 +    nsTArray<nsXPCWrappedJS*> mWrappedJSToReleaseArray;
   1.594 +    nsTArray<nsISupports*> mNativesToReleaseArray;
   1.595 +    bool mDoingFinalization;
   1.596 +    XPCRootSetElem *mVariantRoots;
   1.597 +    XPCRootSetElem *mWrappedJSRoots;
   1.598 +    XPCRootSetElem *mObjectHolderRoots;
   1.599 +    nsTArray<xpcGCCallback> extraGCCallbacks;
   1.600 +    nsTArray<xpcContextCallback> extraContextCallbacks;
   1.601 +    nsRefPtr<WatchdogManager> mWatchdogManager;
   1.602 +    JS::GCSliceCallback mPrevGCSliceCallback;
   1.603 +    JS::PersistentRootedObject mJunkScope;
   1.604 +    JS::PersistentRootedObject mCompilationScope;
   1.605 +    nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
   1.606 +
   1.607 +    mozilla::TimeStamp mSlowScriptCheckpoint;
   1.608 +
   1.609 +#define XPCCCX_STRING_CACHE_SIZE 2
   1.610 +
   1.611 +    mozilla::Maybe<nsString> mScratchStrings[XPCCCX_STRING_CACHE_SIZE];
   1.612 +
   1.613 +    friend class Watchdog;
   1.614 +    friend class AutoLockWatchdog;
   1.615 +    friend class XPCIncrementalReleaseRunnable;
   1.616 +};
   1.617 +
   1.618 +/***************************************************************************/
   1.619 +/***************************************************************************/
   1.620 +// XPCContext is mostly a dumb class to hold JSContext specific data and
   1.621 +// maps that let us find wrappers created for the given JSContext.
   1.622 +
   1.623 +// no virtuals
   1.624 +class XPCContext
   1.625 +{
   1.626 +    friend class XPCJSRuntime;
   1.627 +public:
   1.628 +    static XPCContext* GetXPCContext(JSContext* aJSContext)
   1.629 +        {
   1.630 +            MOZ_ASSERT(JS_GetSecondContextPrivate(aJSContext), "should already have XPCContext");
   1.631 +            return static_cast<XPCContext *>(JS_GetSecondContextPrivate(aJSContext));
   1.632 +        }
   1.633 +
   1.634 +    XPCJSRuntime* GetRuntime() const {return mRuntime;}
   1.635 +    JSContext* GetJSContext() const {return mJSContext;}
   1.636 +
   1.637 +    enum LangType {LANG_UNKNOWN, LANG_JS, LANG_NATIVE};
   1.638 +
   1.639 +    LangType GetCallingLangType() const
   1.640 +        {
   1.641 +            return mCallingLangType;
   1.642 +        }
   1.643 +    LangType SetCallingLangType(LangType lt)
   1.644 +        {
   1.645 +            LangType tmp = mCallingLangType;
   1.646 +            mCallingLangType = lt;
   1.647 +            return tmp;
   1.648 +        }
   1.649 +    bool CallerTypeIsJavaScript() const
   1.650 +        {
   1.651 +            return LANG_JS == mCallingLangType;
   1.652 +        }
   1.653 +    bool CallerTypeIsNative() const
   1.654 +        {
   1.655 +            return LANG_NATIVE == mCallingLangType;
   1.656 +        }
   1.657 +    bool CallerTypeIsKnown() const
   1.658 +        {
   1.659 +            return LANG_UNKNOWN != mCallingLangType;
   1.660 +        }
   1.661 +
   1.662 +    nsresult GetException(nsIException** e)
   1.663 +        {
   1.664 +            nsCOMPtr<nsIException> rval = mException;
   1.665 +            rval.forget(e);
   1.666 +            return NS_OK;
   1.667 +        }
   1.668 +    void SetException(nsIException* e)
   1.669 +        {
   1.670 +            mException = e;
   1.671 +        }
   1.672 +
   1.673 +    nsresult GetLastResult() {return mLastResult;}
   1.674 +    void SetLastResult(nsresult rc) {mLastResult = rc;}
   1.675 +
   1.676 +    nsresult GetPendingResult() {return mPendingResult;}
   1.677 +    void SetPendingResult(nsresult rc) {mPendingResult = rc;}
   1.678 +
   1.679 +    void DebugDump(int16_t depth);
   1.680 +    void AddScope(PRCList *scope) { PR_INSERT_AFTER(scope, &mScopes); }
   1.681 +    void RemoveScope(PRCList *scope) { PR_REMOVE_LINK(scope); }
   1.682 +
   1.683 +    void MarkErrorUnreported() { mErrorUnreported = true; }
   1.684 +    void ClearUnreportedError() { mErrorUnreported = false; }
   1.685 +    bool WasErrorReported() { return !mErrorUnreported; }
   1.686 +
   1.687 +    ~XPCContext();
   1.688 +
   1.689 +private:
   1.690 +    XPCContext();    // no implementation
   1.691 +    XPCContext(XPCJSRuntime* aRuntime, JSContext* aJSContext);
   1.692 +
   1.693 +    static XPCContext* newXPCContext(XPCJSRuntime* aRuntime,
   1.694 +                                     JSContext* aJSContext);
   1.695 +private:
   1.696 +    XPCJSRuntime* mRuntime;
   1.697 +    JSContext*  mJSContext;
   1.698 +    nsresult mLastResult;
   1.699 +    nsresult mPendingResult;
   1.700 +    nsCOMPtr<nsIException> mException;
   1.701 +    LangType mCallingLangType;
   1.702 +    bool mErrorUnreported;
   1.703 +
   1.704 +    // A linked list of scopes to notify when we are destroyed.
   1.705 +    PRCList mScopes;
   1.706 +};
   1.707 +
   1.708 +/***************************************************************************/
   1.709 +
   1.710 +#define NATIVE_CALLER  XPCContext::LANG_NATIVE
   1.711 +#define JS_CALLER      XPCContext::LANG_JS
   1.712 +
   1.713 +// No virtuals
   1.714 +// XPCCallContext is ALWAYS declared as a local variable in some function;
   1.715 +// i.e. instance lifetime is always controled by some C++ function returning.
   1.716 +//
   1.717 +// These things are created frequently in many places. We *intentionally* do
   1.718 +// not inialialize all members in order to save on construction overhead.
   1.719 +// Some constructor pass more valid params than others. We init what must be
   1.720 +// init'd and leave other members undefined. In debug builds the accessors
   1.721 +// use a CHECK_STATE macro to track whether or not the object is in a valid
   1.722 +// state to answer the question a caller might be asking. As long as this
   1.723 +// class is maintained correctly it can do its job without a bunch of added
   1.724 +// overhead from useless initializations and non-DEBUG error checking.
   1.725 +//
   1.726 +// Note that most accessors are inlined.
   1.727 +
   1.728 +class MOZ_STACK_CLASS XPCCallContext : public nsAXPCNativeCallContext
   1.729 +{
   1.730 +public:
   1.731 +    NS_IMETHOD GetCallee(nsISupports **aResult);
   1.732 +    NS_IMETHOD GetCalleeMethodIndex(uint16_t *aResult);
   1.733 +    NS_IMETHOD GetCalleeWrapper(nsIXPConnectWrappedNative **aResult);
   1.734 +    NS_IMETHOD GetJSContext(JSContext **aResult);
   1.735 +    NS_IMETHOD GetArgc(uint32_t *aResult);
   1.736 +    NS_IMETHOD GetArgvPtr(jsval **aResult);
   1.737 +    NS_IMETHOD GetCalleeInterface(nsIInterfaceInfo **aResult);
   1.738 +    NS_IMETHOD GetCalleeClassInfo(nsIClassInfo **aResult);
   1.739 +    NS_IMETHOD GetPreviousCallContext(nsAXPCNativeCallContext **aResult);
   1.740 +    NS_IMETHOD GetLanguage(uint16_t *aResult);
   1.741 +
   1.742 +    enum {NO_ARGS = (unsigned) -1};
   1.743 +
   1.744 +    static JSContext* GetDefaultJSContext();
   1.745 +
   1.746 +    XPCCallContext(XPCContext::LangType callerLanguage,
   1.747 +                   JSContext* cx,
   1.748 +                   JS::HandleObject obj    = JS::NullPtr(),
   1.749 +                   JS::HandleObject funobj = JS::NullPtr(),
   1.750 +                   JS::HandleId id         = JSID_VOIDHANDLE,
   1.751 +                   unsigned argc           = NO_ARGS,
   1.752 +                   jsval *argv             = nullptr,
   1.753 +                   jsval *rval             = nullptr);
   1.754 +
   1.755 +    virtual ~XPCCallContext();
   1.756 +
   1.757 +    inline bool                         IsValid() const ;
   1.758 +
   1.759 +    inline XPCJSRuntime*                GetRuntime() const ;
   1.760 +    inline XPCContext*                  GetXPCContext() const ;
   1.761 +    inline JSContext*                   GetJSContext() const ;
   1.762 +    inline bool                         GetContextPopRequired() const ;
   1.763 +    inline XPCContext::LangType         GetCallerLanguage() const ;
   1.764 +    inline XPCContext::LangType         GetPrevCallerLanguage() const ;
   1.765 +    inline XPCCallContext*              GetPrevCallContext() const ;
   1.766 +
   1.767 +    inline JSObject*                    GetFlattenedJSObject() const ;
   1.768 +    inline nsISupports*                 GetIdentityObject() const ;
   1.769 +    inline XPCWrappedNative*            GetWrapper() const ;
   1.770 +    inline XPCWrappedNativeProto*       GetProto() const ;
   1.771 +
   1.772 +    inline bool                         CanGetTearOff() const ;
   1.773 +    inline XPCWrappedNativeTearOff*     GetTearOff() const ;
   1.774 +
   1.775 +    inline XPCNativeScriptableInfo*     GetScriptableInfo() const ;
   1.776 +    inline bool                         CanGetSet() const ;
   1.777 +    inline XPCNativeSet*                GetSet() const ;
   1.778 +    inline bool                         CanGetInterface() const ;
   1.779 +    inline XPCNativeInterface*          GetInterface() const ;
   1.780 +    inline XPCNativeMember*             GetMember() const ;
   1.781 +    inline bool                         HasInterfaceAndMember() const ;
   1.782 +    inline jsid                         GetName() const ;
   1.783 +    inline bool                         GetStaticMemberIsLocal() const ;
   1.784 +    inline unsigned                     GetArgc() const ;
   1.785 +    inline jsval*                       GetArgv() const ;
   1.786 +    inline jsval*                       GetRetVal() const ;
   1.787 +
   1.788 +    inline uint16_t                     GetMethodIndex() const ;
   1.789 +    inline void                         SetMethodIndex(uint16_t index) ;
   1.790 +
   1.791 +    inline jsid GetResolveName() const;
   1.792 +    inline jsid SetResolveName(JS::HandleId name);
   1.793 +
   1.794 +    inline XPCWrappedNative* GetResolvingWrapper() const;
   1.795 +    inline XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w);
   1.796 +
   1.797 +    inline void SetRetVal(jsval val);
   1.798 +
   1.799 +    void SetName(jsid name);
   1.800 +    void SetArgsAndResultPtr(unsigned argc, jsval *argv, jsval *rval);
   1.801 +    void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
   1.802 +                     bool isSetter);
   1.803 +
   1.804 +    nsresult  CanCallNow();
   1.805 +
   1.806 +    void SystemIsBeingShutDown();
   1.807 +
   1.808 +    operator JSContext*() const {return GetJSContext();}
   1.809 +
   1.810 +private:
   1.811 +
   1.812 +    // no copy ctor or assignment allowed
   1.813 +    XPCCallContext(const XPCCallContext& r); // not implemented
   1.814 +    XPCCallContext& operator= (const XPCCallContext& r); // not implemented
   1.815 +
   1.816 +    XPCWrappedNative* UnwrapThisIfAllowed(JS::HandleObject obj, JS::HandleObject fun,
   1.817 +                                          unsigned argc);
   1.818 +
   1.819 +private:
   1.820 +    // posible values for mState
   1.821 +    enum State {
   1.822 +        INIT_FAILED,
   1.823 +        SYSTEM_SHUTDOWN,
   1.824 +        HAVE_CONTEXT,
   1.825 +        HAVE_OBJECT,
   1.826 +        HAVE_NAME,
   1.827 +        HAVE_ARGS,
   1.828 +        READY_TO_CALL,
   1.829 +        CALL_DONE
   1.830 +    };
   1.831 +
   1.832 +#ifdef DEBUG
   1.833 +inline void CHECK_STATE(int s) const {MOZ_ASSERT(mState >= s, "bad state");}
   1.834 +#else
   1.835 +#define CHECK_STATE(s) ((void)0)
   1.836 +#endif
   1.837 +
   1.838 +private:
   1.839 +    JSAutoRequest                   mAr;
   1.840 +    State                           mState;
   1.841 +
   1.842 +    nsRefPtr<nsXPConnect>           mXPC;
   1.843 +
   1.844 +    XPCContext*                     mXPCContext;
   1.845 +    JSContext*                      mJSContext;
   1.846 +
   1.847 +    XPCContext::LangType            mCallerLanguage;
   1.848 +
   1.849 +    // ctor does not necessarily init the following. BEWARE!
   1.850 +
   1.851 +    XPCContext::LangType            mPrevCallerLanguage;
   1.852 +
   1.853 +    XPCCallContext*                 mPrevCallContext;
   1.854 +
   1.855 +    JS::RootedObject                mFlattenedJSObject;
   1.856 +    XPCWrappedNative*               mWrapper;
   1.857 +    XPCWrappedNativeTearOff*        mTearOff;
   1.858 +
   1.859 +    XPCNativeScriptableInfo*        mScriptableInfo;
   1.860 +
   1.861 +    XPCNativeSet*                   mSet;
   1.862 +    XPCNativeInterface*             mInterface;
   1.863 +    XPCNativeMember*                mMember;
   1.864 +
   1.865 +    JS::RootedId                    mName;
   1.866 +    bool                            mStaticMemberIsLocal;
   1.867 +
   1.868 +    unsigned                        mArgc;
   1.869 +    jsval*                          mArgv;
   1.870 +    jsval*                          mRetVal;
   1.871 +
   1.872 +    uint16_t                        mMethodIndex;
   1.873 +};
   1.874 +
   1.875 +/***************************************************************************
   1.876 +****************************************************************************
   1.877 +*
   1.878 +* Core classes for wrapped native objects for use from JavaScript...
   1.879 +*
   1.880 +****************************************************************************
   1.881 +***************************************************************************/
   1.882 +
   1.883 +// These are the various JSClasses and callbacks whose use that required
   1.884 +// visibility from more than one .cpp file.
   1.885 +
   1.886 +struct XPCWrappedNativeJSClass;
   1.887 +extern const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass;
   1.888 +extern const js::Class XPC_WN_NoMods_WithCall_Proto_JSClass;
   1.889 +extern const js::Class XPC_WN_NoMods_NoCall_Proto_JSClass;
   1.890 +extern const js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass;
   1.891 +extern const js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
   1.892 +extern const js::Class XPC_WN_Tearoff_JSClass;
   1.893 +extern const js::Class XPC_WN_NoHelper_Proto_JSClass;
   1.894 +
   1.895 +extern bool
   1.896 +XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp);
   1.897 +
   1.898 +extern bool
   1.899 +XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp);
   1.900 +
   1.901 +extern bool
   1.902 +XPC_WN_JSOp_Enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op,
   1.903 +                      JS::MutableHandleValue statep, JS::MutableHandleId idp);
   1.904 +
   1.905 +extern JSObject*
   1.906 +XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
   1.907 +
   1.908 +// Macros to initialize Object or Function like XPC_WN classes
   1.909 +#define XPC_WN_WithCall_ObjectOps                                             \
   1.910 +    {                                                                         \
   1.911 +        nullptr, /* lookupGeneric */                                          \
   1.912 +        nullptr, /* lookupProperty */                                         \
   1.913 +        nullptr, /* lookupElement */                                          \
   1.914 +        nullptr, /* defineGeneric */                                          \
   1.915 +        nullptr, /* defineProperty */                                         \
   1.916 +        nullptr, /* defineElement */                                          \
   1.917 +        nullptr, /* getGeneric    */                                          \
   1.918 +        nullptr, /* getProperty    */                                         \
   1.919 +        nullptr, /* getElement    */                                          \
   1.920 +        nullptr, /* setGeneric    */                                          \
   1.921 +        nullptr, /* setProperty    */                                         \
   1.922 +        nullptr, /* setElement    */                                          \
   1.923 +        nullptr, /* getGenericAttributes  */                                  \
   1.924 +        nullptr, /* setGenericAttributes  */                                  \
   1.925 +        nullptr, /* deleteProperty */                                         \
   1.926 +        nullptr, /* deleteElement */                                          \
   1.927 +        nullptr, nullptr, /* watch/unwatch */                                 \
   1.928 +        nullptr, /* slice */                                                  \
   1.929 +        XPC_WN_JSOp_Enumerate,                                                \
   1.930 +        XPC_WN_JSOp_ThisObject,                                               \
   1.931 +    }
   1.932 +
   1.933 +#define XPC_WN_NoCall_ObjectOps                                               \
   1.934 +    {                                                                         \
   1.935 +        nullptr, /* lookupGeneric */                                          \
   1.936 +        nullptr, /* lookupProperty */                                         \
   1.937 +        nullptr, /* lookupElement */                                          \
   1.938 +        nullptr, /* defineGeneric */                                          \
   1.939 +        nullptr, /* defineProperty */                                         \
   1.940 +        nullptr, /* defineElement */                                          \
   1.941 +        nullptr, /* getGeneric    */                                          \
   1.942 +        nullptr, /* getProperty    */                                         \
   1.943 +        nullptr, /* getElement    */                                          \
   1.944 +        nullptr, /* setGeneric    */                                          \
   1.945 +        nullptr, /* setProperty    */                                         \
   1.946 +        nullptr, /* setElement    */                                          \
   1.947 +        nullptr, /* getGenericAttributes  */                                  \
   1.948 +        nullptr, /* setGenericAttributes  */                                  \
   1.949 +        nullptr, /* deleteProperty */                                         \
   1.950 +        nullptr, /* deleteElement */                                          \
   1.951 +        nullptr, nullptr, /* watch/unwatch */                                 \
   1.952 +        nullptr, /* slice */                                                  \
   1.953 +        XPC_WN_JSOp_Enumerate,                                                \
   1.954 +        XPC_WN_JSOp_ThisObject,                                               \
   1.955 +    }
   1.956 +
   1.957 +// Maybe this macro should check for class->enumerate ==
   1.958 +// XPC_WN_Shared_Proto_Enumerate or something rather than checking for
   1.959 +// 4 classes?
   1.960 +static inline bool IS_PROTO_CLASS(const js::Class *clazz)
   1.961 +{
   1.962 +    return clazz == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
   1.963 +           clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass ||
   1.964 +           clazz == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
   1.965 +           clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
   1.966 +}
   1.967 +
   1.968 +/***************************************************************************/
   1.969 +// XPCWrappedNativeScope is one-to-one with a JS global object.
   1.970 +
   1.971 +class nsXPCComponentsBase;
   1.972 +class XPCWrappedNativeScope : public PRCList
   1.973 +{
   1.974 +public:
   1.975 +
   1.976 +    static XPCWrappedNativeScope*
   1.977 +    GetNewOrUsed(JSContext *cx, JS::HandleObject aGlobal);
   1.978 +
   1.979 +    XPCJSRuntime*
   1.980 +    GetRuntime() const {return XPCJSRuntime::Get();}
   1.981 +
   1.982 +    Native2WrappedNativeMap*
   1.983 +    GetWrappedNativeMap() const {return mWrappedNativeMap;}
   1.984 +
   1.985 +    ClassInfo2WrappedNativeProtoMap*
   1.986 +    GetWrappedNativeProtoMap() const {return mWrappedNativeProtoMap;}
   1.987 +
   1.988 +    nsXPCComponentsBase*
   1.989 +    GetComponents() const {return mComponents;}
   1.990 +
   1.991 +    // Forces the creation of a privileged |Components| object, even in
   1.992 +    // content scopes. This will crash if used outside of automation.
   1.993 +    void
   1.994 +    ForcePrivilegedComponents();
   1.995 +
   1.996 +    bool AttachComponentsObject(JSContext *aCx);
   1.997 +
   1.998 +    // Returns the JS object reflection of the Components object.
   1.999 +    bool
  1.1000 +    GetComponentsJSObject(JS::MutableHandleObject obj);
  1.1001 +
  1.1002 +    JSObject*
  1.1003 +    GetGlobalJSObject() const {
  1.1004 +        JS::ExposeObjectToActiveJS(mGlobalJSObject);
  1.1005 +        return mGlobalJSObject;
  1.1006 +    }
  1.1007 +
  1.1008 +    JSObject*
  1.1009 +    GetGlobalJSObjectPreserveColor() const {return mGlobalJSObject;}
  1.1010 +
  1.1011 +    nsIPrincipal*
  1.1012 +    GetPrincipal() const {
  1.1013 +        JSCompartment *c = js::GetObjectCompartment(mGlobalJSObject);
  1.1014 +        return nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
  1.1015 +    }
  1.1016 +
  1.1017 +    JSObject*
  1.1018 +    GetExpandoChain(JS::HandleObject target);
  1.1019 +
  1.1020 +    bool
  1.1021 +    SetExpandoChain(JSContext *cx, JS::HandleObject target, JS::HandleObject chain);
  1.1022 +
  1.1023 +    void RemoveWrappedNativeProtos();
  1.1024 +
  1.1025 +    static void
  1.1026 +    SystemIsBeingShutDown();
  1.1027 +
  1.1028 +    static void
  1.1029 +    TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt);
  1.1030 +
  1.1031 +    void TraceInside(JSTracer *trc) {
  1.1032 +        MOZ_ASSERT(mGlobalJSObject);
  1.1033 +        mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject");
  1.1034 +        if (mXBLScope)
  1.1035 +            mXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope");
  1.1036 +        if (mXrayExpandos.initialized())
  1.1037 +            mXrayExpandos.trace(trc);
  1.1038 +    }
  1.1039 +
  1.1040 +    static void
  1.1041 +    SuspectAllWrappers(XPCJSRuntime* rt, nsCycleCollectionNoteRootCallback &cb);
  1.1042 +
  1.1043 +    static void
  1.1044 +    StartFinalizationPhaseOfGC(JSFreeOp *fop, XPCJSRuntime* rt);
  1.1045 +
  1.1046 +    static void
  1.1047 +    FinishedFinalizationPhaseOfGC();
  1.1048 +
  1.1049 +    static void
  1.1050 +    MarkAllWrappedNativesAndProtos();
  1.1051 +
  1.1052 +#ifdef DEBUG
  1.1053 +    static void
  1.1054 +    ASSERT_NoInterfaceSetsAreMarked();
  1.1055 +#endif
  1.1056 +
  1.1057 +    static void
  1.1058 +    SweepAllWrappedNativeTearOffs();
  1.1059 +
  1.1060 +    static void
  1.1061 +    DebugDumpAllScopes(int16_t depth);
  1.1062 +
  1.1063 +    void
  1.1064 +    DebugDump(int16_t depth);
  1.1065 +
  1.1066 +    struct ScopeSizeInfo {
  1.1067 +        ScopeSizeInfo(mozilla::MallocSizeOf mallocSizeOf)
  1.1068 +            : mMallocSizeOf(mallocSizeOf),
  1.1069 +              mScopeAndMapSize(0),
  1.1070 +              mProtoAndIfaceCacheSize(0)
  1.1071 +        {}
  1.1072 +
  1.1073 +        mozilla::MallocSizeOf mMallocSizeOf;
  1.1074 +        size_t mScopeAndMapSize;
  1.1075 +        size_t mProtoAndIfaceCacheSize;
  1.1076 +    };
  1.1077 +
  1.1078 +    static void
  1.1079 +    AddSizeOfAllScopesIncludingThis(ScopeSizeInfo* scopeSizeInfo);
  1.1080 +
  1.1081 +    void
  1.1082 +    AddSizeOfIncludingThis(ScopeSizeInfo* scopeSizeInfo);
  1.1083 +
  1.1084 +    bool
  1.1085 +    IsValid() const {return mRuntime != nullptr;}
  1.1086 +
  1.1087 +    static bool
  1.1088 +    IsDyingScope(XPCWrappedNativeScope *scope);
  1.1089 +
  1.1090 +    static void InitStatics() { gScopes = nullptr; gDyingScopes = nullptr; }
  1.1091 +
  1.1092 +    XPCContext *GetContext() { return mContext; }
  1.1093 +    void ClearContext() { mContext = nullptr; }
  1.1094 +
  1.1095 +    typedef js::HashSet<JSObject *,
  1.1096 +                        js::PointerHasher<JSObject *, 3>,
  1.1097 +                        js::SystemAllocPolicy> DOMExpandoSet;
  1.1098 +
  1.1099 +    bool RegisterDOMExpandoObject(JSObject *expando) {
  1.1100 +        // Expandos are proxy objects, and proxies are always tenured.
  1.1101 +        JS::AssertGCThingMustBeTenured(expando);
  1.1102 +        if (!mDOMExpandoSet) {
  1.1103 +            mDOMExpandoSet = new DOMExpandoSet();
  1.1104 +            mDOMExpandoSet->init(8);
  1.1105 +        }
  1.1106 +        return mDOMExpandoSet->put(expando);
  1.1107 +    }
  1.1108 +    void RemoveDOMExpandoObject(JSObject *expando) {
  1.1109 +        if (mDOMExpandoSet)
  1.1110 +            mDOMExpandoSet->remove(expando);
  1.1111 +    }
  1.1112 +
  1.1113 +    // Gets the appropriate scope object for XBL in this scope. The context
  1.1114 +    // must be same-compartment with the global upon entering, and the scope
  1.1115 +    // object is wrapped into the compartment of the global.
  1.1116 +    JSObject *EnsureXBLScope(JSContext *cx);
  1.1117 +
  1.1118 +    XPCWrappedNativeScope(JSContext *cx, JS::HandleObject aGlobal);
  1.1119 +
  1.1120 +    nsAutoPtr<JSObject2JSObjectMap> mWaiverWrapperMap;
  1.1121 +
  1.1122 +    bool IsXBLScope() { return mIsXBLScope; }
  1.1123 +    bool AllowXBLScope();
  1.1124 +    bool UseXBLScope() { return mUseXBLScope; }
  1.1125 +
  1.1126 +protected:
  1.1127 +    virtual ~XPCWrappedNativeScope();
  1.1128 +
  1.1129 +    static void KillDyingScopes();
  1.1130 +
  1.1131 +    XPCWrappedNativeScope(); // not implemented
  1.1132 +
  1.1133 +private:
  1.1134 +    static XPCWrappedNativeScope* gScopes;
  1.1135 +    static XPCWrappedNativeScope* gDyingScopes;
  1.1136 +
  1.1137 +    XPCJSRuntime*                    mRuntime;
  1.1138 +    Native2WrappedNativeMap*         mWrappedNativeMap;
  1.1139 +    ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap;
  1.1140 +    nsRefPtr<nsXPCComponentsBase>    mComponents;
  1.1141 +    XPCWrappedNativeScope*           mNext;
  1.1142 +    // The JS global object for this scope.  If non-null, this will be the
  1.1143 +    // default parent for the XPCWrappedNatives that have us as the scope,
  1.1144 +    // unless a PreCreate hook overrides it.  Note that this _may_ be null (see
  1.1145 +    // constructor).
  1.1146 +    JS::ObjectPtr                    mGlobalJSObject;
  1.1147 +
  1.1148 +    // XBL Scope. This is is a lazily-created sandbox for non-system scopes.
  1.1149 +    // EnsureXBLScope() decides whether it needs to be created or not.
  1.1150 +    // This reference is wrapped into the compartment of mGlobalJSObject.
  1.1151 +    JS::ObjectPtr                    mXBLScope;
  1.1152 +
  1.1153 +    XPCContext*                      mContext;
  1.1154 +
  1.1155 +    nsAutoPtr<DOMExpandoSet> mDOMExpandoSet;
  1.1156 +
  1.1157 +    JS::WeakMapPtr<JSObject*, JSObject*> mXrayExpandos;
  1.1158 +
  1.1159 +    bool mIsXBLScope;
  1.1160 +
  1.1161 +    // For remote XUL domains, we run all XBL in the content scope for compat
  1.1162 +    // reasons (though we sometimes pref this off for automation). We separately
  1.1163 +    // track the result of this decision (mAllowXBLScope), from the decision
  1.1164 +    // of whether to actually _use_ an XBL scope (mUseXBLScope), which depends
  1.1165 +    // on the type of global and whether the compartment is system principal
  1.1166 +    // or not.
  1.1167 +    //
  1.1168 +    // This distinction is useful primarily because, if true, we know that we
  1.1169 +    // have no way of distinguishing XBL script from content script for the
  1.1170 +    // given scope. In these (unsupported) situations, we just always claim to
  1.1171 +    // be XBL.
  1.1172 +    bool mAllowXBLScope;
  1.1173 +    bool mUseXBLScope;
  1.1174 +};
  1.1175 +
  1.1176 +/***************************************************************************/
  1.1177 +// XPCNativeMember represents a single idl declared method, attribute or
  1.1178 +// constant.
  1.1179 +
  1.1180 +// Tight. No virtual methods. Can be bitwise copied (until any resolution done).
  1.1181 +
  1.1182 +class XPCNativeMember
  1.1183 +{
  1.1184 +public:
  1.1185 +    static bool GetCallInfo(JSObject* funobj,
  1.1186 +                            XPCNativeInterface** pInterface,
  1.1187 +                            XPCNativeMember**    pMember);
  1.1188 +
  1.1189 +    jsid   GetName() const {return mName;}
  1.1190 +
  1.1191 +    uint16_t GetIndex() const {return mIndex;}
  1.1192 +
  1.1193 +    bool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
  1.1194 +                          jsval* pval)
  1.1195 +        {MOZ_ASSERT(IsConstant(),
  1.1196 +                    "Only call this if you're sure this is a constant!");
  1.1197 +         return Resolve(ccx, iface, JS::NullPtr(), pval);}
  1.1198 +
  1.1199 +    bool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface,
  1.1200 +                           JS::HandleObject parent, jsval* pval);
  1.1201 +
  1.1202 +    bool IsMethod() const
  1.1203 +        {return 0 != (mFlags & METHOD);}
  1.1204 +
  1.1205 +    bool IsConstant() const
  1.1206 +        {return 0 != (mFlags & CONSTANT);}
  1.1207 +
  1.1208 +    bool IsAttribute() const
  1.1209 +        {return 0 != (mFlags & GETTER);}
  1.1210 +
  1.1211 +    bool IsWritableAttribute() const
  1.1212 +        {return 0 != (mFlags & SETTER_TOO);}
  1.1213 +
  1.1214 +    bool IsReadOnlyAttribute() const
  1.1215 +        {return IsAttribute() && !IsWritableAttribute();}
  1.1216 +
  1.1217 +
  1.1218 +    void SetName(jsid a) {mName = a;}
  1.1219 +
  1.1220 +    void SetMethod(uint16_t index)
  1.1221 +        {mFlags = METHOD; mIndex = index;}
  1.1222 +
  1.1223 +    void SetConstant(uint16_t index)
  1.1224 +        {mFlags = CONSTANT; mIndex = index;}
  1.1225 +
  1.1226 +    void SetReadOnlyAttribute(uint16_t index)
  1.1227 +        {mFlags = GETTER; mIndex = index;}
  1.1228 +
  1.1229 +    void SetWritableAttribute()
  1.1230 +        {MOZ_ASSERT(mFlags == GETTER,"bad"); mFlags = GETTER | SETTER_TOO;}
  1.1231 +
  1.1232 +    /* default ctor - leave random contents */
  1.1233 +    XPCNativeMember()  {MOZ_COUNT_CTOR(XPCNativeMember);}
  1.1234 +    ~XPCNativeMember() {MOZ_COUNT_DTOR(XPCNativeMember);}
  1.1235 +
  1.1236 +private:
  1.1237 +    bool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
  1.1238 +                 JS::HandleObject parent, jsval *vp);
  1.1239 +
  1.1240 +    enum {
  1.1241 +        METHOD      = 0x01,
  1.1242 +        CONSTANT    = 0x02,
  1.1243 +        GETTER      = 0x04,
  1.1244 +        SETTER_TOO  = 0x08
  1.1245 +    };
  1.1246 +
  1.1247 +private:
  1.1248 +    // our only data...
  1.1249 +    jsid     mName;
  1.1250 +    uint16_t mIndex;
  1.1251 +    uint16_t mFlags;
  1.1252 +};
  1.1253 +
  1.1254 +/***************************************************************************/
  1.1255 +// XPCNativeInterface represents a single idl declared interface. This is
  1.1256 +// primarily the set of XPCNativeMembers.
  1.1257 +
  1.1258 +// Tight. No virtual methods.
  1.1259 +
  1.1260 +class XPCNativeInterface
  1.1261 +{
  1.1262 +  public:
  1.1263 +    static XPCNativeInterface* GetNewOrUsed(const nsIID* iid);
  1.1264 +    static XPCNativeInterface* GetNewOrUsed(nsIInterfaceInfo* info);
  1.1265 +    static XPCNativeInterface* GetNewOrUsed(const char* name);
  1.1266 +    static XPCNativeInterface* GetISupports();
  1.1267 +
  1.1268 +    inline nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo.get();}
  1.1269 +    inline jsid              GetName()          const {return mName;}
  1.1270 +
  1.1271 +    inline const nsIID* GetIID() const;
  1.1272 +    inline const char*  GetNameString() const;
  1.1273 +    inline XPCNativeMember* FindMember(jsid name) const;
  1.1274 +
  1.1275 +    inline bool HasAncestor(const nsIID* iid) const;
  1.1276 +
  1.1277 +    uint16_t GetMemberCount() const {
  1.1278 +        return mMemberCount;
  1.1279 +    }
  1.1280 +    XPCNativeMember* GetMemberAt(uint16_t i) {
  1.1281 +        MOZ_ASSERT(i < mMemberCount, "bad index");
  1.1282 +        return &mMembers[i];
  1.1283 +    }
  1.1284 +
  1.1285 +    void DebugDump(int16_t depth);
  1.1286 +
  1.1287 +#define XPC_NATIVE_IFACE_MARK_FLAG ((uint16_t)JS_BIT(15)) // only high bit of 16 is set
  1.1288 +
  1.1289 +    void Mark() {
  1.1290 +        mMarked = 1;
  1.1291 +    }
  1.1292 +
  1.1293 +    void Unmark() {
  1.1294 +        mMarked = 0;
  1.1295 +    }
  1.1296 +
  1.1297 +    bool IsMarked() const {
  1.1298 +        return mMarked != 0;
  1.1299 +    }
  1.1300 +
  1.1301 +    // NOP. This is just here to make the AutoMarkingPtr code compile.
  1.1302 +    inline void TraceJS(JSTracer* trc) {}
  1.1303 +    inline void AutoTrace(JSTracer* trc) {}
  1.1304 +
  1.1305 +    static void DestroyInstance(XPCNativeInterface* inst);
  1.1306 +
  1.1307 +    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
  1.1308 +
  1.1309 +  protected:
  1.1310 +    static XPCNativeInterface* NewInstance(nsIInterfaceInfo* aInfo);
  1.1311 +
  1.1312 +    XPCNativeInterface();   // not implemented
  1.1313 +    XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName)
  1.1314 +      : mInfo(aInfo), mName(aName), mMemberCount(0), mMarked(0)
  1.1315 +    {
  1.1316 +        MOZ_COUNT_CTOR(XPCNativeInterface);
  1.1317 +    }
  1.1318 +    ~XPCNativeInterface() {
  1.1319 +        MOZ_COUNT_DTOR(XPCNativeInterface);
  1.1320 +    }
  1.1321 +
  1.1322 +    void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
  1.1323 +
  1.1324 +    XPCNativeInterface(const XPCNativeInterface& r); // not implemented
  1.1325 +    XPCNativeInterface& operator= (const XPCNativeInterface& r); // not implemented
  1.1326 +
  1.1327 +private:
  1.1328 +    nsCOMPtr<nsIInterfaceInfo> mInfo;
  1.1329 +    jsid                       mName;
  1.1330 +    uint16_t                   mMemberCount : 15;
  1.1331 +    uint16_t                   mMarked : 1;
  1.1332 +    XPCNativeMember            mMembers[1]; // always last - object sized for array
  1.1333 +};
  1.1334 +
  1.1335 +/***************************************************************************/
  1.1336 +// XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap.
  1.1337 +
  1.1338 +class XPCNativeSetKey
  1.1339 +{
  1.1340 +public:
  1.1341 +    XPCNativeSetKey(XPCNativeSet*       BaseSet  = nullptr,
  1.1342 +                    XPCNativeInterface* Addition = nullptr,
  1.1343 +                    uint16_t            Position = 0)
  1.1344 +        : mIsAKey(IS_A_KEY), mPosition(Position), mBaseSet(BaseSet),
  1.1345 +          mAddition(Addition) {}
  1.1346 +    ~XPCNativeSetKey() {}
  1.1347 +
  1.1348 +    XPCNativeSet*           GetBaseSet()  const {return mBaseSet;}
  1.1349 +    XPCNativeInterface*     GetAddition() const {return mAddition;}
  1.1350 +    uint16_t                GetPosition() const {return mPosition;}
  1.1351 +
  1.1352 +    // This is a fun little hack...
  1.1353 +    // We build these keys only on the stack. We use them for lookup in
  1.1354 +    // NativeSetMap. Becasue we don't want to pay the cost of cloning a key and
  1.1355 +    // sticking it into the hashtable, when the XPCNativeSet actually
  1.1356 +    // gets added to the table the 'key' in the table is a pointer to the
  1.1357 +    // set itself and not this key. Our key compare function expects to get
  1.1358 +    // a key and a set. When we do external lookups in the map we pass in one
  1.1359 +    // of these keys and our compare function gets passed a key and a set.
  1.1360 +    // (see compare_NativeKeyToSet in xpcmaps.cpp). This is all well and good.
  1.1361 +    // Except, when the table decides to resize itself. Then it tries to use
  1.1362 +    // our compare function with the 'keys' that are in the hashtable (which are
  1.1363 +    // really XPCNativeSet objects and not XPCNativeSetKey objects!
  1.1364 +    //
  1.1365 +    // So, the hack is to have the compare function assume it is getting a
  1.1366 +    // XPCNativeSetKey pointer and call this IsAKey method. If that fails then
  1.1367 +    // it realises that it really has a XPCNativeSet pointer and deals with that
  1.1368 +    // fact. This is safe because we know that both of these classes have no
  1.1369 +    // virtual methods and their first data member is a uint16_t. We are
  1.1370 +    // confident that XPCNativeSet->mMemberCount will never be 0xffff.
  1.1371 +
  1.1372 +    bool                    IsAKey() const {return mIsAKey == IS_A_KEY;}
  1.1373 +
  1.1374 +    enum {IS_A_KEY = 0xffff};
  1.1375 +
  1.1376 +    // Allow shallow copy
  1.1377 +
  1.1378 +private:
  1.1379 +    uint16_t                mIsAKey;    // must be first data member
  1.1380 +    uint16_t                mPosition;
  1.1381 +    XPCNativeSet*           mBaseSet;
  1.1382 +    XPCNativeInterface*     mAddition;
  1.1383 +};
  1.1384 +
  1.1385 +/***************************************************************************/
  1.1386 +// XPCNativeSet represents an ordered collection of XPCNativeInterface pointers.
  1.1387 +
  1.1388 +class XPCNativeSet
  1.1389 +{
  1.1390 +  public:
  1.1391 +    static XPCNativeSet* GetNewOrUsed(const nsIID* iid);
  1.1392 +    static XPCNativeSet* GetNewOrUsed(nsIClassInfo* classInfo);
  1.1393 +    static XPCNativeSet* GetNewOrUsed(XPCNativeSet* otherSet,
  1.1394 +                                      XPCNativeInterface* newInterface,
  1.1395 +                                      uint16_t position);
  1.1396 +
  1.1397 +    // This generates a union set.
  1.1398 +    //
  1.1399 +    // If preserveFirstSetOrder is true, the elements from |firstSet| come first,
  1.1400 +    // followed by any non-duplicate items from |secondSet|. If false, the same
  1.1401 +    // algorithm is applied; but if we detect that |secondSet| is a superset of
  1.1402 +    // |firstSet|, we return |secondSet| without worrying about whether the
  1.1403 +    // ordering might differ from |firstSet|.
  1.1404 +    static XPCNativeSet* GetNewOrUsed(XPCNativeSet* firstSet,
  1.1405 +                                      XPCNativeSet* secondSet,
  1.1406 +                                      bool preserveFirstSetOrder);
  1.1407 +
  1.1408 +    static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
  1.1409 +
  1.1410 +    inline bool FindMember(jsid name, XPCNativeMember** pMember,
  1.1411 +                             uint16_t* pInterfaceIndex) const;
  1.1412 +
  1.1413 +    inline bool FindMember(jsid name, XPCNativeMember** pMember,
  1.1414 +                             XPCNativeInterface** pInterface) const;
  1.1415 +
  1.1416 +    inline bool FindMember(jsid name,
  1.1417 +                             XPCNativeMember** pMember,
  1.1418 +                             XPCNativeInterface** pInterface,
  1.1419 +                             XPCNativeSet* protoSet,
  1.1420 +                             bool* pIsLocal) const;
  1.1421 +
  1.1422 +    inline bool HasInterface(XPCNativeInterface* aInterface) const;
  1.1423 +    inline bool HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const;
  1.1424 +    inline bool HasInterfaceWithAncestor(const nsIID* iid) const;
  1.1425 +
  1.1426 +    inline XPCNativeInterface* FindInterfaceWithIID(const nsIID& iid) const;
  1.1427 +
  1.1428 +    inline XPCNativeInterface* FindNamedInterface(jsid name) const;
  1.1429 +
  1.1430 +    uint16_t GetMemberCount() const {
  1.1431 +        return mMemberCount;
  1.1432 +    }
  1.1433 +    uint16_t GetInterfaceCount() const {
  1.1434 +        return mInterfaceCount;
  1.1435 +    }
  1.1436 +    XPCNativeInterface **GetInterfaceArray() {
  1.1437 +        return mInterfaces;
  1.1438 +    }
  1.1439 +
  1.1440 +    XPCNativeInterface* GetInterfaceAt(uint16_t i)
  1.1441 +        {MOZ_ASSERT(i < mInterfaceCount, "bad index"); return mInterfaces[i];}
  1.1442 +
  1.1443 +    inline bool MatchesSetUpToInterface(const XPCNativeSet* other,
  1.1444 +                                          XPCNativeInterface* iface) const;
  1.1445 +
  1.1446 +#define XPC_NATIVE_SET_MARK_FLAG ((uint16_t)JS_BIT(15)) // only high bit of 16 is set
  1.1447 +
  1.1448 +    inline void Mark();
  1.1449 +
  1.1450 +    // NOP. This is just here to make the AutoMarkingPtr code compile.
  1.1451 +    inline void TraceJS(JSTracer* trc) {}
  1.1452 +    inline void AutoTrace(JSTracer* trc) {}
  1.1453 +
  1.1454 +  private:
  1.1455 +    void MarkSelfOnly() {
  1.1456 +        mMarked = 1;
  1.1457 +    }
  1.1458 +
  1.1459 +  public:
  1.1460 +    void Unmark() {
  1.1461 +        mMarked = 0;
  1.1462 +    }
  1.1463 +    bool IsMarked() const {
  1.1464 +        return !!mMarked;
  1.1465 +    }
  1.1466 +
  1.1467 +#ifdef DEBUG
  1.1468 +    inline void ASSERT_NotMarked();
  1.1469 +#endif
  1.1470 +
  1.1471 +    void DebugDump(int16_t depth);
  1.1472 +
  1.1473 +    static void DestroyInstance(XPCNativeSet* inst);
  1.1474 +
  1.1475 +    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
  1.1476 +
  1.1477 +  protected:
  1.1478 +    static XPCNativeSet* NewInstance(XPCNativeInterface** array,
  1.1479 +                                     uint16_t count);
  1.1480 +    static XPCNativeSet* NewInstanceMutate(XPCNativeSet*       otherSet,
  1.1481 +                                           XPCNativeInterface* newInterface,
  1.1482 +                                           uint16_t            position);
  1.1483 +    XPCNativeSet()
  1.1484 +      : mMemberCount(0), mInterfaceCount(0), mMarked(0)
  1.1485 +    {
  1.1486 +        MOZ_COUNT_CTOR(XPCNativeSet);
  1.1487 +    }
  1.1488 +    ~XPCNativeSet() {
  1.1489 +        MOZ_COUNT_DTOR(XPCNativeSet);
  1.1490 +    }
  1.1491 +    void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
  1.1492 +
  1.1493 +  private:
  1.1494 +    uint16_t                mMemberCount;
  1.1495 +    uint16_t                mInterfaceCount : 15;
  1.1496 +    uint16_t                mMarked : 1;
  1.1497 +    XPCNativeInterface*     mInterfaces[1];  // always last - object sized for array
  1.1498 +};
  1.1499 +
  1.1500 +/***************************************************************************/
  1.1501 +// XPCNativeScriptableFlags is a wrapper class that holds the flags returned
  1.1502 +// from calls to nsIXPCScriptable::GetScriptableFlags(). It has convenience
  1.1503 +// methods to check for particular bitflags. Since we also use this class as
  1.1504 +// a member of the gc'd class XPCNativeScriptableShared, this class holds the
  1.1505 +// bit and exposes the inlined methods to support marking.
  1.1506 +
  1.1507 +#define XPC_WN_SJSFLAGS_MARK_FLAG JS_BIT(31) // only high bit of 32 is set
  1.1508 +
  1.1509 +class XPCNativeScriptableFlags
  1.1510 +{
  1.1511 +private:
  1.1512 +    uint32_t mFlags;
  1.1513 +
  1.1514 +public:
  1.1515 +
  1.1516 +    XPCNativeScriptableFlags(uint32_t flags = 0) : mFlags(flags) {}
  1.1517 +
  1.1518 +    uint32_t GetFlags() const {return mFlags & ~XPC_WN_SJSFLAGS_MARK_FLAG;}
  1.1519 +    void     SetFlags(uint32_t flags) {mFlags = flags;}
  1.1520 +
  1.1521 +    operator uint32_t() const {return GetFlags();}
  1.1522 +
  1.1523 +    XPCNativeScriptableFlags(const XPCNativeScriptableFlags& r)
  1.1524 +        {mFlags = r.GetFlags();}
  1.1525 +
  1.1526 +    XPCNativeScriptableFlags& operator= (const XPCNativeScriptableFlags& r)
  1.1527 +        {mFlags = r.GetFlags(); return *this;}
  1.1528 +
  1.1529 +    void Mark()       {mFlags |= XPC_WN_SJSFLAGS_MARK_FLAG;}
  1.1530 +    void Unmark()     {mFlags &= ~XPC_WN_SJSFLAGS_MARK_FLAG;}
  1.1531 +    bool IsMarked() const {return 0 != (mFlags & XPC_WN_SJSFLAGS_MARK_FLAG);}
  1.1532 +
  1.1533 +#ifdef GET_IT
  1.1534 +#undef GET_IT
  1.1535 +#endif
  1.1536 +#define GET_IT(f_) const {return 0 != (mFlags & nsIXPCScriptable:: f_ );}
  1.1537 +
  1.1538 +    bool WantPreCreate()                GET_IT(WANT_PRECREATE)
  1.1539 +    bool WantCreate()                   GET_IT(WANT_CREATE)
  1.1540 +    bool WantPostCreate()               GET_IT(WANT_POSTCREATE)
  1.1541 +    bool WantAddProperty()              GET_IT(WANT_ADDPROPERTY)
  1.1542 +    bool WantDelProperty()              GET_IT(WANT_DELPROPERTY)
  1.1543 +    bool WantGetProperty()              GET_IT(WANT_GETPROPERTY)
  1.1544 +    bool WantSetProperty()              GET_IT(WANT_SETPROPERTY)
  1.1545 +    bool WantEnumerate()                GET_IT(WANT_ENUMERATE)
  1.1546 +    bool WantNewEnumerate()             GET_IT(WANT_NEWENUMERATE)
  1.1547 +    bool WantNewResolve()               GET_IT(WANT_NEWRESOLVE)
  1.1548 +    bool WantConvert()                  GET_IT(WANT_CONVERT)
  1.1549 +    bool WantFinalize()                 GET_IT(WANT_FINALIZE)
  1.1550 +    bool WantCall()                     GET_IT(WANT_CALL)
  1.1551 +    bool WantConstruct()                GET_IT(WANT_CONSTRUCT)
  1.1552 +    bool WantHasInstance()              GET_IT(WANT_HASINSTANCE)
  1.1553 +    bool WantOuterObject()              GET_IT(WANT_OUTER_OBJECT)
  1.1554 +    bool UseJSStubForAddProperty()      GET_IT(USE_JSSTUB_FOR_ADDPROPERTY)
  1.1555 +    bool UseJSStubForDelProperty()      GET_IT(USE_JSSTUB_FOR_DELPROPERTY)
  1.1556 +    bool UseJSStubForSetProperty()      GET_IT(USE_JSSTUB_FOR_SETPROPERTY)
  1.1557 +    bool DontEnumStaticProps()          GET_IT(DONT_ENUM_STATIC_PROPS)
  1.1558 +    bool DontEnumQueryInterface()       GET_IT(DONT_ENUM_QUERY_INTERFACE)
  1.1559 +    bool DontAskInstanceForScriptable() GET_IT(DONT_ASK_INSTANCE_FOR_SCRIPTABLE)
  1.1560 +    bool ClassInfoInterfacesOnly()      GET_IT(CLASSINFO_INTERFACES_ONLY)
  1.1561 +    bool AllowPropModsDuringResolve()   GET_IT(ALLOW_PROP_MODS_DURING_RESOLVE)
  1.1562 +    bool AllowPropModsToPrototype()     GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE)
  1.1563 +    bool IsGlobalObject()               GET_IT(IS_GLOBAL_OBJECT)
  1.1564 +    bool DontReflectInterfaceNames()    GET_IT(DONT_REFLECT_INTERFACE_NAMES)
  1.1565 +
  1.1566 +#undef GET_IT
  1.1567 +};
  1.1568 +
  1.1569 +/***************************************************************************/
  1.1570 +
  1.1571 +// XPCNativeScriptableShared is used to hold the JSClass and the
  1.1572 +// associated scriptable flags for XPCWrappedNatives. These are shared across
  1.1573 +// the runtime and are garbage collected by xpconnect. We *used* to just store
  1.1574 +// this inside the XPCNativeScriptableInfo (usually owned by instances of
  1.1575 +// XPCWrappedNativeProto. This had two problems... It was wasteful, and it
  1.1576 +// was a big problem when wrappers are reparented to different scopes (and
  1.1577 +// thus different protos (the DOM does this).
  1.1578 +
  1.1579 +// We maintain the invariant that every JSClass for which ext.isWrappedNative
  1.1580 +// is true is a contained in an instance of this struct, and can thus be cast
  1.1581 +// to it.
  1.1582 +struct XPCWrappedNativeJSClass
  1.1583 +{
  1.1584 +    js::Class base;
  1.1585 +    uint32_t interfacesBitmap;
  1.1586 +};
  1.1587 +
  1.1588 +class XPCNativeScriptableShared
  1.1589 +{
  1.1590 +public:
  1.1591 +    const XPCNativeScriptableFlags& GetFlags() const {return mFlags;}
  1.1592 +    uint32_t                        GetInterfacesBitmap() const
  1.1593 +        {return mJSClass.interfacesBitmap;}
  1.1594 +    const JSClass*                  GetJSClass()
  1.1595 +        {return Jsvalify(&mJSClass.base);}
  1.1596 +
  1.1597 +    XPCNativeScriptableShared(uint32_t aFlags, char* aName,
  1.1598 +                              uint32_t interfacesBitmap)
  1.1599 +        : mFlags(aFlags)
  1.1600 +        {memset(&mJSClass, 0, sizeof(mJSClass));
  1.1601 +         mJSClass.base.name = aName;  // take ownership
  1.1602 +         mJSClass.interfacesBitmap = interfacesBitmap;
  1.1603 +         MOZ_COUNT_CTOR(XPCNativeScriptableShared);}
  1.1604 +
  1.1605 +    ~XPCNativeScriptableShared()
  1.1606 +        {if (mJSClass.base.name)nsMemory::Free((void*)mJSClass.base.name);
  1.1607 +         MOZ_COUNT_DTOR(XPCNativeScriptableShared);}
  1.1608 +
  1.1609 +    char* TransferNameOwnership()
  1.1610 +        {char* name=(char*)mJSClass.base.name; mJSClass.base.name = nullptr;
  1.1611 +        return name;}
  1.1612 +
  1.1613 +    void PopulateJSClass();
  1.1614 +
  1.1615 +    void Mark()       {mFlags.Mark();}
  1.1616 +    void Unmark()     {mFlags.Unmark();}
  1.1617 +    bool IsMarked() const {return mFlags.IsMarked();}
  1.1618 +
  1.1619 +private:
  1.1620 +    XPCNativeScriptableFlags mFlags;
  1.1621 +    XPCWrappedNativeJSClass  mJSClass;
  1.1622 +};
  1.1623 +
  1.1624 +/***************************************************************************/
  1.1625 +// XPCNativeScriptableInfo is used to hold the nsIXPCScriptable state for a
  1.1626 +// given class or instance.
  1.1627 +
  1.1628 +class XPCNativeScriptableInfo
  1.1629 +{
  1.1630 +public:
  1.1631 +    static XPCNativeScriptableInfo*
  1.1632 +    Construct(const XPCNativeScriptableCreateInfo* sci);
  1.1633 +
  1.1634 +    nsIXPCScriptable*
  1.1635 +    GetCallback() const {return mCallback;}
  1.1636 +
  1.1637 +    const XPCNativeScriptableFlags&
  1.1638 +    GetFlags() const      {return mShared->GetFlags();}
  1.1639 +
  1.1640 +    uint32_t
  1.1641 +    GetInterfacesBitmap() const {return mShared->GetInterfacesBitmap();}
  1.1642 +
  1.1643 +    const JSClass*
  1.1644 +    GetJSClass()          {return mShared->GetJSClass();}
  1.1645 +
  1.1646 +    XPCNativeScriptableShared*
  1.1647 +    GetScriptableShared() {return mShared;}
  1.1648 +
  1.1649 +    void
  1.1650 +    SetCallback(nsIXPCScriptable* s) {mCallback = s;}
  1.1651 +    void
  1.1652 +    SetCallback(already_AddRefed<nsIXPCScriptable>&& s) {mCallback = s;}
  1.1653 +
  1.1654 +    void
  1.1655 +    SetScriptableShared(XPCNativeScriptableShared* shared) {mShared = shared;}
  1.1656 +
  1.1657 +    void Mark() {
  1.1658 +        if (mShared)
  1.1659 +            mShared->Mark();
  1.1660 +    }
  1.1661 +
  1.1662 +    void TraceJS(JSTracer *trc) {}
  1.1663 +    void AutoTrace(JSTracer *trc) {}
  1.1664 +
  1.1665 +protected:
  1.1666 +    XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nullptr,
  1.1667 +                            XPCNativeScriptableShared* shared = nullptr)
  1.1668 +        : mCallback(scriptable), mShared(shared)
  1.1669 +                               {MOZ_COUNT_CTOR(XPCNativeScriptableInfo);}
  1.1670 +public:
  1.1671 +    ~XPCNativeScriptableInfo() {MOZ_COUNT_DTOR(XPCNativeScriptableInfo);}
  1.1672 +private:
  1.1673 +
  1.1674 +    // disable copy ctor and assignment
  1.1675 +    XPCNativeScriptableInfo(const XPCNativeScriptableInfo& r); // not implemented
  1.1676 +    XPCNativeScriptableInfo& operator= (const XPCNativeScriptableInfo& r); // not implemented
  1.1677 +
  1.1678 +private:
  1.1679 +    nsCOMPtr<nsIXPCScriptable>  mCallback;
  1.1680 +    XPCNativeScriptableShared*  mShared;
  1.1681 +};
  1.1682 +
  1.1683 +/***************************************************************************/
  1.1684 +// XPCNativeScriptableCreateInfo is used in creating new wrapper and protos.
  1.1685 +// it abstracts out the scriptable interface pointer and the flags. After
  1.1686 +// creation these are factored differently using XPCNativeScriptableInfo.
  1.1687 +
  1.1688 +class MOZ_STACK_CLASS XPCNativeScriptableCreateInfo
  1.1689 +{
  1.1690 +public:
  1.1691 +
  1.1692 +    XPCNativeScriptableCreateInfo(const XPCNativeScriptableInfo& si)
  1.1693 +        : mCallback(si.GetCallback()), mFlags(si.GetFlags()),
  1.1694 +          mInterfacesBitmap(si.GetInterfacesBitmap()) {}
  1.1695 +
  1.1696 +    XPCNativeScriptableCreateInfo(already_AddRefed<nsIXPCScriptable>&& callback,
  1.1697 +                                  XPCNativeScriptableFlags flags,
  1.1698 +                                  uint32_t interfacesBitmap)
  1.1699 +        : mCallback(callback), mFlags(flags),
  1.1700 +          mInterfacesBitmap(interfacesBitmap) {}
  1.1701 +
  1.1702 +    XPCNativeScriptableCreateInfo()
  1.1703 +        : mFlags(0), mInterfacesBitmap(0) {}
  1.1704 +
  1.1705 +
  1.1706 +    nsIXPCScriptable*
  1.1707 +    GetCallback() const {return mCallback;}
  1.1708 +
  1.1709 +    const XPCNativeScriptableFlags&
  1.1710 +    GetFlags() const      {return mFlags;}
  1.1711 +
  1.1712 +    uint32_t
  1.1713 +    GetInterfacesBitmap() const     {return mInterfacesBitmap;}
  1.1714 +
  1.1715 +    void
  1.1716 +    SetCallback(already_AddRefed<nsIXPCScriptable>&& callback)
  1.1717 +        {mCallback = callback;}
  1.1718 +
  1.1719 +    void
  1.1720 +    SetFlags(const XPCNativeScriptableFlags& flags)  {mFlags = flags;}
  1.1721 +
  1.1722 +    void
  1.1723 +    SetInterfacesBitmap(uint32_t interfacesBitmap)
  1.1724 +        {mInterfacesBitmap = interfacesBitmap;}
  1.1725 +
  1.1726 +private:
  1.1727 +    nsCOMPtr<nsIXPCScriptable>  mCallback;
  1.1728 +    XPCNativeScriptableFlags    mFlags;
  1.1729 +    uint32_t                    mInterfacesBitmap;
  1.1730 +};
  1.1731 +
  1.1732 +/***********************************************/
  1.1733 +// XPCWrappedNativeProto hold the additional shared wrapper data
  1.1734 +// for XPCWrappedNative whose native objects expose nsIClassInfo.
  1.1735 +
  1.1736 +class XPCWrappedNativeProto
  1.1737 +{
  1.1738 +public:
  1.1739 +    static XPCWrappedNativeProto*
  1.1740 +    GetNewOrUsed(XPCWrappedNativeScope* scope,
  1.1741 +                 nsIClassInfo* classInfo,
  1.1742 +                 const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
  1.1743 +                 bool callPostCreatePrototype = true);
  1.1744 +
  1.1745 +    XPCWrappedNativeScope*
  1.1746 +    GetScope()   const {return mScope;}
  1.1747 +
  1.1748 +    XPCJSRuntime*
  1.1749 +    GetRuntime() const {return mScope->GetRuntime();}
  1.1750 +
  1.1751 +    JSObject*
  1.1752 +    GetJSProtoObject() const {
  1.1753 +        JS::ExposeObjectToActiveJS(mJSProtoObject);
  1.1754 +        return mJSProtoObject;
  1.1755 +    }
  1.1756 +
  1.1757 +    nsIClassInfo*
  1.1758 +    GetClassInfo()     const {return mClassInfo;}
  1.1759 +
  1.1760 +    XPCNativeSet*
  1.1761 +    GetSet()           const {return mSet;}
  1.1762 +
  1.1763 +    XPCNativeScriptableInfo*
  1.1764 +    GetScriptableInfo()   {return mScriptableInfo;}
  1.1765 +
  1.1766 +    uint32_t
  1.1767 +    GetClassInfoFlags() const {return mClassInfoFlags;}
  1.1768 +
  1.1769 +#ifdef GET_IT
  1.1770 +#undef GET_IT
  1.1771 +#endif
  1.1772 +#define GET_IT(f_) const {return !!(mClassInfoFlags & nsIClassInfo:: f_ );}
  1.1773 +
  1.1774 +    bool ClassIsSingleton()           GET_IT(SINGLETON)
  1.1775 +    bool ClassIsDOMObject()           GET_IT(DOM_OBJECT)
  1.1776 +    bool ClassIsPluginObject()        GET_IT(PLUGIN_OBJECT)
  1.1777 +
  1.1778 +#undef GET_IT
  1.1779 +
  1.1780 +    void SetScriptableInfo(XPCNativeScriptableInfo* si)
  1.1781 +        {MOZ_ASSERT(!mScriptableInfo, "leak here!"); mScriptableInfo = si;}
  1.1782 +
  1.1783 +    bool CallPostCreatePrototype();
  1.1784 +    void JSProtoObjectFinalized(js::FreeOp *fop, JSObject *obj);
  1.1785 +
  1.1786 +    void SystemIsBeingShutDown();
  1.1787 +
  1.1788 +    void DebugDump(int16_t depth);
  1.1789 +
  1.1790 +    void TraceSelf(JSTracer *trc) {
  1.1791 +        if (mJSProtoObject)
  1.1792 +            mJSProtoObject.trace(trc, "XPCWrappedNativeProto::mJSProtoObject");
  1.1793 +    }
  1.1794 +
  1.1795 +    void TraceInside(JSTracer *trc) {
  1.1796 +        if (JS_IsGCMarkingTracer(trc)) {
  1.1797 +            mSet->Mark();
  1.1798 +            if (mScriptableInfo)
  1.1799 +                mScriptableInfo->Mark();
  1.1800 +        }
  1.1801 +
  1.1802 +        GetScope()->TraceInside(trc);
  1.1803 +    }
  1.1804 +
  1.1805 +    void TraceJS(JSTracer *trc) {
  1.1806 +        TraceSelf(trc);
  1.1807 +        TraceInside(trc);
  1.1808 +    }
  1.1809 +
  1.1810 +    void WriteBarrierPre(JSRuntime* rt)
  1.1811 +    {
  1.1812 +        if (JS::IsIncrementalBarrierNeeded(rt) && mJSProtoObject)
  1.1813 +            mJSProtoObject.writeBarrierPre(rt);
  1.1814 +    }
  1.1815 +
  1.1816 +    // NOP. This is just here to make the AutoMarkingPtr code compile.
  1.1817 +    inline void AutoTrace(JSTracer* trc) {}
  1.1818 +
  1.1819 +    // Yes, we *do* need to mark the mScriptableInfo in both cases.
  1.1820 +    void Mark() const
  1.1821 +        {mSet->Mark();
  1.1822 +         if (mScriptableInfo) mScriptableInfo->Mark();}
  1.1823 +
  1.1824 +#ifdef DEBUG
  1.1825 +    void ASSERT_SetNotMarked() const {mSet->ASSERT_NotMarked();}
  1.1826 +#endif
  1.1827 +
  1.1828 +    ~XPCWrappedNativeProto();
  1.1829 +
  1.1830 +protected:
  1.1831 +    // disable copy ctor and assignment
  1.1832 +    XPCWrappedNativeProto(const XPCWrappedNativeProto& r); // not implemented
  1.1833 +    XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r); // not implemented
  1.1834 +
  1.1835 +    // hide ctor
  1.1836 +    XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
  1.1837 +                          nsIClassInfo* ClassInfo,
  1.1838 +                          uint32_t ClassInfoFlags,
  1.1839 +                          XPCNativeSet* Set);
  1.1840 +
  1.1841 +    bool Init(const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
  1.1842 +              bool callPostCreatePrototype);
  1.1843 +
  1.1844 +private:
  1.1845 +#ifdef DEBUG
  1.1846 +    static int32_t gDEBUG_LiveProtoCount;
  1.1847 +#endif
  1.1848 +
  1.1849 +private:
  1.1850 +    XPCWrappedNativeScope*   mScope;
  1.1851 +    JS::ObjectPtr            mJSProtoObject;
  1.1852 +    nsCOMPtr<nsIClassInfo>   mClassInfo;
  1.1853 +    uint32_t                 mClassInfoFlags;
  1.1854 +    XPCNativeSet*            mSet;
  1.1855 +    XPCNativeScriptableInfo* mScriptableInfo;
  1.1856 +};
  1.1857 +
  1.1858 +/***********************************************/
  1.1859 +// XPCWrappedNativeTearOff represents the info needed to make calls to one
  1.1860 +// interface on the underlying native object of a XPCWrappedNative.
  1.1861 +
  1.1862 +class XPCWrappedNativeTearOff
  1.1863 +{
  1.1864 +public:
  1.1865 +    bool IsAvailable() const {return mInterface == nullptr;}
  1.1866 +    bool IsReserved()  const {return mInterface == (XPCNativeInterface*)1;}
  1.1867 +    bool IsValid()     const {return !IsAvailable() && !IsReserved();}
  1.1868 +    void   SetReserved()       {mInterface = (XPCNativeInterface*)1;}
  1.1869 +
  1.1870 +    XPCNativeInterface* GetInterface() const {return mInterface;}
  1.1871 +    nsISupports*        GetNative()    const {return mNative;}
  1.1872 +    JSObject*           GetJSObject();
  1.1873 +    JSObject*           GetJSObjectPreserveColor() const;
  1.1874 +    void SetInterface(XPCNativeInterface*  Interface) {mInterface = Interface;}
  1.1875 +    void SetNative(nsISupports*  Native)              {mNative = Native;}
  1.1876 +    void SetJSObject(JSObject*  JSObj);
  1.1877 +
  1.1878 +    void JSObjectFinalized() {SetJSObject(nullptr);}
  1.1879 +
  1.1880 +    XPCWrappedNativeTearOff()
  1.1881 +        : mInterface(nullptr), mNative(nullptr), mJSObject(nullptr) {}
  1.1882 +    ~XPCWrappedNativeTearOff();
  1.1883 +
  1.1884 +    // NOP. This is just here to make the AutoMarkingPtr code compile.
  1.1885 +    inline void TraceJS(JSTracer* trc) {}
  1.1886 +    inline void AutoTrace(JSTracer* trc) {}
  1.1887 +
  1.1888 +    void Mark()       {mJSObject = (JSObject*)(intptr_t(mJSObject) | 1);}
  1.1889 +    void Unmark()     {mJSObject = (JSObject*)(intptr_t(mJSObject) & ~1);}
  1.1890 +    bool IsMarked() const {return !!(intptr_t(mJSObject) & 1);}
  1.1891 +
  1.1892 +private:
  1.1893 +    XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) MOZ_DELETE;
  1.1894 +    XPCWrappedNativeTearOff& operator= (const XPCWrappedNativeTearOff& r) MOZ_DELETE;
  1.1895 +
  1.1896 +private:
  1.1897 +    XPCNativeInterface* mInterface;
  1.1898 +    nsISupports*        mNative;
  1.1899 +    JSObject*           mJSObject;
  1.1900 +};
  1.1901 +
  1.1902 +/***********************************************/
  1.1903 +// XPCWrappedNativeTearOffChunk is a collections of XPCWrappedNativeTearOff
  1.1904 +// objects. It lets us allocate a set of XPCWrappedNativeTearOff objects and
  1.1905 +// link the sets - rather than only having the option of linking single
  1.1906 +// XPCWrappedNativeTearOff objects.
  1.1907 +//
  1.1908 +// The value of XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK can be tuned at buildtime
  1.1909 +// to balance between the code of allocations of additional chunks and the waste
  1.1910 +// of space for ununsed XPCWrappedNativeTearOff objects.
  1.1911 +
  1.1912 +#define XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK 1
  1.1913 +
  1.1914 +class XPCWrappedNativeTearOffChunk
  1.1915 +{
  1.1916 +friend class XPCWrappedNative;
  1.1917 +private:
  1.1918 +    XPCWrappedNativeTearOffChunk() : mNextChunk(nullptr) {}
  1.1919 +    ~XPCWrappedNativeTearOffChunk() {delete mNextChunk;}
  1.1920 +
  1.1921 +private:
  1.1922 +    XPCWrappedNativeTearOff mTearOffs[XPC_WRAPPED_NATIVE_TEAROFFS_PER_CHUNK];
  1.1923 +    XPCWrappedNativeTearOffChunk* mNextChunk;
  1.1924 +};
  1.1925 +
  1.1926 +void *xpc_GetJSPrivate(JSObject *obj);
  1.1927 +
  1.1928 +/***************************************************************************/
  1.1929 +// XPCWrappedNative the wrapper around one instance of a native xpcom object
  1.1930 +// to be used from JavaScript.
  1.1931 +
  1.1932 +class XPCWrappedNative : public nsIXPConnectWrappedNative
  1.1933 +{
  1.1934 +public:
  1.1935 +    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  1.1936 +    NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
  1.1937 +    NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
  1.1938 +
  1.1939 +    NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
  1.1940 +
  1.1941 +    nsIPrincipal* GetObjectPrincipal() const;
  1.1942 +
  1.1943 +    bool
  1.1944 +    IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); }
  1.1945 +
  1.1946 +#define XPC_SCOPE_WORD(s)   (intptr_t(s))
  1.1947 +#define XPC_SCOPE_MASK      (intptr_t(0x3))
  1.1948 +#define XPC_SCOPE_TAG       (intptr_t(0x1))
  1.1949 +#define XPC_WRAPPER_EXPIRED (intptr_t(0x2))
  1.1950 +
  1.1951 +    static inline bool
  1.1952 +    IsTaggedScope(XPCWrappedNativeScope* s)
  1.1953 +        {return XPC_SCOPE_WORD(s) & XPC_SCOPE_TAG;}
  1.1954 +
  1.1955 +    static inline XPCWrappedNativeScope*
  1.1956 +    TagScope(XPCWrappedNativeScope* s)
  1.1957 +        {MOZ_ASSERT(!IsTaggedScope(s), "bad pointer!");
  1.1958 +         return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) | XPC_SCOPE_TAG);}
  1.1959 +
  1.1960 +    static inline XPCWrappedNativeScope*
  1.1961 +    UnTagScope(XPCWrappedNativeScope* s)
  1.1962 +        {return (XPCWrappedNativeScope*)(XPC_SCOPE_WORD(s) & ~XPC_SCOPE_TAG);}
  1.1963 +
  1.1964 +    inline bool
  1.1965 +    IsWrapperExpired() const
  1.1966 +        {return XPC_SCOPE_WORD(mMaybeScope) & XPC_WRAPPER_EXPIRED;}
  1.1967 +
  1.1968 +    bool
  1.1969 +    HasProto() const {return !IsTaggedScope(mMaybeScope);}
  1.1970 +
  1.1971 +    XPCWrappedNativeProto*
  1.1972 +    GetProto() const
  1.1973 +        {return HasProto() ?
  1.1974 +         (XPCWrappedNativeProto*)
  1.1975 +         (XPC_SCOPE_WORD(mMaybeProto) & ~XPC_SCOPE_MASK) : nullptr;}
  1.1976 +
  1.1977 +    void SetProto(XPCWrappedNativeProto* p);
  1.1978 +
  1.1979 +    XPCWrappedNativeScope*
  1.1980 +    GetScope() const
  1.1981 +        {return GetProto() ? GetProto()->GetScope() :
  1.1982 +         (XPCWrappedNativeScope*)
  1.1983 +         (XPC_SCOPE_WORD(mMaybeScope) & ~XPC_SCOPE_MASK);}
  1.1984 +
  1.1985 +    nsISupports*
  1.1986 +    GetIdentityObject() const {return mIdentity;}
  1.1987 +
  1.1988 +    /**
  1.1989 +     * This getter clears the gray bit before handing out the JSObject which
  1.1990 +     * means that the object is guaranteed to be kept alive past the next CC.
  1.1991 +     */
  1.1992 +    JSObject*
  1.1993 +    GetFlatJSObject() const
  1.1994 +    {
  1.1995 +        JS::ExposeObjectToActiveJS(mFlatJSObject);
  1.1996 +        return mFlatJSObject;
  1.1997 +    }
  1.1998 +
  1.1999 +    /**
  1.2000 +     * This getter does not change the color of the JSObject meaning that the
  1.2001 +     * object returned is not guaranteed to be kept alive past the next CC.
  1.2002 +     *
  1.2003 +     * This should only be called if you are certain that the return value won't
  1.2004 +     * be passed into a JS API function and that it won't be stored without
  1.2005 +     * being rooted (or otherwise signaling the stored value to the CC).
  1.2006 +     */
  1.2007 +    JSObject*
  1.2008 +    GetFlatJSObjectPreserveColor() const {return mFlatJSObject;}
  1.2009 +
  1.2010 +    XPCNativeSet*
  1.2011 +    GetSet() const {return mSet;}
  1.2012 +
  1.2013 +    void
  1.2014 +    SetSet(XPCNativeSet* set) {mSet = set;}
  1.2015 +
  1.2016 +    static XPCWrappedNative* Get(JSObject *obj) {
  1.2017 +        MOZ_ASSERT(IS_WN_REFLECTOR(obj));
  1.2018 +        return (XPCWrappedNative*)js::GetObjectPrivate(obj);
  1.2019 +    }
  1.2020 +
  1.2021 +private:
  1.2022 +    inline void
  1.2023 +    ExpireWrapper()
  1.2024 +        {mMaybeScope = (XPCWrappedNativeScope*)
  1.2025 +                       (XPC_SCOPE_WORD(mMaybeScope) | XPC_WRAPPER_EXPIRED);}
  1.2026 +
  1.2027 +public:
  1.2028 +
  1.2029 +    XPCNativeScriptableInfo*
  1.2030 +    GetScriptableInfo() const {return mScriptableInfo;}
  1.2031 +
  1.2032 +    nsIXPCScriptable*      // call this wrong and you deserve to crash
  1.2033 +    GetScriptableCallback() const  {return mScriptableInfo->GetCallback();}
  1.2034 +
  1.2035 +    nsIClassInfo*
  1.2036 +    GetClassInfo() const {return IsValid() && HasProto() ?
  1.2037 +                            GetProto()->GetClassInfo() : nullptr;}
  1.2038 +
  1.2039 +    bool
  1.2040 +    HasMutatedSet() const {return IsValid() &&
  1.2041 +                                  (!HasProto() ||
  1.2042 +                                   GetSet() != GetProto()->GetSet());}
  1.2043 +
  1.2044 +    XPCJSRuntime*
  1.2045 +    GetRuntime() const {XPCWrappedNativeScope* scope = GetScope();
  1.2046 +                        return scope ? scope->GetRuntime() : nullptr;}
  1.2047 +
  1.2048 +    static nsresult
  1.2049 +    WrapNewGlobal(xpcObjectHelper &nativeHelper,
  1.2050 +                  nsIPrincipal *principal, bool initStandardClasses,
  1.2051 +                  JS::CompartmentOptions& aOptions,
  1.2052 +                  XPCWrappedNative **wrappedGlobal);
  1.2053 +
  1.2054 +    static nsresult
  1.2055 +    GetNewOrUsed(xpcObjectHelper& helper,
  1.2056 +                 XPCWrappedNativeScope* Scope,
  1.2057 +                 XPCNativeInterface* Interface,
  1.2058 +                 XPCWrappedNative** wrapper);
  1.2059 +
  1.2060 +public:
  1.2061 +    static nsresult
  1.2062 +    GetUsedOnly(nsISupports* Object,
  1.2063 +                XPCWrappedNativeScope* Scope,
  1.2064 +                XPCNativeInterface* Interface,
  1.2065 +                XPCWrappedNative** wrapper);
  1.2066 +
  1.2067 +    static nsresult
  1.2068 +    ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
  1.2069 +                           XPCWrappedNativeScope* aNewScope,
  1.2070 +                           JS::HandleObject aNewParent,
  1.2071 +                           nsISupports* aCOMObj);
  1.2072 +
  1.2073 +    nsresult RescueOrphans();
  1.2074 +
  1.2075 +    void FlatJSObjectFinalized();
  1.2076 +
  1.2077 +    void SystemIsBeingShutDown();
  1.2078 +
  1.2079 +    enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
  1.2080 +
  1.2081 +    static bool CallMethod(XPCCallContext& ccx,
  1.2082 +                           CallMode mode = CALL_METHOD);
  1.2083 +
  1.2084 +    static bool GetAttribute(XPCCallContext& ccx)
  1.2085 +        {return CallMethod(ccx, CALL_GETTER);}
  1.2086 +
  1.2087 +    static bool SetAttribute(XPCCallContext& ccx)
  1.2088 +        {return CallMethod(ccx, CALL_SETTER);}
  1.2089 +
  1.2090 +    inline bool HasInterfaceNoQI(const nsIID& iid);
  1.2091 +
  1.2092 +    XPCWrappedNativeTearOff* LocateTearOff(XPCNativeInterface* aInterface);
  1.2093 +    XPCWrappedNativeTearOff* FindTearOff(XPCNativeInterface* aInterface,
  1.2094 +                                         bool needJSObject = false,
  1.2095 +                                         nsresult* pError = nullptr);
  1.2096 +    void Mark() const
  1.2097 +    {
  1.2098 +        mSet->Mark();
  1.2099 +        if (mScriptableInfo) mScriptableInfo->Mark();
  1.2100 +        if (HasProto()) GetProto()->Mark();
  1.2101 +    }
  1.2102 +
  1.2103 +    // Yes, we *do* need to mark the mScriptableInfo in both cases.
  1.2104 +    inline void TraceInside(JSTracer *trc) {
  1.2105 +        if (JS_IsGCMarkingTracer(trc)) {
  1.2106 +            mSet->Mark();
  1.2107 +            if (mScriptableInfo)
  1.2108 +                mScriptableInfo->Mark();
  1.2109 +        }
  1.2110 +        if (HasProto())
  1.2111 +            GetProto()->TraceSelf(trc);
  1.2112 +        else
  1.2113 +            GetScope()->TraceInside(trc);
  1.2114 +        if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject))
  1.2115 +        {
  1.2116 +            xpc::TraceXPCGlobal(trc, mFlatJSObject);
  1.2117 +        }
  1.2118 +    }
  1.2119 +
  1.2120 +    void TraceJS(JSTracer *trc) {
  1.2121 +        TraceInside(trc);
  1.2122 +    }
  1.2123 +
  1.2124 +    void TraceSelf(JSTracer *trc) {
  1.2125 +        // If this got called, we're being kept alive by someone who really
  1.2126 +        // needs us alive and whole.  Do not let our mFlatJSObject go away.
  1.2127 +        // This is the only time we should be tracing our mFlatJSObject,
  1.2128 +        // normally somebody else is doing that. Be careful not to trace the
  1.2129 +        // bogus INVALID_OBJECT value we can have during init, though.
  1.2130 +        if (mFlatJSObject) {
  1.2131 +            JS_CallTenuredObjectTracer(trc, &mFlatJSObject,
  1.2132 +                                       "XPCWrappedNative::mFlatJSObject");
  1.2133 +        }
  1.2134 +    }
  1.2135 +
  1.2136 +    static void Trace(JSTracer *trc, JSObject *obj);
  1.2137 +
  1.2138 +    void AutoTrace(JSTracer *trc) {
  1.2139 +        TraceSelf(trc);
  1.2140 +    }
  1.2141 +
  1.2142 +#ifdef DEBUG
  1.2143 +    void ASSERT_SetsNotMarked() const
  1.2144 +        {mSet->ASSERT_NotMarked();
  1.2145 +         if (HasProto()){GetProto()->ASSERT_SetNotMarked();}}
  1.2146 +#endif
  1.2147 +
  1.2148 +    inline void SweepTearOffs();
  1.2149 +
  1.2150 +    // Returns a string that shuld be free'd using JS_smprintf_free (or null).
  1.2151 +    char* ToString(XPCWrappedNativeTearOff* to = nullptr) const;
  1.2152 +
  1.2153 +    static void GatherProtoScriptableCreateInfo(nsIClassInfo* classInfo,
  1.2154 +                                                XPCNativeScriptableCreateInfo& sciProto);
  1.2155 +
  1.2156 +    bool HasExternalReference() const {return mRefCnt > 1;}
  1.2157 +
  1.2158 +    void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
  1.2159 +
  1.2160 +    // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
  1.2161 +protected:
  1.2162 +    XPCWrappedNative(); // not implemented
  1.2163 +
  1.2164 +    // This ctor is used if this object will have a proto.
  1.2165 +    XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
  1.2166 +                     XPCWrappedNativeProto* aProto);
  1.2167 +
  1.2168 +    // This ctor is used if this object will NOT have a proto.
  1.2169 +    XPCWrappedNative(already_AddRefed<nsISupports>&& aIdentity,
  1.2170 +                     XPCWrappedNativeScope* aScope,
  1.2171 +                     XPCNativeSet* aSet);
  1.2172 +
  1.2173 +    virtual ~XPCWrappedNative();
  1.2174 +    void Destroy();
  1.2175 +
  1.2176 +    void UpdateScriptableInfo(XPCNativeScriptableInfo *si);
  1.2177 +
  1.2178 +private:
  1.2179 +    enum {
  1.2180 +        // Flags bits for mFlatJSObject:
  1.2181 +        FLAT_JS_OBJECT_VALID = JS_BIT(0)
  1.2182 +    };
  1.2183 +
  1.2184 +private:
  1.2185 +
  1.2186 +    bool Init(JS::HandleObject parent, const XPCNativeScriptableCreateInfo* sci);
  1.2187 +    bool FinishInit();
  1.2188 +
  1.2189 +    bool ExtendSet(XPCNativeInterface* aInterface);
  1.2190 +
  1.2191 +    nsresult InitTearOff(XPCWrappedNativeTearOff* aTearOff,
  1.2192 +                         XPCNativeInterface* aInterface,
  1.2193 +                         bool needJSObject);
  1.2194 +
  1.2195 +    bool InitTearOffJSObject(XPCWrappedNativeTearOff* to);
  1.2196 +
  1.2197 +public:
  1.2198 +    static const XPCNativeScriptableCreateInfo& GatherScriptableCreateInfo(nsISupports* obj,
  1.2199 +                                                                           nsIClassInfo* classInfo,
  1.2200 +                                                                           XPCNativeScriptableCreateInfo& sciProto,
  1.2201 +                                                                           XPCNativeScriptableCreateInfo& sciWrapper);
  1.2202 +
  1.2203 +private:
  1.2204 +    union
  1.2205 +    {
  1.2206 +        XPCWrappedNativeScope*   mMaybeScope;
  1.2207 +        XPCWrappedNativeProto*   mMaybeProto;
  1.2208 +    };
  1.2209 +    XPCNativeSet*                mSet;
  1.2210 +    JS::TenuredHeap<JSObject*>   mFlatJSObject;
  1.2211 +    XPCNativeScriptableInfo*     mScriptableInfo;
  1.2212 +    XPCWrappedNativeTearOffChunk mFirstChunk;
  1.2213 +};
  1.2214 +
  1.2215 +/***************************************************************************
  1.2216 +****************************************************************************
  1.2217 +*
  1.2218 +* Core classes for wrapped JSObject for use from native code...
  1.2219 +*
  1.2220 +****************************************************************************
  1.2221 +***************************************************************************/
  1.2222 +
  1.2223 +// this interfaces exists so we can refcount nsXPCWrappedJSClass
  1.2224 +// {2453EBA0-A9B8-11d2-BA64-00805F8A5DD7}
  1.2225 +#define NS_IXPCONNECT_WRAPPED_JS_CLASS_IID                                    \
  1.2226 +{ 0x2453eba0, 0xa9b8, 0x11d2,                                                 \
  1.2227 +  { 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
  1.2228 +
  1.2229 +class nsIXPCWrappedJSClass : public nsISupports
  1.2230 +{
  1.2231 +public:
  1.2232 +    NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
  1.2233 +    NS_IMETHOD DebugDump(int16_t depth) = 0;
  1.2234 +};
  1.2235 +
  1.2236 +NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPCWrappedJSClass,
  1.2237 +                              NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
  1.2238 +
  1.2239 +/*************************/
  1.2240 +// nsXPCWrappedJSClass represents the sharable factored out common code and
  1.2241 +// data for nsXPCWrappedJS instances for the same interface type.
  1.2242 +
  1.2243 +class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass
  1.2244 +{
  1.2245 +    // all the interface method declarations...
  1.2246 +    NS_DECL_ISUPPORTS
  1.2247 +    NS_IMETHOD DebugDump(int16_t depth);
  1.2248 +public:
  1.2249 +
  1.2250 +    static already_AddRefed<nsXPCWrappedJSClass>
  1.2251 +    GetNewOrUsed(JSContext* cx,
  1.2252 +                 REFNSIID aIID);
  1.2253 +
  1.2254 +    REFNSIID GetIID() const {return mIID;}
  1.2255 +    XPCJSRuntime* GetRuntime() const {return mRuntime;}
  1.2256 +    nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
  1.2257 +    const char* GetInterfaceName();
  1.2258 +
  1.2259 +    static bool IsWrappedJS(nsISupports* aPtr);
  1.2260 +
  1.2261 +    NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
  1.2262 +                                       void** aInstancePtr);
  1.2263 +
  1.2264 +    JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj);
  1.2265 +
  1.2266 +    NS_IMETHOD CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
  1.2267 +                          const XPTMethodDescriptor* info,
  1.2268 +                          nsXPTCMiniVariant* params);
  1.2269 +
  1.2270 +    JSObject*  CallQueryInterfaceOnJSObject(JSContext* cx,
  1.2271 +                                            JSObject* jsobj, REFNSIID aIID);
  1.2272 +
  1.2273 +    static nsresult BuildPropertyEnumerator(XPCCallContext& ccx,
  1.2274 +                                            JSObject* aJSObj,
  1.2275 +                                            nsISimpleEnumerator** aEnumerate);
  1.2276 +
  1.2277 +    static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
  1.2278 +                                              JSObject* aJSObj,
  1.2279 +                                              const nsAString& aName,
  1.2280 +                                              nsIVariant** aResult);
  1.2281 +
  1.2282 +    virtual ~nsXPCWrappedJSClass();
  1.2283 +
  1.2284 +    static nsresult CheckForException(XPCCallContext & ccx,
  1.2285 +                                      const char * aPropertyName,
  1.2286 +                                      const char * anInterfaceName,
  1.2287 +                                      bool aForceReport);
  1.2288 +private:
  1.2289 +    nsXPCWrappedJSClass();   // not implemented
  1.2290 +    nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID,
  1.2291 +                        nsIInterfaceInfo* aInfo);
  1.2292 +
  1.2293 +    bool IsReflectable(uint16_t i) const
  1.2294 +        {return (bool)(mDescriptors[i/32] & (1 << (i%32)));}
  1.2295 +    void SetReflectable(uint16_t i, bool b)
  1.2296 +        {if (b) mDescriptors[i/32] |= (1 << (i%32));
  1.2297 +         else mDescriptors[i/32] &= ~(1 << (i%32));}
  1.2298 +
  1.2299 +    bool GetArraySizeFromParam(JSContext* cx,
  1.2300 +                               const XPTMethodDescriptor* method,
  1.2301 +                               const nsXPTParamInfo& param,
  1.2302 +                               uint16_t methodIndex,
  1.2303 +                               uint8_t paramIndex,
  1.2304 +                               nsXPTCMiniVariant* params,
  1.2305 +                               uint32_t* result);
  1.2306 +
  1.2307 +    bool GetInterfaceTypeFromParam(JSContext* cx,
  1.2308 +                                   const XPTMethodDescriptor* method,
  1.2309 +                                   const nsXPTParamInfo& param,
  1.2310 +                                   uint16_t methodIndex,
  1.2311 +                                   const nsXPTType& type,
  1.2312 +                                   nsXPTCMiniVariant* params,
  1.2313 +                                   nsID* result);
  1.2314 +
  1.2315 +    void CleanupPointerArray(const nsXPTType& datum_type,
  1.2316 +                             uint32_t array_count,
  1.2317 +                             void** arrayp);
  1.2318 +
  1.2319 +    void CleanupPointerTypeObject(const nsXPTType& type,
  1.2320 +                                  void** pp);
  1.2321 +
  1.2322 +private:
  1.2323 +    XPCJSRuntime* mRuntime;
  1.2324 +    nsCOMPtr<nsIInterfaceInfo> mInfo;
  1.2325 +    char* mName;
  1.2326 +    nsIID mIID;
  1.2327 +    uint32_t* mDescriptors;
  1.2328 +};
  1.2329 +
  1.2330 +/*************************/
  1.2331 +// nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
  1.2332 +// nsXPCWrappedJS objects are chained together to represent the various
  1.2333 +// interface on the single underlying (possibly aggregate) JSObject.
  1.2334 +
  1.2335 +class nsXPCWrappedJS : protected nsAutoXPTCStub,
  1.2336 +                       public nsIXPConnectWrappedJS,
  1.2337 +                       public nsSupportsWeakReference,
  1.2338 +                       public nsIPropertyBag,
  1.2339 +                       public XPCRootSetElem
  1.2340 +{
  1.2341 +public:
  1.2342 +    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  1.2343 +    NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
  1.2344 +    NS_DECL_NSIXPCONNECTWRAPPEDJS
  1.2345 +    NS_DECL_NSISUPPORTSWEAKREFERENCE
  1.2346 +    NS_DECL_NSIPROPERTYBAG
  1.2347 +
  1.2348 +    NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
  1.2349 +
  1.2350 +    NS_IMETHOD CallMethod(uint16_t methodIndex,
  1.2351 +                          const XPTMethodDescriptor *info,
  1.2352 +                          nsXPTCMiniVariant* params);
  1.2353 +
  1.2354 +    /*
  1.2355 +    * This is rarely called directly. Instead one usually calls
  1.2356 +    * XPCConvert::JSObject2NativeInterface which will handles cases where the
  1.2357 +    * JS object is already a wrapped native or a DOM object.
  1.2358 +    */
  1.2359 +
  1.2360 +    static nsresult
  1.2361 +    GetNewOrUsed(JS::HandleObject aJSObj,
  1.2362 +                 REFNSIID aIID,
  1.2363 +                 nsXPCWrappedJS** wrapper);
  1.2364 +
  1.2365 +    nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
  1.2366 +
  1.2367 +    /**
  1.2368 +     * This getter does not change the color of the JSObject meaning that the
  1.2369 +     * object returned is not guaranteed to be kept alive past the next CC.
  1.2370 +     *
  1.2371 +     * This should only be called if you are certain that the return value won't
  1.2372 +     * be passed into a JS API function and that it won't be stored without
  1.2373 +     * being rooted (or otherwise signaling the stored value to the CC).
  1.2374 +     */
  1.2375 +    JSObject* GetJSObjectPreserveColor() const {return mJSObj;}
  1.2376 +
  1.2377 +    nsXPCWrappedJSClass*  GetClass() const {return mClass;}
  1.2378 +    REFNSIID GetIID() const {return GetClass()->GetIID();}
  1.2379 +    nsXPCWrappedJS* GetRootWrapper() const {return mRoot;}
  1.2380 +    nsXPCWrappedJS* GetNextWrapper() const {return mNext;}
  1.2381 +
  1.2382 +    nsXPCWrappedJS* Find(REFNSIID aIID);
  1.2383 +    nsXPCWrappedJS* FindInherited(REFNSIID aIID);
  1.2384 +    nsXPCWrappedJS* FindOrFindInherited(REFNSIID aIID) {
  1.2385 +        nsXPCWrappedJS* wrapper = Find(aIID);
  1.2386 +        if (wrapper)
  1.2387 +            return wrapper;
  1.2388 +        return FindInherited(aIID);
  1.2389 +    }
  1.2390 +
  1.2391 +    bool IsRootWrapper() const {return mRoot == this;}
  1.2392 +    bool IsValid() const {return mJSObj != nullptr;}
  1.2393 +    void SystemIsBeingShutDown();
  1.2394 +
  1.2395 +    // These two methods are used by JSObject2WrappedJSMap::FindDyingJSObjects
  1.2396 +    // to find non-rooting wrappers for dying JS objects. See the top of
  1.2397 +    // XPCWrappedJS.cpp for more details.
  1.2398 +    bool IsSubjectToFinalization() const {return IsValid() && mRefCnt == 1;}
  1.2399 +    bool IsObjectAboutToBeFinalized() {return JS_IsAboutToBeFinalized(&mJSObj);}
  1.2400 +
  1.2401 +    bool IsAggregatedToNative() const {return mRoot->mOuter != nullptr;}
  1.2402 +    nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
  1.2403 +    void SetAggregatedNativeObject(nsISupports *aNative) {
  1.2404 +        MOZ_ASSERT(aNative);
  1.2405 +        if (mRoot->mOuter) {
  1.2406 +            MOZ_ASSERT(mRoot->mOuter == aNative,
  1.2407 +                       "Only one aggregated native can be set");
  1.2408 +            return;
  1.2409 +        }
  1.2410 +        mRoot->mOuter = aNative;
  1.2411 +    }
  1.2412 +
  1.2413 +    void TraceJS(JSTracer* trc);
  1.2414 +    static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize);
  1.2415 +
  1.2416 +    virtual ~nsXPCWrappedJS();
  1.2417 +protected:
  1.2418 +    nsXPCWrappedJS();   // not implemented
  1.2419 +    nsXPCWrappedJS(JSContext* cx,
  1.2420 +                   JSObject* aJSObj,
  1.2421 +                   nsXPCWrappedJSClass* aClass,
  1.2422 +                   nsXPCWrappedJS* root);
  1.2423 +
  1.2424 +    bool CanSkip();
  1.2425 +    void Destroy();
  1.2426 +    void Unlink();
  1.2427 +
  1.2428 +private:
  1.2429 +    JS::Heap<JSObject*> mJSObj;
  1.2430 +    nsRefPtr<nsXPCWrappedJSClass> mClass;
  1.2431 +    nsXPCWrappedJS* mRoot;    // If mRoot != this, it is an owning pointer.
  1.2432 +    nsXPCWrappedJS* mNext;
  1.2433 +    nsCOMPtr<nsISupports> mOuter;    // only set in root
  1.2434 +};
  1.2435 +
  1.2436 +/***************************************************************************/
  1.2437 +
  1.2438 +class XPCJSObjectHolder : public nsIXPConnectJSObjectHolder,
  1.2439 +                          public XPCRootSetElem
  1.2440 +{
  1.2441 +public:
  1.2442 +    // all the interface method declarations...
  1.2443 +    NS_DECL_ISUPPORTS
  1.2444 +    NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
  1.2445 +
  1.2446 +    // non-interface implementation
  1.2447 +
  1.2448 +public:
  1.2449 +    static XPCJSObjectHolder* newHolder(JSObject* obj);
  1.2450 +
  1.2451 +    virtual ~XPCJSObjectHolder();
  1.2452 +
  1.2453 +    void TraceJS(JSTracer *trc);
  1.2454 +    static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize);
  1.2455 +
  1.2456 +private:
  1.2457 +    XPCJSObjectHolder(JSObject* obj);
  1.2458 +    XPCJSObjectHolder(); // not implemented
  1.2459 +
  1.2460 +    JS::Heap<JSObject*> mJSObj;
  1.2461 +};
  1.2462 +
  1.2463 +/***************************************************************************
  1.2464 +****************************************************************************
  1.2465 +*
  1.2466 +* All manner of utility classes follow...
  1.2467 +*
  1.2468 +****************************************************************************
  1.2469 +***************************************************************************/
  1.2470 +
  1.2471 +class xpcProperty : public nsIProperty
  1.2472 +{
  1.2473 +public:
  1.2474 +  NS_DECL_ISUPPORTS
  1.2475 +  NS_DECL_NSIPROPERTY
  1.2476 +
  1.2477 +  xpcProperty(const char16_t* aName, uint32_t aNameLen, nsIVariant* aValue);
  1.2478 +  virtual ~xpcProperty() {}
  1.2479 +
  1.2480 +private:
  1.2481 +    nsString             mName;
  1.2482 +    nsCOMPtr<nsIVariant> mValue;
  1.2483 +};
  1.2484 +
  1.2485 +/***************************************************************************/
  1.2486 +// class here just for static methods
  1.2487 +class XPCConvert
  1.2488 +{
  1.2489 +public:
  1.2490 +    static bool IsMethodReflectable(const XPTMethodDescriptor& info);
  1.2491 +
  1.2492 +    /**
  1.2493 +     * Convert a native object into a jsval.
  1.2494 +     *
  1.2495 +     * @param d [out] the resulting jsval
  1.2496 +     * @param s the native object we're working with
  1.2497 +     * @param type the type of object that s is
  1.2498 +     * @param iid the interface of s that we want
  1.2499 +     * @param scope the default scope to put on the new JSObject's parent
  1.2500 +     *        chain
  1.2501 +     * @param pErr [out] relevant error code, if any.
  1.2502 +     */
  1.2503 +
  1.2504 +    static bool NativeData2JS(JS::MutableHandleValue d,
  1.2505 +                              const void* s, const nsXPTType& type,
  1.2506 +                              const nsID* iid, nsresult* pErr);
  1.2507 +
  1.2508 +    static bool JSData2Native(void* d, JS::HandleValue s,
  1.2509 +                              const nsXPTType& type,
  1.2510 +                              bool useAllocator, const nsID* iid,
  1.2511 +                              nsresult* pErr);
  1.2512 +
  1.2513 +    /**
  1.2514 +     * Convert a native nsISupports into a JSObject.
  1.2515 +     *
  1.2516 +     * @param dest [out] the resulting JSObject
  1.2517 +     * @param src the native object we're working with
  1.2518 +     * @param iid the interface of src that we want (may be null)
  1.2519 +     * @param Interface the interface of src that we want
  1.2520 +     * @param cache the wrapper cache for src (may be null, in which case src
  1.2521 +     *              will be QI'ed to get the cache)
  1.2522 +     * @param allowNativeWrapper if true, this method may wrap the resulting
  1.2523 +     *        JSObject in an XPCNativeWrapper and return that, as needed.
  1.2524 +     * @param pErr [out] relevant error code, if any.
  1.2525 +     * @param src_is_identity optional performance hint. Set to true only
  1.2526 +     *                        if src is the identity pointer.
  1.2527 +     */
  1.2528 +    static bool NativeInterface2JSObject(JS::MutableHandleValue d,
  1.2529 +                                         nsIXPConnectJSObjectHolder** dest,
  1.2530 +                                         xpcObjectHelper& aHelper,
  1.2531 +                                         const nsID* iid,
  1.2532 +                                         XPCNativeInterface** Interface,
  1.2533 +                                         bool allowNativeWrapper,
  1.2534 +                                         nsresult* pErr);
  1.2535 +
  1.2536 +    static bool GetNativeInterfaceFromJSObject(void** dest, JSObject* src,
  1.2537 +                                               const nsID* iid,
  1.2538 +                                               nsresult* pErr);
  1.2539 +    static bool JSObject2NativeInterface(void** dest, JS::HandleObject src,
  1.2540 +                                         const nsID* iid,
  1.2541 +                                         nsISupports* aOuter,
  1.2542 +                                         nsresult* pErr);
  1.2543 +    static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
  1.2544 +
  1.2545 +    /**
  1.2546 +     * Convert a native array into a jsval.
  1.2547 +     *
  1.2548 +     * @param d [out] the resulting jsval
  1.2549 +     * @param s the native array we're working with
  1.2550 +     * @param type the type of objects in the array
  1.2551 +     * @param iid the interface of each object in the array that we want
  1.2552 +     * @param count the number of items in the array
  1.2553 +     * @param scope the default scope to put on the new JSObjects' parent chain
  1.2554 +     * @param pErr [out] relevant error code, if any.
  1.2555 +     */
  1.2556 +    static bool NativeArray2JS(JS::MutableHandleValue d, const void** s,
  1.2557 +                               const nsXPTType& type, const nsID* iid,
  1.2558 +                               uint32_t count, nsresult* pErr);
  1.2559 +
  1.2560 +    static bool JSArray2Native(void** d, JS::HandleValue s,
  1.2561 +                               uint32_t count, const nsXPTType& type,
  1.2562 +                               const nsID* iid, nsresult* pErr);
  1.2563 +
  1.2564 +    static bool JSTypedArray2Native(void** d,
  1.2565 +                                    JSObject* jsarray,
  1.2566 +                                    uint32_t count,
  1.2567 +                                    const nsXPTType& type,
  1.2568 +                                    nsresult* pErr);
  1.2569 +
  1.2570 +    static bool NativeStringWithSize2JS(JS::MutableHandleValue d, const void* s,
  1.2571 +                                        const nsXPTType& type,
  1.2572 +                                        uint32_t count,
  1.2573 +                                        nsresult* pErr);
  1.2574 +
  1.2575 +    static bool JSStringWithSize2Native(void* d, JS::HandleValue s,
  1.2576 +                                        uint32_t count, const nsXPTType& type,
  1.2577 +                                        nsresult* pErr);
  1.2578 +
  1.2579 +    static nsresult JSValToXPCException(JS::MutableHandleValue s,
  1.2580 +                                        const char* ifaceName,
  1.2581 +                                        const char* methodName,
  1.2582 +                                        nsIException** exception);
  1.2583 +
  1.2584 +    static nsresult JSErrorToXPCException(const char* message,
  1.2585 +                                          const char* ifaceName,
  1.2586 +                                          const char* methodName,
  1.2587 +                                          const JSErrorReport* report,
  1.2588 +                                          nsIException** exception);
  1.2589 +
  1.2590 +    static nsresult ConstructException(nsresult rv, const char* message,
  1.2591 +                                       const char* ifaceName,
  1.2592 +                                       const char* methodName,
  1.2593 +                                       nsISupports* data,
  1.2594 +                                       nsIException** exception,
  1.2595 +                                       JSContext* cx,
  1.2596 +                                       jsval *jsExceptionPtr);
  1.2597 +
  1.2598 +private:
  1.2599 +    XPCConvert(); // not implemented
  1.2600 +
  1.2601 +};
  1.2602 +
  1.2603 +/***************************************************************************/
  1.2604 +// code for throwing exceptions into JS
  1.2605 +
  1.2606 +class nsXPCException;
  1.2607 +
  1.2608 +class XPCThrower
  1.2609 +{
  1.2610 +public:
  1.2611 +    static void Throw(nsresult rv, JSContext* cx);
  1.2612 +    static void Throw(nsresult rv, XPCCallContext& ccx);
  1.2613 +    static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
  1.2614 +    static void ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx);
  1.2615 +    static bool SetVerbosity(bool state)
  1.2616 +        {bool old = sVerbose; sVerbose = state; return old;}
  1.2617 +
  1.2618 +    static bool CheckForPendingException(nsresult result, JSContext *cx);
  1.2619 +
  1.2620 +private:
  1.2621 +    static void Verbosify(XPCCallContext& ccx,
  1.2622 +                          char** psz, bool own);
  1.2623 +
  1.2624 +private:
  1.2625 +    static bool sVerbose;
  1.2626 +};
  1.2627 +
  1.2628 +/***************************************************************************/
  1.2629 +
  1.2630 +class nsXPCException
  1.2631 +{
  1.2632 +public:
  1.2633 +    static bool NameAndFormatForNSResult(nsresult rv,
  1.2634 +                                         const char** name,
  1.2635 +                                         const char** format);
  1.2636 +
  1.2637 +    static const void* IterateNSResults(nsresult* rv,
  1.2638 +                                        const char** name,
  1.2639 +                                        const char** format,
  1.2640 +                                        const void** iterp);
  1.2641 +
  1.2642 +    static uint32_t GetNSResultCount();
  1.2643 +};
  1.2644 +
  1.2645 +/***************************************************************************/
  1.2646 +/*
  1.2647 +* nsJSID implements nsIJSID. It is also used by nsJSIID and nsJSCID as a
  1.2648 +* member (as a hidden implementaion detail) to which they delegate many calls.
  1.2649 +*/
  1.2650 +
  1.2651 +// Initialization is done on demand, and calling the destructor below is always
  1.2652 +// safe.
  1.2653 +extern void xpc_DestroyJSxIDClassObjects();
  1.2654 +
  1.2655 +class nsJSID : public nsIJSID
  1.2656 +{
  1.2657 +public:
  1.2658 +    NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID)
  1.2659 +
  1.2660 +    NS_DECL_ISUPPORTS
  1.2661 +    NS_DECL_NSIJSID
  1.2662 +
  1.2663 +    bool InitWithName(const nsID& id, const char *nameString);
  1.2664 +    bool SetName(const char* name);
  1.2665 +    void   SetNameToNoString()
  1.2666 +        {MOZ_ASSERT(!mName, "name already set"); mName = gNoString;}
  1.2667 +    bool NameIsSet() const {return nullptr != mName;}
  1.2668 +    const nsID& ID() const {return mID;}
  1.2669 +    bool IsValid() const {return !mID.Equals(GetInvalidIID());}
  1.2670 +
  1.2671 +    static already_AddRefed<nsJSID> NewID(const char* str);
  1.2672 +    static already_AddRefed<nsJSID> NewID(const nsID& id);
  1.2673 +
  1.2674 +    nsJSID();
  1.2675 +    virtual ~nsJSID();
  1.2676 +protected:
  1.2677 +
  1.2678 +    void Reset();
  1.2679 +    const nsID& GetInvalidIID() const;
  1.2680 +
  1.2681 +protected:
  1.2682 +    static char gNoString[];
  1.2683 +    nsID    mID;
  1.2684 +    char*   mNumber;
  1.2685 +    char*   mName;
  1.2686 +};
  1.2687 +
  1.2688 +// nsJSIID
  1.2689 +
  1.2690 +class nsJSIID : public nsIJSIID,
  1.2691 +                public nsIXPCScriptable
  1.2692 +{
  1.2693 +public:
  1.2694 +    NS_DECL_ISUPPORTS
  1.2695 +
  1.2696 +    // we manually delagate these to nsJSID
  1.2697 +    NS_DECL_NSIJSID
  1.2698 +
  1.2699 +    // we implement the rest...
  1.2700 +    NS_DECL_NSIJSIID
  1.2701 +    NS_DECL_NSIXPCSCRIPTABLE
  1.2702 +
  1.2703 +    static already_AddRefed<nsJSIID> NewID(nsIInterfaceInfo* aInfo);
  1.2704 +
  1.2705 +    nsJSIID(nsIInterfaceInfo* aInfo);
  1.2706 +    nsJSIID(); // not implemented
  1.2707 +    virtual ~nsJSIID();
  1.2708 +
  1.2709 +private:
  1.2710 +    nsCOMPtr<nsIInterfaceInfo> mInfo;
  1.2711 +};
  1.2712 +
  1.2713 +// nsJSCID
  1.2714 +
  1.2715 +class nsJSCID : public nsIJSCID, public nsIXPCScriptable
  1.2716 +{
  1.2717 +public:
  1.2718 +    NS_DECL_ISUPPORTS
  1.2719 +
  1.2720 +    // we manually delagate these to nsJSID
  1.2721 +    NS_DECL_NSIJSID
  1.2722 +
  1.2723 +    // we implement the rest...
  1.2724 +    NS_DECL_NSIJSCID
  1.2725 +    NS_DECL_NSIXPCSCRIPTABLE
  1.2726 +
  1.2727 +    static already_AddRefed<nsJSCID> NewID(const char* str);
  1.2728 +
  1.2729 +    nsJSCID();
  1.2730 +    virtual ~nsJSCID();
  1.2731 +
  1.2732 +private:
  1.2733 +    void ResolveName();
  1.2734 +
  1.2735 +private:
  1.2736 +    nsJSID mDetails;
  1.2737 +};
  1.2738 +
  1.2739 +
  1.2740 +/***************************************************************************/
  1.2741 +// XPCJSContextStack is not actually an xpcom object, but xpcom calls are
  1.2742 +// delegated to it as an implementation detail.
  1.2743 +struct XPCJSContextInfo {
  1.2744 +    XPCJSContextInfo(JSContext* aCx) :
  1.2745 +        cx(aCx),
  1.2746 +        savedFrameChain(false)
  1.2747 +    {}
  1.2748 +    JSContext* cx;
  1.2749 +
  1.2750 +    // Whether the frame chain was saved
  1.2751 +    bool savedFrameChain;
  1.2752 +};
  1.2753 +
  1.2754 +namespace xpc {
  1.2755 +
  1.2756 +// These functions are used in a few places where a callback model makes it
  1.2757 +// impossible to push a JSContext using one of our stack-scoped classes. We
  1.2758 +// depend on those stack-scoped classes to maintain nsIScriptContext
  1.2759 +// invariants, so these functions may only be used of the context is not
  1.2760 +// associated with an nsJSContext/nsIScriptContext.
  1.2761 +bool PushJSContextNoScriptContext(JSContext *aCx);
  1.2762 +void PopJSContextNoScriptContext();
  1.2763 +
  1.2764 +} /* namespace xpc */
  1.2765 +
  1.2766 +class XPCJSContextStack
  1.2767 +{
  1.2768 +public:
  1.2769 +    XPCJSContextStack(XPCJSRuntime *aRuntime)
  1.2770 +      : mRuntime(aRuntime)
  1.2771 +      , mSafeJSContext(nullptr)
  1.2772 +      , mSafeJSContextGlobal(aRuntime->Runtime(), nullptr)
  1.2773 +    { }
  1.2774 +
  1.2775 +    virtual ~XPCJSContextStack();
  1.2776 +
  1.2777 +    uint32_t Count()
  1.2778 +    {
  1.2779 +        return mStack.Length();
  1.2780 +    }
  1.2781 +
  1.2782 +    JSContext *Peek()
  1.2783 +    {
  1.2784 +        return mStack.IsEmpty() ? nullptr : mStack[mStack.Length() - 1].cx;
  1.2785 +    }
  1.2786 +
  1.2787 +    JSContext *InitSafeJSContext();
  1.2788 +    JSContext *GetSafeJSContext();
  1.2789 +    JSObject *GetSafeJSContextGlobal();
  1.2790 +    bool HasJSContext(JSContext *cx);
  1.2791 +
  1.2792 +    const InfallibleTArray<XPCJSContextInfo>* GetStack()
  1.2793 +    { return &mStack; }
  1.2794 +
  1.2795 +private:
  1.2796 +    friend class mozilla::AutoCxPusher;
  1.2797 +    friend bool xpc::PushJSContextNoScriptContext(JSContext *aCx);;
  1.2798 +    friend void xpc::PopJSContextNoScriptContext();
  1.2799 +
  1.2800 +    // We make these private so that stack manipulation can only happen
  1.2801 +    // through one of the above friends.
  1.2802 +    JSContext *Pop();
  1.2803 +    bool Push(JSContext *cx);
  1.2804 +
  1.2805 +    AutoInfallibleTArray<XPCJSContextInfo, 16> mStack;
  1.2806 +    XPCJSRuntime* mRuntime;
  1.2807 +    JSContext*  mSafeJSContext;
  1.2808 +    JS::PersistentRootedObject mSafeJSContextGlobal;
  1.2809 +};
  1.2810 +
  1.2811 +/***************************************************************************/
  1.2812 +// 'Components' object implementations. nsXPCComponentsBase has the
  1.2813 +// less-privileged stuff that we're willing to expose to XBL.
  1.2814 +
  1.2815 +class nsXPCComponentsBase : public nsIXPCComponentsBase
  1.2816 +{
  1.2817 +public:
  1.2818 +    NS_DECL_ISUPPORTS
  1.2819 +    NS_DECL_NSIXPCCOMPONENTSBASE
  1.2820 +
  1.2821 +public:
  1.2822 +    void SystemIsBeingShutDown() { ClearMembers(); }
  1.2823 +    virtual ~nsXPCComponentsBase();
  1.2824 +
  1.2825 +    XPCWrappedNativeScope *GetScope() { return mScope; }
  1.2826 +
  1.2827 +protected:
  1.2828 +    nsXPCComponentsBase(XPCWrappedNativeScope* aScope);
  1.2829 +    virtual void ClearMembers();
  1.2830 +
  1.2831 +    XPCWrappedNativeScope*                   mScope;
  1.2832 +
  1.2833 +    // Unprivileged members from nsIXPCComponentsBase.
  1.2834 +    nsRefPtr<nsXPCComponents_Interfaces>     mInterfaces;
  1.2835 +    nsRefPtr<nsXPCComponents_InterfacesByID> mInterfacesByID;
  1.2836 +    nsRefPtr<nsXPCComponents_Results>        mResults;
  1.2837 +
  1.2838 +    friend class XPCWrappedNativeScope;
  1.2839 +};
  1.2840 +
  1.2841 +class nsXPCComponents : public nsXPCComponentsBase,
  1.2842 +                        public nsIXPCComponents
  1.2843 +{
  1.2844 +public:
  1.2845 +    NS_DECL_ISUPPORTS
  1.2846 +    NS_FORWARD_NSIXPCCOMPONENTSBASE(nsXPCComponentsBase::)
  1.2847 +    NS_DECL_NSIXPCCOMPONENTS
  1.2848 +
  1.2849 +protected:
  1.2850 +    nsXPCComponents(XPCWrappedNativeScope* aScope);
  1.2851 +    virtual ~nsXPCComponents();
  1.2852 +    virtual void ClearMembers() MOZ_OVERRIDE;
  1.2853 +
  1.2854 +    // Privileged members added by nsIXPCComponents.
  1.2855 +    nsRefPtr<nsXPCComponents_Classes>     mClasses;
  1.2856 +    nsRefPtr<nsXPCComponents_ClassesByID> mClassesByID;
  1.2857 +    nsRefPtr<nsXPCComponents_ID>          mID;
  1.2858 +    nsRefPtr<nsXPCComponents_Exception>   mException;
  1.2859 +    nsRefPtr<nsXPCComponents_Constructor> mConstructor;
  1.2860 +    nsRefPtr<nsXPCComponents_Utils>       mUtils;
  1.2861 +
  1.2862 +    friend class XPCWrappedNativeScope;
  1.2863 +};
  1.2864 +
  1.2865 +
  1.2866 +/***************************************************************************/
  1.2867 +
  1.2868 +extern JSObject*
  1.2869 +xpc_NewIDObject(JSContext *cx, JS::HandleObject jsobj, const nsID& aID);
  1.2870 +
  1.2871 +extern const nsID*
  1.2872 +xpc_JSObjectToID(JSContext *cx, JSObject* obj);
  1.2873 +
  1.2874 +extern bool
  1.2875 +xpc_JSObjectIsID(JSContext *cx, JSObject* obj);
  1.2876 +
  1.2877 +/***************************************************************************/
  1.2878 +// in XPCDebug.cpp
  1.2879 +
  1.2880 +extern bool
  1.2881 +xpc_DumpJSStack(JSContext* cx, bool showArgs, bool showLocals,
  1.2882 +                bool showThisProps);
  1.2883 +
  1.2884 +// Return a newly-allocated string containing a representation of the
  1.2885 +// current JS stack.  It is the *caller's* responsibility to free this
  1.2886 +// string with JS_smprintf_free().
  1.2887 +extern char*
  1.2888 +xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
  1.2889 +                 bool showThisProps);
  1.2890 +
  1.2891 +extern bool
  1.2892 +xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text);
  1.2893 +
  1.2894 +extern bool
  1.2895 +xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
  1.2896 +
  1.2897 +/***************************************************************************/
  1.2898 +
  1.2899 +// Definition of nsScriptError, defined here because we lack a place to put
  1.2900 +// XPCOM objects associated with the JavaScript engine.
  1.2901 +class nsScriptError : public nsIScriptError {
  1.2902 +public:
  1.2903 +    nsScriptError();
  1.2904 +
  1.2905 +    virtual ~nsScriptError();
  1.2906 +
  1.2907 +  // TODO - do something reasonable on getting null from these babies.
  1.2908 +
  1.2909 +    NS_DECL_THREADSAFE_ISUPPORTS
  1.2910 +    NS_DECL_NSICONSOLEMESSAGE
  1.2911 +    NS_DECL_NSISCRIPTERROR
  1.2912 +
  1.2913 +private:
  1.2914 +    nsString mMessage;
  1.2915 +    nsString mSourceName;
  1.2916 +    uint32_t mLineNumber;
  1.2917 +    nsString mSourceLine;
  1.2918 +    uint32_t mColumnNumber;
  1.2919 +    uint32_t mFlags;
  1.2920 +    nsCString mCategory;
  1.2921 +    uint64_t mOuterWindowID;
  1.2922 +    uint64_t mInnerWindowID;
  1.2923 +    int64_t mTimeStamp;
  1.2924 +    bool mIsFromPrivateWindow;
  1.2925 +};
  1.2926 +
  1.2927 +/******************************************************************************
  1.2928 + * Handles pre/post script processing and the setting/resetting the error
  1.2929 + * reporter
  1.2930 + */
  1.2931 +class MOZ_STACK_CLASS AutoScriptEvaluate
  1.2932 +{
  1.2933 +public:
  1.2934 +    /**
  1.2935 +     * Saves the JSContext as well as initializing our state
  1.2936 +     * @param cx The JSContext, this can be null, we don't do anything then
  1.2937 +     */
  1.2938 +    AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  1.2939 +         : mJSContext(cx), mErrorReporterSet(false), mEvaluated(false) {
  1.2940 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.2941 +    }
  1.2942 +
  1.2943 +    /**
  1.2944 +     * Does the pre script evaluation and sets the error reporter if given
  1.2945 +     * This function should only be called once, and will assert if called
  1.2946 +     * more than once
  1.2947 +     * @param errorReporter the error reporter callback function to set
  1.2948 +     */
  1.2949 +
  1.2950 +    bool StartEvaluating(JS::HandleObject scope, JSErrorReporter errorReporter = nullptr);
  1.2951 +
  1.2952 +    /**
  1.2953 +     * Does the post script evaluation and resets the error reporter
  1.2954 +     */
  1.2955 +    ~AutoScriptEvaluate();
  1.2956 +private:
  1.2957 +    JSContext* mJSContext;
  1.2958 +    mozilla::Maybe<JS::AutoSaveExceptionState> mState;
  1.2959 +    bool mErrorReporterSet;
  1.2960 +    bool mEvaluated;
  1.2961 +    mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
  1.2962 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.2963 +
  1.2964 +    // No copying or assignment allowed
  1.2965 +    AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
  1.2966 +    AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;
  1.2967 +};
  1.2968 +
  1.2969 +/***************************************************************************/
  1.2970 +class MOZ_STACK_CLASS AutoResolveName
  1.2971 +{
  1.2972 +public:
  1.2973 +    AutoResolveName(XPCCallContext& ccx, JS::HandleId name
  1.2974 +                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
  1.2975 +          mOld(ccx, XPCJSRuntime::Get()->SetResolveName(name))
  1.2976 +#ifdef DEBUG
  1.2977 +          ,mCheck(ccx, name)
  1.2978 +#endif
  1.2979 +    {
  1.2980 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.2981 +    }
  1.2982 +    ~AutoResolveName()
  1.2983 +        {
  1.2984 +#ifdef DEBUG
  1.2985 +            jsid old =
  1.2986 +#endif
  1.2987 +            XPCJSRuntime::Get()->SetResolveName(mOld);
  1.2988 +            MOZ_ASSERT(old == mCheck, "Bad Nesting!");
  1.2989 +        }
  1.2990 +
  1.2991 +private:
  1.2992 +    JS::RootedId mOld;
  1.2993 +#ifdef DEBUG
  1.2994 +    JS::RootedId mCheck;
  1.2995 +#endif
  1.2996 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.2997 +};
  1.2998 +
  1.2999 +/***************************************************************************/
  1.3000 +// AutoMarkingPtr is the base class for the various AutoMarking pointer types
  1.3001 +// below. This system allows us to temporarily protect instances of our garbage
  1.3002 +// collected types after they are constructed but before they are safely
  1.3003 +// attached to other rooted objects.
  1.3004 +// This base class has pure virtual support for marking.
  1.3005 +
  1.3006 +class AutoMarkingPtr
  1.3007 +{
  1.3008 +  public:
  1.3009 +    AutoMarkingPtr(JSContext* cx) {
  1.3010 +        mRoot = XPCJSRuntime::Get()->GetAutoRootsAdr();
  1.3011 +        mNext = *mRoot;
  1.3012 +        *mRoot = this;
  1.3013 +    }
  1.3014 +
  1.3015 +    virtual ~AutoMarkingPtr() {
  1.3016 +        if (mRoot) {
  1.3017 +            MOZ_ASSERT(*mRoot == this);
  1.3018 +            *mRoot = mNext;
  1.3019 +        }
  1.3020 +    }
  1.3021 +
  1.3022 +    void TraceJSAll(JSTracer* trc) {
  1.3023 +        for (AutoMarkingPtr *cur = this; cur; cur = cur->mNext)
  1.3024 +            cur->TraceJS(trc);
  1.3025 +    }
  1.3026 +
  1.3027 +    void MarkAfterJSFinalizeAll() {
  1.3028 +        for (AutoMarkingPtr *cur = this; cur; cur = cur->mNext)
  1.3029 +            cur->MarkAfterJSFinalize();
  1.3030 +    }
  1.3031 +
  1.3032 +  protected:
  1.3033 +    virtual void TraceJS(JSTracer* trc) = 0;
  1.3034 +    virtual void MarkAfterJSFinalize() = 0;
  1.3035 +
  1.3036 +  private:
  1.3037 +    AutoMarkingPtr** mRoot;
  1.3038 +    AutoMarkingPtr* mNext;
  1.3039 +};
  1.3040 +
  1.3041 +template<class T>
  1.3042 +class TypedAutoMarkingPtr : public AutoMarkingPtr
  1.3043 +{
  1.3044 +  public:
  1.3045 +    TypedAutoMarkingPtr(JSContext* cx) : AutoMarkingPtr(cx), mPtr(nullptr) {}
  1.3046 +    TypedAutoMarkingPtr(JSContext* cx, T* ptr) : AutoMarkingPtr(cx), mPtr(ptr) {}
  1.3047 +
  1.3048 +    T* get() const { return mPtr; }
  1.3049 +    operator T *() const { return mPtr; }
  1.3050 +    T* operator->() const { return mPtr; }
  1.3051 +
  1.3052 +    TypedAutoMarkingPtr<T>& operator =(T* ptr) { mPtr = ptr; return *this; }
  1.3053 +
  1.3054 +  protected:
  1.3055 +    virtual void TraceJS(JSTracer* trc)
  1.3056 +    {
  1.3057 +        if (mPtr) {
  1.3058 +            mPtr->TraceJS(trc);
  1.3059 +            mPtr->AutoTrace(trc);
  1.3060 +        }
  1.3061 +    }
  1.3062 +
  1.3063 +    virtual void MarkAfterJSFinalize()
  1.3064 +    {
  1.3065 +        if (mPtr)
  1.3066 +            mPtr->Mark();
  1.3067 +    }
  1.3068 +
  1.3069 +  private:
  1.3070 +    T* mPtr;
  1.3071 +};
  1.3072 +
  1.3073 +typedef TypedAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtr;
  1.3074 +typedef TypedAutoMarkingPtr<XPCNativeSet> AutoMarkingNativeSetPtr;
  1.3075 +typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr;
  1.3076 +typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr;
  1.3077 +typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
  1.3078 +typedef TypedAutoMarkingPtr<XPCNativeScriptableInfo> AutoMarkingNativeScriptableInfoPtr;
  1.3079 +
  1.3080 +template<class T>
  1.3081 +class ArrayAutoMarkingPtr : public AutoMarkingPtr
  1.3082 +{
  1.3083 +  public:
  1.3084 +    ArrayAutoMarkingPtr(JSContext* cx)
  1.3085 +      : AutoMarkingPtr(cx), mPtr(nullptr), mCount(0) {}
  1.3086 +    ArrayAutoMarkingPtr(JSContext* cx, T** ptr, uint32_t count, bool clear)
  1.3087 +      : AutoMarkingPtr(cx), mPtr(ptr), mCount(count)
  1.3088 +    {
  1.3089 +        if (!mPtr) mCount = 0;
  1.3090 +        else if (clear) memset(mPtr, 0, mCount*sizeof(T*));
  1.3091 +    }
  1.3092 +
  1.3093 +    T** get() const { return mPtr; }
  1.3094 +    operator T **() const { return mPtr; }
  1.3095 +    T** operator->() const { return mPtr; }
  1.3096 +
  1.3097 +    ArrayAutoMarkingPtr<T>& operator =(const ArrayAutoMarkingPtr<T> &other)
  1.3098 +    {
  1.3099 +        mPtr = other.mPtr;
  1.3100 +        mCount = other.mCount;
  1.3101 +        return *this;
  1.3102 +    }
  1.3103 +
  1.3104 +  protected:
  1.3105 +    virtual void TraceJS(JSTracer* trc)
  1.3106 +    {
  1.3107 +        for (uint32_t i = 0; i < mCount; i++) {
  1.3108 +            if (mPtr[i]) {
  1.3109 +                mPtr[i]->TraceJS(trc);
  1.3110 +                mPtr[i]->AutoTrace(trc);
  1.3111 +            }
  1.3112 +        }
  1.3113 +    }
  1.3114 +
  1.3115 +    virtual void MarkAfterJSFinalize()
  1.3116 +    {
  1.3117 +        for (uint32_t i = 0; i < mCount; i++) {
  1.3118 +            if (mPtr[i])
  1.3119 +                mPtr[i]->Mark();
  1.3120 +        }
  1.3121 +    }
  1.3122 +
  1.3123 +  private:
  1.3124 +    T** mPtr;
  1.3125 +    uint32_t mCount;
  1.3126 +};
  1.3127 +
  1.3128 +typedef ArrayAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtrArrayPtr;
  1.3129 +
  1.3130 +/***************************************************************************/
  1.3131 +namespace xpc {
  1.3132 +// Allocates a string that grants all access ("AllAccess")
  1.3133 +char *
  1.3134 +CloneAllAccess();
  1.3135 +
  1.3136 +// Returns access if wideName is in list
  1.3137 +char *
  1.3138 +CheckAccessList(const char16_t *wideName, const char *const list[]);
  1.3139 +} /* namespace xpc */
  1.3140 +
  1.3141 +/***************************************************************************/
  1.3142 +// in xpcvariant.cpp...
  1.3143 +
  1.3144 +// {1809FD50-91E8-11d5-90F9-0010A4E73D9A}
  1.3145 +#define XPCVARIANT_IID                                                        \
  1.3146 +    {0x1809fd50, 0x91e8, 0x11d5,                                              \
  1.3147 +      { 0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
  1.3148 +
  1.3149 +// {DC524540-487E-4501-9AC7-AAA784B17C1C}
  1.3150 +#define XPCVARIANT_CID                                                        \
  1.3151 +    {0xdc524540, 0x487e, 0x4501,                                              \
  1.3152 +      { 0x9a, 0xc7, 0xaa, 0xa7, 0x84, 0xb1, 0x7c, 0x1c } }
  1.3153 +
  1.3154 +class XPCVariant : public nsIVariant
  1.3155 +{
  1.3156 +public:
  1.3157 +    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  1.3158 +    NS_DECL_NSIVARIANT
  1.3159 +    NS_DECL_CYCLE_COLLECTION_CLASS(XPCVariant)
  1.3160 +
  1.3161 +    // If this class ever implements nsIWritableVariant, take special care with
  1.3162 +    // the case when mJSVal is JSVAL_STRING, since we don't own the data in
  1.3163 +    // that case.
  1.3164 +
  1.3165 +    // We #define and iid so that out module local code can use QI to detect
  1.3166 +    // if a given nsIVariant is in fact an XPCVariant.
  1.3167 +    NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
  1.3168 +
  1.3169 +    static already_AddRefed<XPCVariant> newVariant(JSContext* cx, jsval aJSVal);
  1.3170 +
  1.3171 +    /**
  1.3172 +     * This getter clears the gray bit before handing out the jsval if the jsval
  1.3173 +     * represents a JSObject. That means that the object is guaranteed to be
  1.3174 +     * kept alive past the next CC.
  1.3175 +     */
  1.3176 +    jsval GetJSVal() const {
  1.3177 +        if (!JSVAL_IS_PRIMITIVE(mJSVal))
  1.3178 +            JS::ExposeObjectToActiveJS(&mJSVal.toObject());
  1.3179 +        return mJSVal;
  1.3180 +    }
  1.3181 +
  1.3182 +    /**
  1.3183 +     * This getter does not change the color of the jsval (if it represents a
  1.3184 +     * JSObject) meaning that the value returned is not guaranteed to be kept
  1.3185 +     * alive past the next CC.
  1.3186 +     *
  1.3187 +     * This should only be called if you are certain that the return value won't
  1.3188 +     * be passed into a JS API function and that it won't be stored without
  1.3189 +     * being rooted (or otherwise signaling the stored value to the CC).
  1.3190 +     */
  1.3191 +    jsval GetJSValPreserveColor() const {return mJSVal;}
  1.3192 +
  1.3193 +    XPCVariant(JSContext* cx, jsval aJSVal);
  1.3194 +
  1.3195 +    /**
  1.3196 +     * Convert a variant into a jsval.
  1.3197 +     *
  1.3198 +     * @param ccx the context for the whole procedure
  1.3199 +     * @param variant the variant to convert
  1.3200 +     * @param scope the default scope to put on the new JSObject's parent chain
  1.3201 +     * @param pErr [out] relevant error code, if any.
  1.3202 +     * @param pJSVal [out] the resulting jsval.
  1.3203 +     */
  1.3204 +    static bool VariantDataToJS(nsIVariant* variant,
  1.3205 +                                nsresult* pErr, JS::MutableHandleValue pJSVal);
  1.3206 +
  1.3207 +    bool IsPurple()
  1.3208 +    {
  1.3209 +        return mRefCnt.IsPurple();
  1.3210 +    }
  1.3211 +
  1.3212 +    void RemovePurple()
  1.3213 +    {
  1.3214 +        mRefCnt.RemovePurple();
  1.3215 +    }
  1.3216 +
  1.3217 +    void SetCCGeneration(uint32_t aGen)
  1.3218 +    {
  1.3219 +        mCCGeneration = aGen;
  1.3220 +    }
  1.3221 +
  1.3222 +    uint32_t CCGeneration() { return mCCGeneration; }
  1.3223 +protected:
  1.3224 +    virtual ~XPCVariant() { }
  1.3225 +
  1.3226 +    bool InitializeData(JSContext* cx);
  1.3227 +
  1.3228 +protected:
  1.3229 +    nsDiscriminatedUnion mData;
  1.3230 +    JS::Heap<JS::Value>  mJSVal;
  1.3231 +    bool                 mReturnRawObject : 1;
  1.3232 +    uint32_t             mCCGeneration : 31;
  1.3233 +};
  1.3234 +
  1.3235 +NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID)
  1.3236 +
  1.3237 +class XPCTraceableVariant: public XPCVariant,
  1.3238 +                           public XPCRootSetElem
  1.3239 +{
  1.3240 +public:
  1.3241 +    XPCTraceableVariant(JSContext* cx, jsval aJSVal)
  1.3242 +        : XPCVariant(cx, aJSVal)
  1.3243 +    {
  1.3244 +         nsXPConnect::GetRuntimeInstance()->AddVariantRoot(this);
  1.3245 +    }
  1.3246 +
  1.3247 +    virtual ~XPCTraceableVariant();
  1.3248 +
  1.3249 +    void TraceJS(JSTracer* trc);
  1.3250 +    static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize);
  1.3251 +};
  1.3252 +
  1.3253 +/***************************************************************************/
  1.3254 +// Utilities
  1.3255 +
  1.3256 +inline void *
  1.3257 +xpc_GetJSPrivate(JSObject *obj)
  1.3258 +{
  1.3259 +    return js::GetObjectPrivate(obj);
  1.3260 +}
  1.3261 +
  1.3262 +inline JSContext *
  1.3263 +xpc_GetSafeJSContext()
  1.3264 +{
  1.3265 +    return XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContext();
  1.3266 +}
  1.3267 +
  1.3268 +namespace xpc {
  1.3269 +
  1.3270 +// JSNatives to expose atob and btoa in various non-DOM XPConnect scopes.
  1.3271 +bool
  1.3272 +Atob(JSContext *cx, unsigned argc, jsval *vp);
  1.3273 +
  1.3274 +bool
  1.3275 +Btoa(JSContext *cx, unsigned argc, jsval *vp);
  1.3276 +
  1.3277 +
  1.3278 +// Helper function that creates a JSFunction that wraps a native function that
  1.3279 +// forwards the call to the original 'callable'. If the 'doclone' argument is
  1.3280 +// set, it also structure clones non-native arguments for extra security.
  1.3281 +bool
  1.3282 +NewFunctionForwarder(JSContext *cx, JS::HandleId id, JS::HandleObject callable,
  1.3283 +                     bool doclone, JS::MutableHandleValue vp);
  1.3284 +
  1.3285 +bool
  1.3286 +NewFunctionForwarder(JSContext *cx, JS::HandleObject callable,
  1.3287 +                     bool doclone, JS::MutableHandleValue vp);
  1.3288 +
  1.3289 +// Old fashioned xpc error reporter. Try to use JS_ReportError instead.
  1.3290 +nsresult
  1.3291 +ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval);
  1.3292 +
  1.3293 +struct GlobalProperties {
  1.3294 +    GlobalProperties(bool aPromise) {
  1.3295 +      mozilla::PodZero(this);
  1.3296 +      Promise = true;
  1.3297 +    }
  1.3298 +    bool Parse(JSContext *cx, JS::HandleObject obj);
  1.3299 +    bool Define(JSContext *cx, JS::HandleObject obj);
  1.3300 +    bool Promise : 1;
  1.3301 +    bool indexedDB : 1;
  1.3302 +    bool XMLHttpRequest : 1;
  1.3303 +    bool TextDecoder : 1;
  1.3304 +    bool TextEncoder : 1;
  1.3305 +    bool URL : 1;
  1.3306 +    bool atob : 1;
  1.3307 +    bool btoa : 1;
  1.3308 +};
  1.3309 +
  1.3310 +// Infallible.
  1.3311 +already_AddRefed<nsIXPCComponents_utils_Sandbox>
  1.3312 +NewSandboxConstructor();
  1.3313 +
  1.3314 +// Returns true if class of 'obj' is SandboxClass.
  1.3315 +bool
  1.3316 +IsSandbox(JSObject *obj);
  1.3317 +
  1.3318 +class MOZ_STACK_CLASS OptionsBase {
  1.3319 +public:
  1.3320 +    OptionsBase(JSContext *cx = xpc_GetSafeJSContext(),
  1.3321 +                JSObject *options = nullptr)
  1.3322 +        : mCx(cx)
  1.3323 +        , mObject(cx, options)
  1.3324 +    { }
  1.3325 +
  1.3326 +    virtual bool Parse() = 0;
  1.3327 +
  1.3328 +protected:
  1.3329 +    bool ParseValue(const char *name, JS::MutableHandleValue prop, bool *found = nullptr);
  1.3330 +    bool ParseBoolean(const char *name, bool *prop);
  1.3331 +    bool ParseObject(const char *name, JS::MutableHandleObject prop);
  1.3332 +    bool ParseString(const char *name, nsCString &prop);
  1.3333 +    bool ParseString(const char *name, nsString &prop);
  1.3334 +    bool ParseId(const char* name, JS::MutableHandleId id);
  1.3335 +
  1.3336 +    JSContext *mCx;
  1.3337 +    JS::RootedObject mObject;
  1.3338 +};
  1.3339 +
  1.3340 +class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
  1.3341 +public:
  1.3342 +    SandboxOptions(JSContext *cx = xpc_GetSafeJSContext(),
  1.3343 +                   JSObject *options = nullptr)
  1.3344 +        : OptionsBase(cx, options)
  1.3345 +        , wantXrays(true)
  1.3346 +        , wantComponents(true)
  1.3347 +        , wantExportHelpers(false)
  1.3348 +        , proto(cx)
  1.3349 +        , sameZoneAs(cx)
  1.3350 +        , invisibleToDebugger(false)
  1.3351 +        , discardSource(false)
  1.3352 +        , globalProperties(true)
  1.3353 +        , metadata(cx)
  1.3354 +    { }
  1.3355 +
  1.3356 +    virtual bool Parse();
  1.3357 +
  1.3358 +    bool wantXrays;
  1.3359 +    bool wantComponents;
  1.3360 +    bool wantExportHelpers;
  1.3361 +    JS::RootedObject proto;
  1.3362 +    nsCString sandboxName;
  1.3363 +    JS::RootedObject sameZoneAs;
  1.3364 +    bool invisibleToDebugger;
  1.3365 +    bool discardSource;
  1.3366 +    GlobalProperties globalProperties;
  1.3367 +    JS::RootedValue metadata;
  1.3368 +
  1.3369 +protected:
  1.3370 +    bool ParseGlobalProperties();
  1.3371 +};
  1.3372 +
  1.3373 +class MOZ_STACK_CLASS CreateObjectInOptions : public OptionsBase {
  1.3374 +public:
  1.3375 +    CreateObjectInOptions(JSContext *cx = xpc_GetSafeJSContext(),
  1.3376 +                          JSObject* options = nullptr)
  1.3377 +        : OptionsBase(cx, options)
  1.3378 +        , defineAs(cx, JSID_VOID)
  1.3379 +    { }
  1.3380 +
  1.3381 +    virtual bool Parse() { return ParseId("defineAs", &defineAs); };
  1.3382 +
  1.3383 +    JS::RootedId defineAs;
  1.3384 +};
  1.3385 +
  1.3386 +class MOZ_STACK_CLASS ExportOptions : public OptionsBase {
  1.3387 +public:
  1.3388 +    ExportOptions(JSContext *cx = xpc_GetSafeJSContext(),
  1.3389 +                  JSObject* options = nullptr)
  1.3390 +        : OptionsBase(cx, options)
  1.3391 +        , defineAs(cx, JSID_VOID)
  1.3392 +    { }
  1.3393 +
  1.3394 +    virtual bool Parse() { return ParseId("defineAs", &defineAs); };
  1.3395 +
  1.3396 +    JS::RootedId defineAs;
  1.3397 +};
  1.3398 +
  1.3399 +JSObject *
  1.3400 +CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
  1.3401 +                   JS::CompartmentOptions& aOptions);
  1.3402 +
  1.3403 +bool
  1.3404 +InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal,
  1.3405 +                 uint32_t aFlags);
  1.3406 +
  1.3407 +// Helper for creating a sandbox object to use for evaluating
  1.3408 +// untrusted code completely separated from all other code in the
  1.3409 +// system using EvalInSandbox(). Takes the JSContext on which to
  1.3410 +// do setup etc on, puts the sandbox object in *vp (which must be
  1.3411 +// rooted by the caller), and uses the principal that's either
  1.3412 +// directly passed in prinOrSop or indirectly as an
  1.3413 +// nsIScriptObjectPrincipal holding the principal. If no principal is
  1.3414 +// reachable through prinOrSop, a new null principal will be created
  1.3415 +// and used.
  1.3416 +nsresult
  1.3417 +CreateSandboxObject(JSContext *cx, JS::MutableHandleValue vp, nsISupports *prinOrSop,
  1.3418 +                    xpc::SandboxOptions& options);
  1.3419 +// Helper for evaluating scripts in a sandbox object created with
  1.3420 +// CreateSandboxObject(). The caller is responsible of ensuring
  1.3421 +// that *rval doesn't get collected during the call or usage after the
  1.3422 +// call. This helper will use filename and lineNo for error reporting,
  1.3423 +// and if no filename is provided it will use the codebase from the
  1.3424 +// principal and line number 1 as a fallback. if returnStringOnly is
  1.3425 +// true, then the result in *rval, or the exception in cx->exception
  1.3426 +// will be coerced into strings. If an exception is thrown converting
  1.3427 +// an exception to a string, evalInSandbox will return an NS_ERROR_*
  1.3428 +// result, and cx->exception will be empty.
  1.3429 +nsresult
  1.3430 +EvalInSandbox(JSContext *cx, JS::HandleObject sandbox, const nsAString& source,
  1.3431 +              const nsACString& filename, int32_t lineNo,
  1.3432 +              JSVersion jsVersion, bool returnStringOnly,
  1.3433 +              JS::MutableHandleValue rval);
  1.3434 +
  1.3435 +// Helper for retrieving metadata stored in a reserved slot. The metadata
  1.3436 +// is set during the sandbox creation using the "metadata" option.
  1.3437 +nsresult
  1.3438 +GetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
  1.3439 +                   JS::MutableHandleValue rval);
  1.3440 +
  1.3441 +nsresult
  1.3442 +SetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
  1.3443 +                   JS::HandleValue metadata);
  1.3444 +
  1.3445 +bool
  1.3446 +CreateObjectIn(JSContext *cx, JS::HandleValue vobj, CreateObjectInOptions &options,
  1.3447 +               JS::MutableHandleValue rval);
  1.3448 +
  1.3449 +bool
  1.3450 +EvalInWindow(JSContext *cx, const nsAString &source, JS::HandleObject scope,
  1.3451 +             JS::MutableHandleValue rval);
  1.3452 +
  1.3453 +bool
  1.3454 +ExportFunction(JSContext *cx, JS::HandleValue vscope, JS::HandleValue vfunction,
  1.3455 +               JS::HandleValue voptions, JS::MutableHandleValue rval);
  1.3456 +
  1.3457 +bool
  1.3458 +CloneInto(JSContext *cx, JS::HandleValue vobj, JS::HandleValue vscope,
  1.3459 +          JS::HandleValue voptions, JS::MutableHandleValue rval);
  1.3460 +
  1.3461 +} /* namespace xpc */
  1.3462 +
  1.3463 +
  1.3464 +/***************************************************************************/
  1.3465 +// Inlined utilities.
  1.3466 +
  1.3467 +inline bool
  1.3468 +xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid id);
  1.3469 +
  1.3470 +inline jsid
  1.3471 +GetRTIdByIndex(JSContext *cx, unsigned index);
  1.3472 +
  1.3473 +namespace xpc {
  1.3474 +
  1.3475 +class CompartmentPrivate
  1.3476 +{
  1.3477 +public:
  1.3478 +    enum LocationHint {
  1.3479 +        LocationHintRegular,
  1.3480 +        LocationHintAddon
  1.3481 +    };
  1.3482 +
  1.3483 +    CompartmentPrivate(JSCompartment *c)
  1.3484 +        : wantXrays(false)
  1.3485 +        , universalXPConnectEnabled(false)
  1.3486 +        , adoptedNode(false)
  1.3487 +        , donatedNode(false)
  1.3488 +        , scriptability(c)
  1.3489 +        , scope(nullptr)
  1.3490 +    {
  1.3491 +        MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
  1.3492 +    }
  1.3493 +
  1.3494 +    ~CompartmentPrivate();
  1.3495 +
  1.3496 +    bool wantXrays;
  1.3497 +
  1.3498 +    // This is only ever set during mochitest runs when enablePrivilege is called.
  1.3499 +    // It's intended as a temporary stopgap measure until we can finish ripping out
  1.3500 +    // enablePrivilege. Once set, this value is never unset (i.e., it doesn't follow
  1.3501 +    // the old scoping rules of enablePrivilege). Using it is inherently unsafe.
  1.3502 +    bool universalXPConnectEnabled;
  1.3503 +
  1.3504 +    // for telemetry. See bug 928476.
  1.3505 +    bool adoptedNode;
  1.3506 +    bool donatedNode;
  1.3507 +
  1.3508 +    // The scriptability of this compartment.
  1.3509 +    Scriptability scriptability;
  1.3510 +
  1.3511 +    // Our XPCWrappedNativeScope. This is non-null if and only if this is an
  1.3512 +    // XPConnect compartment.
  1.3513 +    XPCWrappedNativeScope *scope;
  1.3514 +
  1.3515 +    const nsACString& GetLocation() {
  1.3516 +        if (location.IsEmpty() && locationURI) {
  1.3517 +            if (NS_FAILED(locationURI->GetSpec(location)))
  1.3518 +                location = NS_LITERAL_CSTRING("<unknown location>");
  1.3519 +        }
  1.3520 +        return location;
  1.3521 +    }
  1.3522 +    bool GetLocationURI(nsIURI **aURI) {
  1.3523 +        return GetLocationURI(LocationHintRegular, aURI);
  1.3524 +    }
  1.3525 +    bool GetLocationURI(LocationHint aLocationHint, nsIURI **aURI) {
  1.3526 +        if (locationURI) {
  1.3527 +            nsCOMPtr<nsIURI> rval = locationURI;
  1.3528 +            rval.forget(aURI);
  1.3529 +            return true;
  1.3530 +        }
  1.3531 +        return TryParseLocationURI(aLocationHint, aURI);
  1.3532 +    }
  1.3533 +    void SetLocation(const nsACString& aLocation) {
  1.3534 +        if (aLocation.IsEmpty())
  1.3535 +            return;
  1.3536 +        if (!location.IsEmpty() || locationURI)
  1.3537 +            return;
  1.3538 +        location = aLocation;
  1.3539 +    }
  1.3540 +    void SetLocationURI(nsIURI *aLocationURI) {
  1.3541 +        if (!aLocationURI)
  1.3542 +            return;
  1.3543 +        if (locationURI)
  1.3544 +            return;
  1.3545 +        locationURI = aLocationURI;
  1.3546 +    }
  1.3547 +
  1.3548 +private:
  1.3549 +    nsCString location;
  1.3550 +    nsCOMPtr<nsIURI> locationURI;
  1.3551 +
  1.3552 +    bool TryParseLocationURI(LocationHint aType, nsIURI** aURI);
  1.3553 +};
  1.3554 +
  1.3555 +CompartmentPrivate*
  1.3556 +EnsureCompartmentPrivate(JSObject *obj);
  1.3557 +
  1.3558 +CompartmentPrivate*
  1.3559 +EnsureCompartmentPrivate(JSCompartment *c);
  1.3560 +
  1.3561 +inline CompartmentPrivate*
  1.3562 +GetCompartmentPrivate(JSCompartment *compartment)
  1.3563 +{
  1.3564 +    MOZ_ASSERT(compartment);
  1.3565 +    void *priv = JS_GetCompartmentPrivate(compartment);
  1.3566 +    return static_cast<CompartmentPrivate*>(priv);
  1.3567 +}
  1.3568 +
  1.3569 +inline CompartmentPrivate*
  1.3570 +GetCompartmentPrivate(JSObject *object)
  1.3571 +{
  1.3572 +    MOZ_ASSERT(object);
  1.3573 +    JSCompartment *compartment = js::GetObjectCompartment(object);
  1.3574 +
  1.3575 +    MOZ_ASSERT(compartment);
  1.3576 +    return GetCompartmentPrivate(compartment);
  1.3577 +}
  1.3578 +
  1.3579 +bool IsUniversalXPConnectEnabled(JSCompartment *compartment);
  1.3580 +bool IsUniversalXPConnectEnabled(JSContext *cx);
  1.3581 +bool EnableUniversalXPConnect(JSContext *cx);
  1.3582 +
  1.3583 +// This returns null if and only if it is called on an object in a non-XPConnect
  1.3584 +// compartment.
  1.3585 +inline XPCWrappedNativeScope*
  1.3586 +GetObjectScope(JSObject *obj)
  1.3587 +{
  1.3588 +    return EnsureCompartmentPrivate(obj)->scope;
  1.3589 +}
  1.3590 +
  1.3591 +// This returns null if a scope doesn't already exist.
  1.3592 +XPCWrappedNativeScope* MaybeGetObjectScope(JSObject *obj);
  1.3593 +
  1.3594 +extern bool gDebugMode;
  1.3595 +extern bool gDesiredDebugMode;
  1.3596 +
  1.3597 +extern const JSClass SafeJSContextGlobalClass;
  1.3598 +
  1.3599 +JSObject* NewOutObject(JSContext* cx, JSObject* scope);
  1.3600 +bool IsOutObject(JSContext* cx, JSObject* obj);
  1.3601 +
  1.3602 +nsresult HasInstance(JSContext *cx, JS::HandleObject objArg, const nsID *iid, bool *bp);
  1.3603 +
  1.3604 +/**
  1.3605 + * Define quick stubs on the given object, @a proto.
  1.3606 + *
  1.3607 + * @param cx
  1.3608 + *     A context.  Requires request.
  1.3609 + * @param proto
  1.3610 + *     The (newly created) prototype object for a DOM class.  The JS half
  1.3611 + *     of an XPCWrappedNativeProto.
  1.3612 + * @param flags
  1.3613 + *     Property flags for the quick stub properties--should be either
  1.3614 + *     JSPROP_ENUMERATE or 0.
  1.3615 + * @param interfaceCount
  1.3616 + *     The number of interfaces the class implements.
  1.3617 + * @param interfaceArray
  1.3618 + *     The interfaces the class implements; interfaceArray and
  1.3619 + *     interfaceCount are like what nsIClassInfo.getInterfaces returns.
  1.3620 + */
  1.3621 +bool
  1.3622 +DOM_DefineQuickStubs(JSContext *cx, JSObject *proto, uint32_t flags,
  1.3623 +                     uint32_t interfaceCount, const nsIID **interfaceArray);
  1.3624 +
  1.3625 +nsIPrincipal *GetObjectPrincipal(JSObject *obj);
  1.3626 +
  1.3627 +} // namespace xpc
  1.3628 +
  1.3629 +namespace mozilla {
  1.3630 +namespace dom {
  1.3631 +extern bool
  1.3632 +DefineStaticJSVals(JSContext *cx);
  1.3633 +} // namespace dom
  1.3634 +} // namespace mozilla
  1.3635 +
  1.3636 +bool
  1.3637 +xpc_LocalizeRuntime(JSRuntime *rt);
  1.3638 +void
  1.3639 +xpc_DelocalizeRuntime(JSRuntime *rt);
  1.3640 +
  1.3641 +/***************************************************************************/
  1.3642 +// Inlines use the above - include last.
  1.3643 +
  1.3644 +#include "XPCInlines.h"
  1.3645 +
  1.3646 +/***************************************************************************/
  1.3647 +// Maps have inlines that use the above - include last.
  1.3648 +
  1.3649 +#include "XPCMaps.h"
  1.3650 +
  1.3651 +/***************************************************************************/
  1.3652 +
  1.3653 +#endif /* xpcprivate_h___ */

mercurial