Bug 606585 - Make the compartment map use principals properly. r=peterv/bz

--HG--
extra : rebase_source : b4585beb4aa5f9f44cb02beb3f0f91212345f1f8
This commit is contained in:
Blake Kaplan 2010-10-26 23:57:31 -07:00
parent c04b88acb1
commit b35c9ba393
19 changed files with 269 additions and 131 deletions

View File

@ -315,7 +315,7 @@ nsInProcessTabChildGlobal::InitTabChildGlobal()
nsresult rv =
xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
NS_GET_IID(nsISupports),
GetPrincipal(), EmptyCString(),
GetPrincipal(), nsnull,
flags, getter_AddRefs(mGlobal));
NS_ENSURE_SUCCESS(rv, false);

View File

@ -327,11 +327,9 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment(PRUint32 aLangID)
JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
nsIPrincipal *principal = GetPrincipal();
nsCString origin;
JSCompartment *compartment;
principal->GetOrigin(getter_Copies(origin));
rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal,
rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull,
false, &mJSObject, &compartment);
NS_ENSURE_SUCCESS(rv, nsnull);

View File

@ -732,12 +732,10 @@ nsXULPDGlobalObject::EnsureScriptEnvironment(PRUint32 lang_id)
JSAutoRequest ar(cx);
nsIPrincipal *principal = GetPrincipal();
nsCString origin;
JSObject *newGlob;
JSCompartment *compartment;
principal->GetOrigin(getter_Copies(origin));
rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal,
rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull,
false, &newGlob, &compartment);
NS_ENSURE_SUCCESS(rv, nsnull);

View File

@ -2537,7 +2537,7 @@ nsJSContext::CreateNativeGlobalForInner(
InitClassesWithNewWrappedGlobal(mContext,
aNewInner, NS_GET_IID(nsISupports),
aIsChrome ? systemPrincipal.get() : aPrincipal,
EmptyCString(), flags,
nsnull, flags,
getter_AddRefs(jsholder));
if (NS_FAILED(rv))
return rv;

View File

@ -973,7 +973,7 @@ TabChild::InitTabChildGlobal()
nsresult rv =
xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
NS_GET_IID(nsISupports),
scope->GetPrincipal(), EmptyCString(),
scope->GetPrincipal(), nsnull,
flags, getter_AddRefs(mGlobal));
NS_ENSURE_SUCCESS(rv, false);

View File

@ -1641,15 +1641,12 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest,
const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
nsIXPConnect::OMIT_COMPONENTS_OBJECT;
nsCAutoString origin("DOM worker: ");
origin.AppendInt((PRUint64)this);
nsCOMPtr<nsIXPConnectJSObjectHolder> globalWrapper;
nsresult rv =
xpc->InitClassesWithNewWrappedGlobal(aCx, scopeSupports,
NS_GET_IID(nsISupports), nsnull,
origin, flags,
getter_AddRefs(globalWrapper));
NS_ISUPPORTS_CAST(nsIWorker*, this),
flags, getter_AddRefs(globalWrapper));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
JSObject* global;

View File

@ -618,7 +618,7 @@ NS_IMETHODIMP nsJSSh::Init()
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
xpc->InitClassesWithNewWrappedGlobal(mJSContext, (nsIJSSh*)this,
NS_GET_IID(nsISupports),
PR_TRUE,
mPrincipal, nsnull, PR_TRUE,
getter_AddRefs(holder));
if (!holder) {
NS_ERROR("global initialization failed");

View File

@ -1164,7 +1164,7 @@ XPCShellEnvironment::Init()
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
NS_GET_IID(nsISupports),
principal,
EmptyCString(),
nsnull,
nsIXPConnect::
FLAG_SYSTEM_GLOBAL_OBJECT,
getter_AddRefs(holder));

View File

