mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 606585 - Make the compartment map use principals properly. r=peterv/bz
--HG-- extra : rebase_source : b4585beb4aa5f9f44cb02beb3f0f91212345f1f8
This commit is contained in:
parent
c04b88acb1
commit
b35c9ba393
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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, ¤t), "no compartment?");
|
||||
NS_ASSERTION(current == compartment, "compartment mismatch");
|
||||
}
|
||||
XPCCompartmentMap &map = self->GetCompartmentMap();
|
||||
#ifdef DEBUG
|
||||
{
|
||||
JSCompartment *current;
|
||||
NS_ASSERTION(map.Get(key, ¤t), "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, ¤t), "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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user