@ -399,7 +399,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%}
[uuid(74b5811e-92d1-468a-a59a-47760200370f)]
[uuid(fb780ace-dced-432b-bb82-8df7d4f919c8)]
interface nsIXPConnect : nsISupports
{
%{ C++
@ -424,12 +424,10 @@ interface nsIXPConnect : nsISupports
* @param aCOMObj the native object that represents the global object.
* @param aIID the IID used to wrap the global object.
* @param aPrincipal the principal of the code that will run in this
* compartment. Can be null. If no specific origin is
* passed, will be used to compute the origin.
* @param aOrigin must be passed if aPrincipal is null. If non-empty,
* overrides aPrincipal's origin. (can be used to separate
* code from the same principals into different
* comartments, like sandboxes).
* compartment. Can be null if not on the main thread.
* @param aExtraPtr must be passed if aPrincipal is null. Used to separate
* code from the same principal into different
* compartments, as for sandboxes.
* @param aFlags one of the flags below specifying what options this
* global object wants.
*/
@ -439,7 +437,7 @@ interface nsIXPConnect : nsISupports
in nsISupports aCOMObj,
in nsIIDRef aIID,
in nsIPrincipal aPrincipal,
in ACString aOrigin,
in nsISupports aExtraPtr,
in PRUint32 aFlags);
const PRUint32 INIT_JS_STANDARD_CLASSES = 1 << 0;

View File

@ -976,7 +976,7 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
NS_GET_IID(nsISupports),
mSystemPrincipal,
EmptyCString(),
nsnull,
nsIXPConnect::
FLAG_SYSTEM_GLOBAL_OBJECT,
getter_AddRefs(holder));

View File

@ -1957,7 +1957,7 @@ main(int argc, char **argv)
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
NS_GET_IID(nsISupports),
systemprincipal,
EmptyCString(),
nsnull,
nsIXPConnect::
FLAG_SYSTEM_GLOBAL_OBJECT,
getter_AddRefs(holder));

View File

@ -60,8 +60,6 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject);
} // namespace XPCNativeWrapper
extern nsIScriptSecurityManager *gScriptSecurityManager;
// This namespace wraps some common functionality between the three existing
// wrappers. Its main purpose is to allow XPCCrossOriginWrapper to act both
// as an XPCSafeJSObjectWrapper and as an XPCNativeWrapper when required to
@ -75,7 +73,7 @@ namespace XPCWrapper {
inline nsIScriptSecurityManager *
GetSecurityManager()
{
return ::gScriptSecurityManager;
return nsXPConnect::gScriptSecurityManager;
}
inline JSBool

View File

@ -75,7 +75,7 @@ PRUint32 nsXPConnect::gReportAllJSExceptions = 0;
// Global cache of the default script security manager (QI'd to
// nsIScriptSecurityManager)
nsIScriptSecurityManager *gScriptSecurityManager = nsnull;
nsIScriptSecurityManager *nsXPConnect::gScriptSecurityManager = nsnull;
const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1";
const char XPC_RUNTIME_CONTRACTID[] = "@mozilla.org/js/xpc/RuntimeService;1";
@ -939,69 +939,105 @@ static JSClass xpcTempGlobalClass = {
JSCLASS_NO_OPTIONAL_MEMBERS
};
static bool
CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
xpc::CompartmentPrivate *priv, JSObject **global,
JSCompartment **compartment)
{
// We take ownership of |priv|. Ensure that either we free it in the case
// of failure or give ownership to the compartment in case of success (in
// that case it will be free'd in CompartmentCallback during GC).
nsAutoPtr<xpc::CompartmentPrivate> priv_holder(priv);
JSPrincipals *principals = nsnull;
if(principal)
principal->GetJSPrincipals(cx, &principals);
JSObject *tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals);
if(principals)
JSPRINCIPALS_DROP(cx, principals);
if(!tempGlobal)
return false;
*global = tempGlobal;
*compartment = tempGlobal->getCompartment();
js::SwitchToCompartment sc(cx, *compartment);
JS_SetCompartmentPrivate(cx, *compartment, priv_holder.forget());
return true;
}
nsresult
xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
const nsACString &origin, nsIPrincipal *principal,
nsIPrincipal *principal, nsISupports *ptr,
bool wantXrays, JSObject **global,
JSCompartment **compartment)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "using a principal off the main thread?");
NS_ABORT_IF_FALSE(principal, "bad key");
nsCOMPtr<nsIURI> uri;
nsresult rv = principal->GetURI(getter_AddRefs(uri));
if(NS_FAILED(rv))
return UnexpectedFailure(rv);
XPCCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetCompartmentMap();
nsCAutoString local_origin(origin);
if(local_origin.EqualsLiteral("file://") && principal)
xpc::PtrAndPrincipalHashKey key(ptr, uri);
if(!map.Get(&key, compartment))
{
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
uri->GetSpec(local_origin);
}
JSObject *tempGlobal;
if(!map.Get(local_origin, compartment))
{
JSPrincipals *principals = nsnull;
if(principal)
principal->GetJSPrincipals(cx, &principals);
tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals);
if(principals)
JSPRINCIPALS_DROP(cx, principals);
if(!tempGlobal)
return UnexpectedFailure(NS_ERROR_FAILURE);
*global = tempGlobal;
*compartment = tempGlobal->getCompartment();
js::SwitchToCompartment sc(cx, *compartment);
xpc::PtrAndPrincipalHashKey *priv_key =
new xpc::PtrAndPrincipalHashKey(ptr, uri);
xpc::CompartmentPrivate *priv =
new xpc::CompartmentPrivate(ToNewCString(local_origin), wantXrays);
JS_SetCompartmentPrivate(cx, *compartment, priv);
map.Put(local_origin, *compartment);
new xpc::CompartmentPrivate(priv_key, wantXrays);
if(!CreateNewCompartment(cx, clasp, principal, priv,
global, compartment))
{
return UnexpectedFailure(NS_ERROR_FAILURE);
}
map.Put(&key, *compartment);
}
else
{
js::SwitchToCompartment sc(cx, *compartment);
#ifdef DEBUG
if(principal)
{
nsIPrincipal *cprincipal = xpc::AccessCheck::getPrincipal(*compartment);
PRBool equals;
nsresult rv = cprincipal->Equals(principal, &equals);
NS_ASSERTION(NS_SUCCEEDED(rv), "bad Equals implementation");
if(!equals)
{
nsCOMPtr<nsIURI> domain;
cprincipal->GetDomain(getter_AddRefs(domain));
if(!domain)
{
principal->GetDomain(getter_AddRefs(domain));
NS_ASSERTION(!domain, "bad mixing");
}
}
}
#endif
tempGlobal = JS_NewGlobalObject(cx, clasp);
JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp);
if(!tempGlobal)
return UnexpectedFailure(NS_ERROR_FAILURE);
*global = tempGlobal;
}
return NS_OK;
}
nsresult
xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp,
nsISupports *ptr, JSObject **global,
JSCompartment **compartment)
{
// NB: We can be either on or off the main thread here.
XPCMTCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetMTCompartmentMap();
if(!map.Get(ptr, compartment))
{
// We allow the pointer to be a principal, in which case it becomes
// the principal for the newly created compartment. The caller is
// responsible for ensuring that doing this doesn't violate
// threadsafety assumptions.
nsCOMPtr<nsIPrincipal> principal(do_QueryInterface(ptr));
xpc::CompartmentPrivate *priv =
new xpc::CompartmentPrivate(ptr, false);
if(!CreateNewCompartment(cx, clasp, principal, priv, global,
compartment))
{
return UnexpectedFailure(NS_ERROR_UNEXPECTED);
}
map.Put(ptr, *compartment);
}
else
{
js::SwitchToCompartment sc(cx, *compartment);
JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp);
if(!tempGlobal)
return UnexpectedFailure(NS_ERROR_FAILURE);
*global = tempGlobal;
@ -1010,20 +1046,19 @@ xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
return NS_OK;
}
/* nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal (in JSContextPtr aJSContext, in nsISupports aCOMObj, in nsIIDRef aIID, in PRUint32 aFlags); */
NS_IMETHODIMP
nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
nsISupports *aCOMObj,
const nsIID & aIID,
nsIPrincipal * aPrincipal,
const nsACString & aOrigin,
nsISupports * aExtraPtr,
PRUint32 aFlags,
nsIXPConnectJSObjectHolder **_retval)
{
NS_ASSERTION(aJSContext, "bad param");
NS_ASSERTION(aCOMObj, "bad param");
NS_ASSERTION(_retval, "bad param");
NS_ASSERTION(!aOrigin.IsEmpty() || aPrincipal, "must be able to assign an origin");
NS_ASSERTION(aExtraPtr || aPrincipal, "must be able to find a compartment");
// XXX This is not pretty. We make a temporary global object and
// init it with all the Components object junk just so we have a
@ -1032,18 +1067,16 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
XPCCallContext ccx(NATIVE_CALLER, aJSContext);
nsCString origin;
if(aOrigin.IsEmpty())
aPrincipal->GetOrigin(getter_Copies(origin));
else
origin = aOrigin;
JSCompartment* compartment;
JSObject* tempGlobal;
nsresult rv = xpc_CreateGlobalObject(ccx, &xpcTempGlobalClass, origin,
aPrincipal, false, &tempGlobal,
&compartment);
nsresult rv = aPrincipal
? xpc_CreateGlobalObject(ccx, &xpcTempGlobalClass, aPrincipal,
aExtraPtr, false, &tempGlobal,
&compartment)
: xpc_CreateMTGlobalObject(ccx, &xpcTempGlobalClass,
aExtraPtr, &tempGlobal,
&compartment);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoEnterCompartment ac;

View File

@ -3174,6 +3174,15 @@ WrapForSandbox(JSContext *cx, bool wantXrays, jsval *vp)
: xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp);
}
// Needed to distinguish multiple compartments with the same origin from each
// other. The only thing we need out of identity objects are unique addresses.
class Identity : public nsISupports
{
NS_DECL_ISUPPORTS
};
NS_IMPL_ISUPPORTS0(Identity)
nsresult
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto,
bool wantXrays)
@ -3209,25 +3218,12 @@ xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSOb
}
nsIPrincipal *principal = sop->GetPrincipal();
nsAdoptingCString principalorigin;
principal->GetOrigin(getter_Copies(principalorigin));
nsCAutoString origin("sandbox:");
origin.Append(principalorigin);
nsRefPtr<nsNullPrincipal> nullPrincipal = new nsNullPrincipal();
rv = nullPrincipal->Init();
NS_ENSURE_SUCCESS(rv, rv);
rv = nullPrincipal->GetOrigin(getter_Copies(principalorigin));
NS_ENSURE_SUCCESS(rv, rv);
origin.Append(principalorigin);
JSCompartment *compartment;
JSObject *sandbox;
rv = xpc_CreateGlobalObject(cx, &SandboxClass, origin, principal,
nsRefPtr<Identity> identity = new Identity();
rv = xpc_CreateGlobalObject(cx, &SandboxClass, principal, identity,
wantXrays, &sandbox, &compartment);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -44,6 +44,19 @@
#define xpcinlines_h___
/***************************************************************************/
PRBool
xpc::PtrAndPrincipalHashKey::KeyEquals(const PtrAndPrincipalHashKey* aKey) const
{
if(aKey->mPtr != mPtr)
return PR_FALSE;
if(!mURI || !aKey->mURI)
return mURI == aKey->mURI;
nsIScriptSecurityManager *ssm = nsXPConnect::gScriptSecurityManager;
return !ssm || NS_SUCCEEDED(ssm->CheckSameOriginURI(mURI, aKey->mURI, PR_FALSE));
}
inline void
XPCJSRuntime::AddVariantRoot(XPCTraceableVariant* variant)
{

View File

@ -246,24 +246,37 @@ CompartmentCallback(JSContext *cx, JSCompartment *compartment, uintN op)
if(!self)
return JS_TRUE;
XPCCompartmentMap& map = self->GetCompartmentMap();
nsAutoPtr<xpc::CompartmentPrivate> priv(
static_cast<xpc::CompartmentPrivate*>(JS_SetCompartmentPrivate(cx, compartment, nsnull)));
if (!priv)
if(!priv)
return JS_TRUE;
nsAdoptingCString origin;
origin.Adopt(static_cast<char *>(priv->origin));
#ifdef DEBUG
if(xpc::PtrAndPrincipalHashKey *key = priv->key)
{
JSCompartment *current;
NS_ASSERTION(map.Get(origin, &current), "no compartment?");
NS_ASSERTION(current == compartment, "compartment mismatch");
}
XPCCompartmentMap &map = self->GetCompartmentMap();
#ifdef DEBUG
{
JSCompartment *current;
NS_ASSERTION(map.Get(key, &current), "no compartment?");
NS_ASSERTION(current == compartment, "compartment mismatch");
}
#endif
map.Remove(key);
}
else
{
nsISupports *ptr = priv->ptr;
XPCMTCompartmentMap &map = self->GetMTCompartmentMap();
#ifdef DEBUG
{
JSCompartment *current;
NS_ASSERTION(map.Get(ptr, &current), "no compartment?");
NS_ASSERTION(current == compartment, "compartment mismatch");
}
#endif
map.Remove(ptr);
}
map.Remove(origin);
return JS_TRUE;
}
@ -1168,6 +1181,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
mJSHolders.ops = nsnull;
mCompartmentMap.Init();
mMTCompartmentMap.Init();
// Install a JavaScript 'debugger' keyword handler in debug builds only
#ifdef DEBUG

View File

@ -117,6 +117,9 @@
#include "nsWrapperCache.h"
#include "nsStringBuffer.h"
#include "nsIScriptSecurityManager.h"
#include "nsNetUtil.h"
#include "nsIXPCScriptNotify.h" // used to notify: ScriptEvaluated
#ifndef XPCONNECT_STANDALONE
@ -242,7 +245,75 @@ extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
extern const char XPC_ID_CONTRACTID[];
extern const char XPC_XPCONNECT_CONTRACTID[];
typedef nsDataHashtableMT<nsCStringHashKey, JSCompartment *> XPCCompartmentMap;
namespace xpc {
class PtrAndPrincipalHashKey : public PLDHashEntryHdr
{
public:
typedef PtrAndPrincipalHashKey *KeyType;
typedef const PtrAndPrincipalHashKey *KeyTypePointer;
PtrAndPrincipalHashKey(const PtrAndPrincipalHashKey *aKey)
: mPtr(aKey->mPtr), mURI(aKey->mURI), mSavedHash(aKey->mSavedHash)
{
MOZ_COUNT_CTOR(PtrAndPrincipalHashKey);
}
PtrAndPrincipalHashKey(nsISupports *aPtr, nsIURI *aURI)
: mPtr(aPtr), mURI(aURI)
{
MOZ_COUNT_CTOR(PtrAndPrincipalHashKey);
mSavedHash = mURI
? NS_SecurityHashURI(mURI)
: (NS_PTR_TO_UINT32(mPtr.get()) >> 2);
}
~PtrAndPrincipalHashKey()
{
MOZ_COUNT_DTOR(PtrAndPrincipalHashKey);
}
PtrAndPrincipalHashKey* GetKey() const
{
return const_cast<PtrAndPrincipalHashKey*>(this);
}
const PtrAndPrincipalHashKey* GetKeyPointer() const { return this; }
inline PRBool KeyEquals(const PtrAndPrincipalHashKey* aKey) const;
static const PtrAndPrincipalHashKey*
KeyToPointer(PtrAndPrincipalHashKey* aKey) { return aKey; }
static PLDHashNumber HashKey(const PtrAndPrincipalHashKey* aKey)
{
return aKey->mSavedHash;
}
enum { ALLOW_MEMMOVE = PR_TRUE };
protected:
nsCOMPtr<nsISupports> mPtr;
nsCOMPtr<nsIURI> mURI;
// During shutdown, when we GC, we need to remove these keys from the hash
// table. However, computing the saved hash, NS_SecurityHashURI calls back
// into XPCOM (which is illegal during shutdown). In order to avoid this,
// we compute the hash up front, so when we're in GC during shutdown, we
// don't have to call into XPCOM.
PLDHashNumber mSavedHash;
};
}
// NB: nsDataHashtableMT is usually not very useful as all it does is lock
// around each individual operation performed on it. That would imply, that
// the pattern: if(!map.Get(key)) map.Put(key, value); is not safe as another
// thread could race to insert key into map. However, in our case, only one
// thread at any time could attempt to insert |key| into |map|, so it works
// well enough for our uses.
typedef nsDataHashtableMT<nsISupportsHashKey, JSCompartment *> XPCMTCompartmentMap;
// This map is only used on the main thread.
typedef nsDataHashtable<xpc::PtrAndPrincipalHashKey, JSCompartment *> XPCCompartmentMap;
/***************************************************************************/
// useful macros...
@ -555,6 +626,9 @@ private:
nsCOMPtr<nsIXPCScriptable> mBackstagePass;
static PRUint32 gReportAllJSExceptions;
public:
static nsIScriptSecurityManager *gScriptSecurityManager;
};
/***************************************************************************/
@ -631,6 +705,8 @@ public:
XPCCompartmentMap& GetCompartmentMap()
{return mCompartmentMap;}
XPCMTCompartmentMap& GetMTCompartmentMap()
{return mMTCompartmentMap;}
XPCLock* GetMapLock() const {return mMapLock;}
@ -754,6 +830,7 @@ private:
XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap;
XPCNativeWrapperMap* mExplicitNativeWrapperMap;
XPCCompartmentMap mCompartmentMap;
XPCMTCompartmentMap mMTCompartmentMap;
XPCLock* mMapLock;
PRThread* mThreadRunningGC;
nsTArray<nsXPCWrappedJS*> mWrappedJSToReleaseArray;
@ -4431,12 +4508,22 @@ namespace xpc {
struct CompartmentPrivate
{
CompartmentPrivate(char *origin, bool wantXrays)
: origin(origin),
CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays)
: key(key),
ptr(nsnull),
wantXrays(wantXrays)
{
}
char *origin;
CompartmentPrivate(nsISupports *ptr, bool wantXrays)
: key(nsnull),
ptr(ptr),
wantXrays(wantXrays)
{
}
// NB: key and ptr are mutually exclusive.
nsAutoPtr<PtrAndPrincipalHashKey> key;
nsCOMPtr<nsISupports> ptr;
bool wantXrays;
};

View File

@ -41,13 +41,19 @@
#define xpcpublic_h
#include "jsapi.h"
#include "nsAString.h"
#include "nsIPrincipal.h"
#include "nsISupports.h"
class nsIPrincipal;
nsresult
xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
const nsACString &origin, nsIPrincipal *principal,
nsIPrincipal *principal, nsISupports *ptr,
bool wantXrays, JSObject **global,
JSCompartment **compartment);
nsresult
xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp,
nsISupports *ptr, JSObject **global,
JSCompartment **compartment);
#endif

View File

@ -259,16 +259,16 @@ XPCJSContextStack::GetSafeJSContext(JSContext * *aSafeJSContext)
mSafeJSContext = JS_NewContext(rt, 8192);
if(mSafeJSContext)
{
nsCString origin;
principal->GetOrigin(getter_Copies(origin));
// scoped JS Request
JSAutoRequest req(mSafeJSContext);
// Because we can run off the main thread, we create an MT
// global object. Our principal is the unique key.
JSCompartment *compartment;
nsresult rv = xpc_CreateGlobalObject(mSafeJSContext, &global_class,
origin, principal, false, &glob,
&compartment);
nsresult rv = xpc_CreateMTGlobalObject(mSafeJSContext,
&global_class,
principal, &glob,
&compartment);
if(NS_FAILED(rv))
glob = nsnull;