bug 728250 - remove JSPrincipals::codebase. r=:luke,:bz

In just 2 cases where JSPrincipals::codebase is used it can be reconstructed from the values stored in the associated nsJSPrincipal. In addition the patch makes nsJSprincipals to inherit both from nsIPrincipal and JSPrincipals allowing to use static_cast to convert between nsIPrincipal and JSPrincipals pointers and to drop many cases of manual JSPrincipal reference counting.
This commit is contained in:
Igor Bukanov 2012-03-09 10:48:50 +01:00
parent a4e916975c
commit 524dbd7e47
46 changed files with 512 additions and 792 deletions

View File

@ -52,7 +52,7 @@ interface nsIContentSecurityPolicy;
[ptr] native JSContext(JSContext);
[ptr] native JSPrincipals(JSPrincipals);
[scriptable, uuid(1f83b0e0-6b63-4bdc-a50a-b9afe256bd25)]
[scriptable, uuid(f8c4c89a-d726-421b-8415-3e34b241175b)]
interface nsIPrincipal : nsISerializable
{
/**
@ -96,12 +96,6 @@ interface nsIPrincipal : nsISerializable
*/
[noscript] readonly attribute unsigned long hashValue;
/**
* Returns the JS equivalent of the principal.
* @see JSPrincipals.h
*/
[noscript] JSPrincipals getJSPrincipals(in JSContext cx);
/**
* The domain security policy of the principal.
*/

View File

@ -43,14 +43,47 @@
class nsCString;
struct nsJSPrincipals : JSPrincipals
struct nsJSPrincipals : nsIPrincipal, JSPrincipals
{
static nsresult Startup();
nsJSPrincipals();
nsresult Init(nsIPrincipal* aPrincipal, const nsCString& aCodebase);
~nsJSPrincipals(void);
static JSBool Subsume(JSPrincipals *jsprin, JSPrincipals *other);
static void Destroy(JSPrincipals *jsprin);
static JSBool Transcode(JSXDRState *xdr, JSPrincipals **jsprinp);
nsIPrincipal *nsIPrincipalPtr; // [WEAK] it owns us.
/*
* Get a weak reference to nsIPrincipal associated with the given JS
* principal.
*/
static nsJSPrincipals* get(JSPrincipals *principals) {
nsJSPrincipals *self = static_cast<nsJSPrincipals *>(principals);
MOZ_ASSERT_IF(self, self->debugToken == DEBUG_TOKEN);
return self;
}
static nsJSPrincipals* get(nsIPrincipal *principal) {
nsJSPrincipals *self = static_cast<nsJSPrincipals *>(principal);
MOZ_ASSERT_IF(self, self->debugToken == DEBUG_TOKEN);
return self;
}
nsJSPrincipals() {
refcount = 0;
setDebugToken(DEBUG_TOKEN);
}
virtual ~nsJSPrincipals() {
setDebugToken(0);
}
/**
* Return a string that can be used as JS script filename in error reports.
*/
virtual void GetScriptLocation(nsACString &aStr) = 0;
#ifdef DEBUG
virtual void dumpImpl() = 0;
#endif
static const uint32_t DEBUG_TOKEN = 0x0bf41760;
};
#endif /* nsJSPrincipals_h__ */

View File

@ -59,16 +59,16 @@ class nsIURI;
#define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal"
class nsNullPrincipal : public nsIPrincipal
class nsNullPrincipal : public nsJSPrincipals
{
public:
nsNullPrincipal();
// Our refcount is managed by mJSPrincipals. Use this macro to avoid an
// Our refcount is managed by nsJSPrincipals. Use this macro to avoid an
// extra refcount member.
// FIXME: bug 327245 -- I sorta wish there were a clean way to share the
// mJSPrincipals munging code between the various principal classes without
// nsJSPrincipals munging code between the various principal classes without
// giving up the NS_DECL_NSIPRINCIPAL goodness.
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPRINCIPAL
@ -76,10 +76,15 @@ public:
nsresult Init();
protected:
virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE;
#ifdef DEBUG
virtual void dumpImpl() MOZ_OVERRIDE;
#endif
protected:
virtual ~nsNullPrincipal();
nsJSPrincipals mJSPrincipals;
nsCOMPtr<nsIURI> mURI;
};

View File

@ -51,7 +51,7 @@
class nsIObjectInputStream;
class nsIObjectOutputStream;
class nsPrincipal : public nsIPrincipal
class nsPrincipal : public nsJSPrincipals
{
public:
nsPrincipal();
@ -60,7 +60,7 @@ protected:
virtual ~nsPrincipal();
public:
// Our refcount is managed by mJSPrincipals. Use this macro to avoid
// Our refcount is managed by nsJSPrincipals. Use this macro to avoid
// an extra refcount member.
NS_DECL_ISUPPORTS_INHERITED
public:
@ -100,8 +100,13 @@ public:
static const char sInvalid[];
virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE;
#ifdef DEBUG
virtual void dumpImpl() MOZ_OVERRIDE;
#endif
protected:
nsJSPrincipals mJSPrincipals;
nsTArray< nsAutoPtr<nsHashtable> > mAnnotations;
nsHashtable* mCapabilities;
nsCString mPrefName;

View File

@ -428,6 +428,9 @@ private:
jsid id, JSAccessMode mode,
jsval *vp);
static JSPrincipals *
ObjectPrincipalFinder(JSObject *obj);
// Decides, based on CSP, whether or not eval() and stuff can be executed.
static JSBool
ContentSecurityPolicyPermitsJSAction(JSContext *cx);

View File

@ -50,23 +50,26 @@
#define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1"
class nsSystemPrincipal : public nsIPrincipal
class nsSystemPrincipal : public nsJSPrincipals
{
public:
// Our refcount is managed by mJSPrincipals. Use this macro to avoid
// Our refcount is managed by nsJSPrincipals. Use this macro to avoid
// an extra refcount member.
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPRINCIPAL
NS_DECL_NSISERIALIZABLE
nsresult Init(JSPrincipals **jsprin);
nsSystemPrincipal();
virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE;
#ifdef DEBUG
virtual void dumpImpl() MOZ_OVERRIDE;
#endif
protected:
virtual ~nsSystemPrincipal(void);
nsJSPrincipals mJSPrincipals;
// XXX Probably unnecessary. See bug 143559.
NS_DECL_OWNINGTHREAD
};

View File

@ -50,46 +50,44 @@
#include "nsMemory.h"
#include "nsStringBuffer.h"
static JSBool
nsJSPrincipalsSubsume(JSPrincipals *jsprin, JSPrincipals *other)
{
nsJSPrincipals *nsjsprin = static_cast<nsJSPrincipals *>(jsprin);
nsJSPrincipals *nsother = static_cast<nsJSPrincipals *>(other);
// for mozilla::dom::workers::kJSPrincipalsDebugToken
#include "mozilla/dom/workers/Workers.h"
/* static */ JSBool
nsJSPrincipals::Subsume(JSPrincipals *jsprin, JSPrincipals *other)
{
bool result;
nsresult rv = nsjsprin->nsIPrincipalPtr->Subsumes(nsother->nsIPrincipalPtr,
&result);
nsresult rv = nsJSPrincipals::get(jsprin)->Subsumes(nsJSPrincipals::get(other), &result);
return NS_SUCCEEDED(rv) && result;
}
static void
nsDestroyJSPrincipals(JSContext *cx, struct JSPrincipals *jsprin)
/* static */ void
nsJSPrincipals::Destroy(JSPrincipals *jsprin)
{
nsJSPrincipals *nsjsprin = static_cast<nsJSPrincipals *>(jsprin);
// The JS runtime can call this method during the last GC when
// nsScriptSecurityManager is destroyed. So we must not assume here that
// the security manager still exists.
nsJSPrincipals *nsjsprin = nsJSPrincipals::get(jsprin);
// We need to destroy the nsIPrincipal. We'll do this by adding
// to the refcount and calling release
// Note that we don't want to use NS_IF_RELEASE because it will try
// to set nsjsprin->nsIPrincipalPtr to nsnull *after* nsjsprin has
// already been destroyed.
#ifdef NS_BUILD_REFCNT_LOGGING
// The refcount logging considers AddRef-to-1 to indicate creation,
// so trick it into thinking it's otherwise, but balance the
// Release() we do below.
nsjsprin->refcount++;
nsjsprin->nsIPrincipalPtr->AddRef();
nsjsprin->AddRef();
nsjsprin->refcount--;
#else
nsjsprin->refcount++;
#endif
nsjsprin->nsIPrincipalPtr->Release();
// The nsIPrincipal that we release owns the JSPrincipal struct,
// so we don't need to worry about "codebase"
nsjsprin->Release();
}
static JSBool
nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp)
/* static */ JSBool
nsJSPrincipals::Transcode(JSXDRState *xdr, JSPrincipals **jsprinp)
{
nsresult rv;
@ -107,12 +105,7 @@ nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp)
if (NS_SUCCEEDED(rv)) {
::JS_XDRMemResetData(xdr);
// Require that GetJSPrincipals has been called already by the
// code that compiled the script that owns the principals.
nsJSPrincipals *nsjsprin =
static_cast<nsJSPrincipals*>(*jsprinp);
rv = stream->WriteObject(nsjsprin->nsIPrincipalPtr, true);
rv = stream->WriteObject(nsJSPrincipals::get(*jsprinp), true);
}
}
} else {
@ -141,7 +134,8 @@ nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp)
nsMemory::Free(olddata);
::JS_XDRMemSetData(xdr, data, size);
prin->GetJSPrincipals(xdr->cx, jsprinp);
*jsprinp = nsJSPrincipals::get(prin);
JS_HoldPrincipals(*jsprinp);
}
}
}
@ -156,69 +150,22 @@ nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp)
return JS_TRUE;
}
nsresult
nsJSPrincipals::Startup()
#ifdef DEBUG
// Defined here so one can do principals->dump() in the debugger
JS_EXPORT_API(void)
JSPrincipals::dump()
{
nsCOMPtr<nsIJSRuntimeService> rtsvc = nsXPConnect::GetXPConnect();
if (!rtsvc)
return NS_ERROR_FAILURE;
JSRuntime *rt;
rtsvc->GetRuntime(&rt);
NS_ASSERTION(rt != nsnull, "no JSRuntime?!");
JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(rt);
NS_ASSERTION(callbacks, "Need a callbacks struct by now!");
NS_ASSERTION(!callbacks->principalsTranscoder,
"oops, JS_SetPrincipalsTranscoder wars!");
callbacks->principalsTranscoder = nsTranscodeJSPrincipals;
return NS_OK;
}
nsJSPrincipals::nsJSPrincipals()
{
codebase = nsnull;
refcount = 0;
destroy = nsDestroyJSPrincipals;
subsume = nsJSPrincipalsSubsume;
nsIPrincipalPtr = nsnull;
}
nsresult
nsJSPrincipals::Init(nsIPrincipal *aPrincipal, const nsCString& aCodebase)
{
if (nsIPrincipalPtr) {
NS_ERROR("Init called twice!");
return NS_ERROR_UNEXPECTED;
}
nsIPrincipalPtr = aPrincipal;
nsStringBuffer* buf = nsStringBuffer::FromString(aCodebase);
char* data;
if (buf) {
buf->AddRef();
data = static_cast<char*>(buf->Data());
if (debugToken == nsJSPrincipals::DEBUG_TOKEN) {
static_cast<nsJSPrincipals *>(this)->dumpImpl();
} else if (debugToken == mozilla::dom::workers::kJSPrincipalsDebugToken) {
fprintf(stderr, "Web Worker principal singleton (%p)\n", this);
} else {
PRUint32 len = aCodebase.Length();
buf = nsStringBuffer::Alloc(len + 1); // addrefs
if (!buf) {
return NS_ERROR_OUT_OF_MEMORY;
}
data = static_cast<char*>(buf->Data());
memcpy(data, aCodebase.get(), len);
data[len] = '\0';
}
codebase = data;
return NS_OK;
}
nsJSPrincipals::~nsJSPrincipals()
{
if (codebase) {
nsStringBuffer::FromData(codebase)->Release();
fprintf(stderr,
"!!! JSPrincipals (%p) is not nsJSPrincipals instance - bad token: "
"actual=0x%x expected=0x%x\n",
this, unsigned(debugToken), unsigned(nsJSPrincipals::DEBUG_TOKEN));
}
}
#endif

View File

@ -69,8 +69,8 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
NS_IMETHODIMP_(nsrefcnt)
nsNullPrincipal::AddRef()
{
NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount);
NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt");
nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount);
NS_LOG_ADDREF(this, count, "nsNullPrincipal", sizeof(*this));
return count;
}
@ -78,8 +78,8 @@ nsNullPrincipal::AddRef()
NS_IMETHODIMP_(nsrefcnt)
nsNullPrincipal::Release()
{
NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount);
NS_PRECONDITION(0 != refcount, "dup release");
nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount);
NS_LOG_RELEASE(this, count, "nsNullPrincipal");
if (count == 0) {
delete this;
@ -133,9 +133,24 @@ nsNullPrincipal::Init()
mURI = new nsNullPrincipalURI(str);
NS_ENSURE_TRUE(mURI, NS_ERROR_OUT_OF_MEMORY);
return mJSPrincipals.Init(this, str);
return NS_OK;
}
void
nsNullPrincipal::GetScriptLocation(nsACString &aStr)
{
mURI->GetSpec(aStr);
}
#ifdef DEBUG
void nsNullPrincipal::dumpImpl()
{
nsCAutoString str;
mURI->GetSpec(str);
fprintf(stderr, "nsNullPrincipal (%p) = %s\n", this, str.get());
}
#endif
/**
* nsIPrincipal implementation
*/
@ -179,17 +194,6 @@ nsNullPrincipal::GetHashValue(PRUint32 *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **aJsprin)
{
NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr,
"mJSPrincipals is uninitalized!");
JSPRINCIPALS_HOLD(cx, &mJSPrincipals);
*aJsprin = &mJSPrincipals;
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipal::GetSecurityPolicy(void** aSecurityPolicy)
{

View File

@ -93,9 +93,9 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal,
NS_IMETHODIMP_(nsrefcnt)
nsPrincipal::AddRef()
{
NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt");
// XXXcaa does this need to be threadsafe? See bug 143559.
nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount);
nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount);
NS_LOG_ADDREF(this, count, "nsPrincipal", sizeof(*this));
return count;
}
@ -103,8 +103,8 @@ nsPrincipal::AddRef()
NS_IMETHODIMP_(nsrefcnt)
nsPrincipal::Release()
{
NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount);
NS_PRECONDITION(0 != refcount, "dup release");
nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount);
NS_LOG_RELEASE(this, count, "nsPrincipal");
if (count == 0) {
delete this;
@ -147,24 +147,10 @@ nsPrincipal::Init(const nsACString& aCertFingerprint,
mCodebase = NS_TryToMakeImmutable(aCodebase);
mCodebaseImmutable = URIIsImmutable(mCodebase);
nsresult rv;
if (!aCertFingerprint.IsEmpty()) {
rv = SetCertificate(aCertFingerprint, aSubjectName, aPrettyName, aCert);
if (NS_SUCCEEDED(rv)) {
rv = mJSPrincipals.Init(this, mCert->fingerprint);
}
}
else {
nsCAutoString spec;
rv = mCodebase->GetSpec(spec);
if (NS_SUCCEEDED(rv)) {
rv = mJSPrincipals.Init(this, spec);
}
}
if (aCertFingerprint.IsEmpty())
return NS_OK;
NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrincipal::Init() failed");
return rv;
return SetCertificate(aCertFingerprint, aSubjectName, aPrettyName, aCert);
}
nsPrincipal::~nsPrincipal(void)
@ -173,16 +159,25 @@ nsPrincipal::~nsPrincipal(void)
delete mCapabilities;
}
NS_IMETHODIMP
nsPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin)
void
nsPrincipal::GetScriptLocation(nsACString &aStr)
{
NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitialized!");
JSPRINCIPALS_HOLD(cx, &mJSPrincipals);
*jsprin = &mJSPrincipals;
return NS_OK;
if (mCert) {
aStr.Assign(mCert->fingerprint);
} else {
mCodebase->GetSpec(aStr);
}
}
#ifdef DEBUG
void nsPrincipal::dumpImpl()
{
nsCAutoString str;
GetScriptLocation(str);
fprintf(stderr, "nsPrincipal (%p) = %s\n", this, str.get());
}
#endif
NS_IMETHODIMP
nsPrincipal::GetOrigin(char **aOrigin)
{
@ -883,9 +878,6 @@ nsPrincipal::InitFromPersistent(const char* aPrefName,
mTrusted = aTrusted;
}
rv = mJSPrincipals.Init(this, aToken);
NS_ENSURE_SUCCESS(rv, rv);
//-- Save the preference name
mPrefName = aPrefName;

View File

@ -517,6 +517,13 @@ NS_IMPL_ISUPPORTS4(nsScriptSecurityManager,
///////////////////////////////////////////////////
///////////////// Security Checks /////////////////
/* static */ JSPrincipals *
nsScriptSecurityManager::ObjectPrincipalFinder(JSObject *aObj)
{
return nsJSPrincipals::get(doGetObjectPrincipal(aObj));
}
JSBool
nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
{
@ -537,7 +544,7 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
if (!subjectPrincipal) {
// See bug 553448 for discussion of this case.
NS_ASSERTION(!JS_GetSecurityCallbacks(cx)->findObjectPrincipals,
NS_ASSERTION(!JS_GetSecurityCallbacks(js::GetRuntime(cx))->findObjectPrincipals,
"CSP: Should have been able to find subject principal. "
"Reluctantly granting access.");
return JS_TRUE;
@ -2179,11 +2186,7 @@ nsScriptSecurityManager::GetScriptPrincipal(JSContext *cx,
NS_ERROR("Script compiled without principals!");
return nsnull;
}
nsJSPrincipals *nsJSPrin = static_cast<nsJSPrincipals *>(jsp);
nsIPrincipal* result = nsJSPrin->nsIPrincipalPtr;
if (!result)
*rv = NS_ERROR_FAILURE;
return result;
return nsJSPrincipals::get(jsp);
}
// static
@ -3330,7 +3333,6 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
mPrincipals.Init(31);
}
nsresult nsScriptSecurityManager::Init()
{
nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
@ -3365,10 +3367,6 @@ nsresult nsScriptSecurityManager::Init()
nsRefPtr<nsSystemPrincipal> system = new nsSystemPrincipal();
NS_ENSURE_TRUE(system, NS_ERROR_OUT_OF_MEMORY);
JSPrincipals *jsprin;
rv = system->Init(&jsprin);
NS_ENSURE_SUCCESS(rv, rv);
mSystemPrincipal = system;
//-- Register security check callback in the JS engine
@ -3380,20 +3378,19 @@ nsresult nsScriptSecurityManager::Init()
rv = runtimeService->GetRuntime(&sRuntime);
NS_ENSURE_SUCCESS(rv, rv);
static JSSecurityCallbacks securityCallbacks = {
static const JSSecurityCallbacks securityCallbacks = {
CheckObjectAccess,
NULL,
NULL,
nsJSPrincipals::Subsume,
nsJSPrincipals::Transcode,
ObjectPrincipalFinder,
ContentSecurityPolicyPermitsJSAction
};
#ifdef DEBUG
JSSecurityCallbacks *oldcallbacks =
#endif
JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks);
NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!");
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
JS_SetTrustedPrincipals(sRuntime, jsprin);
JS_SetTrustedPrincipals(sRuntime, system);
return NS_OK;
}
@ -3417,7 +3414,7 @@ void
nsScriptSecurityManager::Shutdown()
{
if (sRuntime) {
JS_SetRuntimeSecurityCallbacks(sRuntime, NULL);
JS_SetSecurityCallbacks(sRuntime, NULL);
JS_SetTrustedPrincipals(sRuntime, NULL);
sRuntime = nsnull;
}
@ -3445,13 +3442,6 @@ nsScriptSecurityManager::GetScriptSecurityManager()
return nsnull;
}
rv = nsJSPrincipals::Startup();
if (NS_FAILED(rv)) {
NS_WARNING("can't initialize JS engine security protocol glue!");
delete ssManager;
return nsnull;
}
rv = sXPConnect->SetDefaultSecurityManager(ssManager,
nsIXPCSecurityManager::HOOK_ALL);
if (NS_FAILED(rv)) {

View File

@ -62,8 +62,8 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsSystemPrincipal,
NS_IMETHODIMP_(nsrefcnt)
nsSystemPrincipal::AddRef()
{
NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount);
NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt");
nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount);
NS_LOG_ADDREF(this, count, "nsSystemPrincipal", sizeof(*this));
return count;
}
@ -71,8 +71,8 @@ nsSystemPrincipal::AddRef()
NS_IMETHODIMP_(nsrefcnt)
nsSystemPrincipal::Release()
{
NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount);
NS_PRECONDITION(0 != refcount, "dup release");
nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount);
NS_LOG_RELEASE(this, count, "nsSystemPrincipal");
if (count == 0) {
delete this;
@ -81,13 +81,26 @@ nsSystemPrincipal::Release()
return count;
}
static const char SYSTEM_PRINCIPAL_SPEC[] = "[System Principal]";
void
nsSystemPrincipal::GetScriptLocation(nsACString &aStr)
{
aStr.Assign(SYSTEM_PRINCIPAL_SPEC);
}
#ifdef DEBUG
void nsSystemPrincipal::dumpImpl()
{
fprintf(stderr, "nsSystemPrincipal (%p)\n", this);
}
#endif
///////////////////////////////////////
// Methods implementing nsIPrincipal //
///////////////////////////////////////
#define SYSTEM_PRINCIPAL_SPEC "[System Principal]"
NS_IMETHODIMP
nsSystemPrincipal::GetPreferences(char** aPrefName, char** aID,
char** aSubjectName,
@ -280,16 +293,6 @@ nsSystemPrincipal::SetSecurityPolicy(void* aSecurityPolicy)
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin)
{
NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitialized!");
JSPRINCIPALS_HOLD(cx, &mJSPrincipals);
*jsprin = &mJSPrincipals;
return NS_OK;
}
//////////////////////////////////////////
// Methods implementing nsISerializable //
@ -317,24 +320,6 @@ nsSystemPrincipal::nsSystemPrincipal()
{
}
nsresult
nsSystemPrincipal::Init(JSPrincipals **jsprin)
{
// Use an nsCString so we only do the allocation once here and then
// share with nsJSPrincipals
nsCString str(SYSTEM_PRINCIPAL_SPEC);
if (!str.EqualsLiteral(SYSTEM_PRINCIPAL_SPEC)) {
NS_WARNING("Out of memory initializing system principal");
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = mJSPrincipals.Init(this, str);
NS_ENSURE_SUCCESS(rv, rv);
*jsprin = &mJSPrincipals;
return NS_OK;
}
nsSystemPrincipal::~nsSystemPrincipal(void)
nsSystemPrincipal::~nsSystemPrincipal()
{
}

View File

@ -43,6 +43,7 @@
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsJSUtils.h"
#include "nsJSPrincipals.h"
#include "nsNetUtil.h"
#include "nsScriptLoader.h"
#include "nsIJSContextStack.h"
@ -811,15 +812,13 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
JSObject* global = nsnull;
mGlobal->GetJSObject(&global);
if (global) {
JSPrincipals* jsprin = nsnull;
mPrincipal->GetJSPrincipals(mCx, &jsprin);
uint32 oldopts = JS_GetOptions(mCx);
JS_SetOptions(mCx, oldopts | JSOPTION_NO_SCRIPT_RVAL);
JSScript* script =
JS_CompileUCScriptForPrincipals(mCx, nsnull, jsprin,
(jschar*)dataString.get(),
JS_CompileUCScriptForPrincipals(mCx, nsnull,
nsJSPrincipals::get(mPrincipal),
static_cast<const jschar*>(dataString.get()),
dataString.Length(),
url.get(), 1);
@ -839,8 +838,6 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
}
(void) JS_ExecuteScript(mCx, global, script, nsnull);
}
//XXX Argh, JSPrincipals are manually refcounted!
JSPRINCIPALS_DROP(mCx, jsprin);
}
}
JSContext* unused;

View File

@ -518,11 +518,10 @@ NS_ScriptErrorReporter(JSContext *cx,
innerWindowID = innerWin->WindowID();
}
}
JSPrincipals *prin = report->originPrincipals;
nsIPrincipal *principal =
prin ? static_cast<nsJSPrincipals*>(prin)->nsIPrincipalPtr : nsnull;
nsContentUtils::AddScriptRunner(
new ScriptErrorEvent(globalObject, principal, report->lineno,
new ScriptErrorEvent(globalObject,
nsJSPrincipals::get(report->originPrincipals),
report->lineno,
report->uctokenptr - report->uclinebuf,
report->flags, msg, fileName, sourceLine,
report->errorNumber != JSMSG_OUT_OF_MEMORY,
@ -1218,8 +1217,7 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
// Safety first: get an object representing the script's principals, i.e.,
// the entities who signed this script, or the fully-qualified-domain-name
// or "codebase" from which it was loaded.
JSPrincipals *jsprin;
nsIPrincipal *principal = aPrincipal;
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
nsresult rv;
if (!aPrincipal) {
nsIScriptGlobalObject *global = GetGlobalObject();
@ -1234,15 +1232,10 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
return NS_ERROR_FAILURE;
}
principal->GetJSPrincipals(mContext, &jsprin);
// From here on, we must JSPRINCIPALS_DROP(jsprin) before returning...
bool ok = false;
rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
if (NS_FAILED(rv)) {
JSPRINCIPALS_DROP(mContext, jsprin);
return NS_ERROR_FAILURE;
}
@ -1253,7 +1246,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
nsCOMPtr<nsIJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
JSPRINCIPALS_DROP(mContext, jsprin);
return NS_ERROR_FAILURE;
}
@ -1273,7 +1265,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, aScopeObject)) {
JSPRINCIPALS_DROP(mContext, jsprin);
stack->Pop(nsnull);
return NS_ERROR_FAILURE;
}
@ -1282,7 +1273,7 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
ok = ::JS_EvaluateUCScriptForPrincipalsVersion(mContext,
aScopeObject,
jsprin,
nsJSPrincipals::get(principal),
static_cast<const jschar*>(PromiseFlatString(aScript).get()),
aScript.Length(),
aURL,
@ -1301,9 +1292,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
}
}
// Whew! Finally done with these manually ref-counted things.
JSPRINCIPALS_DROP(mContext, jsprin);
// If all went well, convert val to a string (XXXbe unless undefined?).
if (ok) {
if (aIsUndefined) {
@ -1427,12 +1415,8 @@ nsJSContext::EvaluateString(const nsAString& aScript,
// Safety first: get an object representing the script's principals, i.e.,
// the entities who signed this script, or the fully-qualified-domain-name
// or "codebase" from which it was loaded.
JSPrincipals *jsprin;
nsIPrincipal *principal = aPrincipal;
if (aPrincipal) {
aPrincipal->GetJSPrincipals(mContext, &jsprin);
}
else {
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
if (!aPrincipal) {
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
do_QueryInterface(GetGlobalObject());
if (!objPrincipal)
@ -1440,26 +1424,12 @@ nsJSContext::EvaluateString(const nsAString& aScript,
principal = objPrincipal->GetPrincipal();
if (!principal)
return NS_ERROR_FAILURE;
principal->GetJSPrincipals(mContext, &jsprin);
}
JSPrincipals *originJSprin;
if (aOriginPrincipal) {
aOriginPrincipal->GetJSPrincipals(mContext, &originJSprin);
} else {
originJSprin = nsnull;
}
// From here on, we must JSPRINCIPALS_DROP(jsprin) before returning...
bool ok = false;
nsresult rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
if (NS_FAILED(rv)) {
JSPRINCIPALS_DROP(mContext, jsprin);
if (originJSprin) {
JSPRINCIPALS_DROP(mContext, originJSprin);
}
return NS_ERROR_FAILURE;
}
@ -1470,10 +1440,6 @@ nsJSContext::EvaluateString(const nsAString& aScript,
nsCOMPtr<nsIJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
JSPRINCIPALS_DROP(mContext, jsprin);
if (originJSprin) {
JSPRINCIPALS_DROP(mContext, originJSprin);
}
return NS_ERROR_FAILURE;
}
@ -1498,15 +1464,12 @@ nsJSContext::EvaluateString(const nsAString& aScript,
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, aScopeObject)) {
stack->Pop(nsnull);
JSPRINCIPALS_DROP(mContext, jsprin);
if (originJSprin) {
JSPRINCIPALS_DROP(mContext, originJSprin);
}
return NS_ERROR_FAILURE;
}
ok = JS_EvaluateUCScriptForPrincipalsVersionOrigin(
mContext, aScopeObject, jsprin, originJSprin,
mContext, aScopeObject,
nsJSPrincipals::get(principal), nsJSPrincipals::get(aOriginPrincipal),
static_cast<const jschar*>(PromiseFlatString(aScript).get()),
aScript.Length(), aURL, aLineNo, vp, JSVersion(aVersion));
@ -1519,12 +1482,6 @@ nsJSContext::EvaluateString(const nsAString& aScript,
}
}
// Whew! Finally done with these manually ref-counted things.
JSPRINCIPALS_DROP(mContext, jsprin);
if (originJSprin) {
JSPRINCIPALS_DROP(mContext, originJSprin);
}
// If all went well, convert val to a string if one is wanted.
if (ok) {
JSAutoRequest ar(mContext);
@ -1573,47 +1530,38 @@ nsJSContext::CompileScript(const PRUnichar* aText,
JSObject* scopeObject = ::JS_GetGlobalObject(mContext);
JSPrincipals *jsprin;
aPrincipal->GetJSPrincipals(mContext, &jsprin);
// From here on, we must JSPRINCIPALS_DROP(jsprin) before returning...
bool ok = false;
nsresult rv = sSecurityManager->CanExecuteScripts(mContext, aPrincipal, &ok);
if (NS_FAILED(rv)) {
JSPRINCIPALS_DROP(mContext, jsprin);
return NS_ERROR_FAILURE;
}
aScriptObject.drop(); // ensure old object not used on failure...
// SecurityManager said "ok", but don't compile if aVersion is unknown.
// Don't compile if SecurityManager said "not ok" or aVersion is unknown.
// Since the caller is responsible for parsing the version strings, we just
// check it isn't JSVERSION_UNKNOWN.
if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
JSAutoRequest ar(mContext);
if (!ok || JSVersion(aVersion) == JSVERSION_UNKNOWN)
return NS_OK;
JSAutoRequest ar(mContext);
JSScript* script =
::JS_CompileUCScriptForPrincipalsVersion(mContext,
scopeObject,
jsprin,
static_cast<const jschar*>(aText),
aTextLength,
aURL,
aLineNo,
JSVersion(aVersion));
if (script) {
NS_ASSERTION(aScriptObject.getScriptTypeID()==JAVASCRIPT,
"Expecting JS script object holder");
rv = aScriptObject.set(script);
} else {
rv = NS_ERROR_OUT_OF_MEMORY;
}
JSScript* script =
::JS_CompileUCScriptForPrincipalsVersion(mContext,
scopeObject,
nsJSPrincipals::get(aPrincipal),
static_cast<const jschar*>(aText),
aTextLength,
aURL,
aLineNo,
JSVersion(aVersion));
if (!script) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Whew! Finally done.
JSPRINCIPALS_DROP(mContext, jsprin);
return rv;
NS_ASSERTION(aScriptObject.getScriptTypeID()==JAVASCRIPT,
"Expecting JS script object holder");
return aScriptObject.set(script);
}
nsresult
@ -1836,17 +1784,15 @@ nsJSContext::CompileFunction(JSObject* aTarget,
return NS_ERROR_ILLEGAL_VALUE;
}
JSPrincipals *jsprin = nsnull;
nsIScriptGlobalObject *global = GetGlobalObject();
nsCOMPtr<nsIPrincipal> principal;
if (global) {
// XXXbe why the two-step QI? speed up via a new GetGlobalObjectData func?
nsCOMPtr<nsIScriptObjectPrincipal> globalData = do_QueryInterface(global);
if (globalData) {
nsIPrincipal *prin = globalData->GetPrincipal();
if (!prin)
principal = globalData->GetPrincipal();
if (!principal)
return NS_ERROR_FAILURE;
prin->GetJSPrincipals(mContext, &jsprin);
}
}
@ -1856,7 +1802,8 @@ nsJSContext::CompileFunction(JSObject* aTarget,
JSFunction* fun =
::JS_CompileUCFunctionForPrincipalsVersion(mContext,
aShared ? nsnull : target, jsprin,
aShared ? nsnull : target,
nsJSPrincipals::get(principal),
PromiseFlatCString(aName).get(),
aArgCount, aArgArray,
static_cast<const jschar*>(PromiseFlatString(aBody).get()),
@ -1864,8 +1811,6 @@ nsJSContext::CompileFunction(JSObject* aTarget,
aURL, aLineNo,
JSVersion(aVersion));
if (jsprin)
JSPRINCIPALS_DROP(mContext, jsprin);
if (!fun)
return NS_ERROR_FAILURE;
@ -3768,33 +3713,6 @@ SetMemoryGCSliceTimePrefChangedCallback(const char* aPrefName, void* aClosure)
return 0;
}
static JSPrincipals *
ObjectPrincipalFinder(JSContext *cx, JSObject *obj)
{
if (!sSecurityManager)
return nsnull;
nsCOMPtr<nsIPrincipal> principal;
nsresult rv =
sSecurityManager->GetObjectPrincipal(cx, obj,
getter_AddRefs(principal));
if (NS_FAILED(rv) || !principal) {
return nsnull;
}
JSPrincipals *jsPrincipals = nsnull;
principal->GetJSPrincipals(cx, &jsPrincipals);
// nsIPrincipal::GetJSPrincipals() returns a strong reference to the
// JS principals, but the caller of this function expects a weak
// reference. So we need to release here.
JSPRINCIPALS_DROP(cx, jsPrincipals);
return jsPrincipals;
}
JSObject*
NS_DOMReadStructuredClone(JSContext* cx,
JSStructuredCloneReader* reader,
@ -3853,11 +3771,6 @@ nsJSRuntime::Init()
sPrevGCSliceCallback = js::SetGCSliceCallback(sRuntime, DOMGCSliceCallback);
JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
NS_ASSERTION(callbacks, "SecMan should have set security callbacks!");
callbacks->findObjectPrincipals = ObjectPrincipalFinder;
// Set up the structured clone callbacks.
static JSStructuredCloneCallbacks cloneCallbacks = {
NS_DOMReadStructuredClone,
@ -3955,14 +3868,6 @@ nsJSRuntime::Shutdown()
// We're being shutdown, and there are no more contexts
// alive, release the JS runtime service and the security manager.
if (sRuntimeService && sSecurityManager) {
JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
if (callbacks) {
NS_ASSERTION(callbacks->findObjectPrincipals == ObjectPrincipalFinder,
"Fighting over the findObjectPrincipals callback!");
callbacks->findObjectPrincipals = NULL;
}
}
NS_IF_RELEASE(sRuntimeService);
NS_IF_RELEASE(sSecurityManager);
}

View File

@ -40,31 +40,19 @@
#include "jsapi.h"
BEGIN_WORKERS_NAMESPACE
namespace {
void
PrincipalDestroy(JSContext*, JSPrincipals*)
{
// nothing
}
JSBool
PrincipalSubsume(JSPrincipals*, JSPrincipals*)
{
return JS_TRUE;
}
const char gPrincipalCodebase[] = "Web Worker";
JSPrincipals gPrincipal = {
const_cast<char*>(gPrincipalCodebase),
1, PrincipalDestroy, PrincipalSubsume
1
#ifdef DEBUG
, kJSPrincipalsDebugToken
#endif
};
} // anonymous namespace
BEGIN_WORKERS_NAMESPACE
JSPrincipals*
GetWorkerPrincipal()
{

View File

@ -157,6 +157,22 @@ SwapToISupportsArray(SmartPtr<T>& aSrc,
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf, "js-worker")
struct WorkerJSRuntimeStats : public JS::RuntimeStats
{
WorkerJSRuntimeStats()
: JS::RuntimeStats(JsWorkerMallocSizeOf) { }
virtual void initExtraCompartmentStats(JSCompartment *c,
JS::CompartmentStats *cstats) MOZ_OVERRIDE
{
MOZ_ASSERT(!cstats->extra);
// ReportJSRuntimeExplicitTreeStats expects that cstats->extra is a char pointer
const char *name = js::IsAtomsCompartment(c) ? "Web Worker Atoms" : "Web Worker";
cstats->extra = const_cast<char *>(name);
}
};
class WorkerMemoryReporter : public nsIMemoryMultiReporter
{
WorkerPrivate* mWorkerPrivate;
@ -240,8 +256,7 @@ public:
{
AssertIsOnMainThread();
JS::RuntimeStats rtStats(JsWorkerMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
WorkerJSRuntimeStats rtStats;
nsresult rv = CollectForRuntime(/* isQuick = */false, &rtStats);
if (NS_FAILED(rv)) {
return rv;

View File

@ -123,6 +123,9 @@ protected:
WorkerCrossThreadDispatcher*
GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker);
// Random unique constant to facilitate JSPrincipal debugging
const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2;
END_WORKERS_NAMESPACE
#endif /* mozilla_dom_workers_workers_h__ */

View File

@ -67,6 +67,7 @@
#include "nsIXPCScriptable.h"
#include "nsJSUtils.h"
#include "nsJSPrincipals.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
@ -1058,7 +1059,7 @@ XPCShellEnvironment::~XPCShellEnvironment()
mCxStack = nsnull;
if (mJSPrincipals) {
JSPRINCIPALS_DROP(mCx, mJSPrincipals);
JS_DropPrincipals(JS_GetRuntime(mCx), mJSPrincipals);
}
JSRuntime* rt = gOldContextCallback ? JS_GetRuntime(mCx) : NULL;
@ -1140,10 +1141,8 @@ XPCShellEnvironment::Init()
fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
} else {
// fetch the JS principals and stick in a global
rv = principal->GetJSPrincipals(cx, &mJSPrincipals);
if (NS_FAILED(rv)) {
fprintf(stderr, "+++ Failed to obtain JS principals from SystemPrincipal.\n");
}
mJSPrincipals = nsJSPrincipals::get(principal);
JS_HoldPrincipals(mJSPrincipals);
secman->SetSystemPrincipal(principal);
}
} else {

View File

@ -1,4 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -61,31 +64,13 @@ struct TypeInferenceSizes
size_t temporary;
};
typedef void* (* GetNameCallback)(JSRuntime *rt, JSCompartment *c);
typedef void (* DestroyNameCallback)(void *string);
struct CompartmentStats
{
CompartmentStats()
{
CompartmentStats() {
memset(this, 0, sizeof(*this));
}
void init(void *name_, DestroyNameCallback destroyName)
{
name = name_;
destroyNameCb = destroyName;
}
~CompartmentStats()
{
destroyNameCb(name);
}
// Pointer to an nsCString, which we can't use here.
void *name;
DestroyNameCallback destroyNameCb;
void *extra;
size_t gcHeapArenaHeaders;
size_t gcHeapArenaPadding;
size_t gcHeapArenaUnused;
@ -119,8 +104,7 @@ struct CompartmentStats
struct RuntimeStats
{
RuntimeStats(JSMallocSizeOfFun mallocSizeOf, GetNameCallback getNameCb,
DestroyNameCallback destroyNameCb)
RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
: runtimeObject(0)
, runtimeAtomsTable(0)
, runtimeContexts(0)
@ -149,8 +133,6 @@ struct RuntimeStats
, compartmentStatsVector()
, currCompartmentStats(NULL)
, mallocSizeOf(mallocSizeOf)
, getNameCb(getNameCb)
, destroyNameCb(destroyNameCb)
{}
size_t runtimeObject;
@ -183,8 +165,8 @@ struct RuntimeStats
CompartmentStats *currCompartmentStats;
JSMallocSizeOfFun mallocSizeOf;
GetNameCallback getNameCb;
DestroyNameCallback destroyNameCb;
virtual void initExtraCompartmentStats(JSCompartment *c, CompartmentStats *cstats) = 0;
};
#ifdef JS_THREADSAFE

View File

@ -63,7 +63,7 @@ StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
// CollectRuntimeStats reserves enough space.
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
CompartmentStats &cStats = rtStats->compartmentStatsVector.back();
cStats.init(rtStats->getNameCb(rt, compartment), rtStats->destroyNameCb);
rtStats->initExtraCompartmentStats(compartment, &cStats);
rtStats->currCompartmentStats = &cStats;
// Get the compartment-level numbers.

View File

@ -156,9 +156,9 @@ Parser::~Parser()
{
JSContext *cx = context;
if (principals)
JSPRINCIPALS_DROP(cx, principals);
JS_DropPrincipals(cx->runtime, principals);
if (originPrincipals)
JSPRINCIPALS_DROP(cx, originPrincipals);
JS_DropPrincipals(cx->runtime, originPrincipals);
cx->tempLifoAlloc().release(tempPoolMark);
cx->activeCompilations--;
}
@ -169,10 +169,10 @@ Parser::setPrincipals(JSPrincipals *prin, JSPrincipals *originPrin)
JS_ASSERT(!principals && !originPrincipals);
principals = prin;
if (principals)
JSPRINCIPALS_HOLD(context, principals);
JS_HoldPrincipals(principals);
originPrincipals = originPrin;
if (originPrincipals)
JSPRINCIPALS_HOLD(context, originPrincipals);
JS_HoldPrincipals(originPrincipals);
}
ObjectBox *

View File

@ -158,7 +158,7 @@ TokenStream::TokenStream(JSContext *cx, JSPrincipals *prin, JSPrincipals *origin
cx(cx), originPrincipals(JSScript::normalizeOriginPrincipals(prin, originPrin))
{
if (originPrincipals)
JSPRINCIPALS_HOLD(cx, originPrincipals);
JS_HoldPrincipals(originPrincipals);
}
#ifdef _MSC_VER
@ -248,7 +248,7 @@ TokenStream::~TokenStream()
if (sourceMap)
cx->free_(sourceMap);
if (originPrincipals)
JSPRINCIPALS_DROP(cx, originPrincipals);
JS_DropPrincipals(cx->runtime, originPrincipals);
}
/* Use the fastest available getc. */

View File

@ -1,18 +1,9 @@
#include "tests.h"
static void
Destroy(JSContext *cx, JSPrincipals *prin);
JSPrincipals system_principals = {
(char *)"", 1, Destroy, NULL
1
};
static void
Destroy(JSContext *cx, JSPrincipals *prin)
{
JS_ASSERT(prin == &system_principals);
}
JSClass global_class = {
"global",
JSCLASS_IS_GLOBAL | JSCLASS_GLOBAL_FLAGS,

View File

@ -52,7 +52,7 @@ BEGIN_TEST(test_cloneScript)
END_TEST(test_cloneScript)
void
DestroyPrincipals(JSContext *cx, JSPrincipals *principals)
DestroyPrincipals(JSPrincipals *principals)
{
delete principals;
}
@ -60,54 +60,38 @@ DestroyPrincipals(JSContext *cx, JSPrincipals *principals)
struct Principals : public JSPrincipals
{
public:
Principals(const char *name)
Principals()
{
refcount = 0;
codebase = const_cast<char *>(name);
destroy = DestroyPrincipals;
subsume = NULL;
}
};
class AutoDropPrincipals
{
JSContext *cx;
JSRuntime *rt;
JSPrincipals *principals;
public:
AutoDropPrincipals(JSContext *cx, JSPrincipals *principals)
: cx(cx), principals(principals)
AutoDropPrincipals(JSRuntime *rt, JSPrincipals *principals)
: rt(rt), principals(principals)
{
JSPRINCIPALS_HOLD(cx, principals);
JS_HoldPrincipals(principals);
}
~AutoDropPrincipals()
{
JSPRINCIPALS_DROP(cx, principals);
JS_DropPrincipals(rt, principals);
}
};
JSBool
TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp)
{
return JS_XDRBytes(xdr, reinterpret_cast<char *>(principalsp), sizeof(*principalsp));
}
BEGIN_TEST(test_cloneScriptWithPrincipals)
{
JSSecurityCallbacks cbs = {
NULL,
TranscodePrincipals,
NULL,
NULL
};
JS_InitDestroyPrincipalsCallback(rt, DestroyPrincipals);
JS_SetRuntimeSecurityCallbacks(rt, &cbs);
JSPrincipals *principalsA = new Principals("A");
AutoDropPrincipals dropA(cx, principalsA);
JSPrincipals *principalsB = new Principals("B");
AutoDropPrincipals dropB(cx, principalsB);
JSPrincipals *principalsA = new Principals();
AutoDropPrincipals dropA(rt, principalsA);
JSPrincipals *principalsB = new Principals();
AutoDropPrincipals dropB(rt, principalsB);
JSObject *A, *B;

View File

@ -5,28 +5,19 @@
JSPrincipals *sCurrentGlobalPrincipals = NULL;
JSPrincipals *
ObjectPrincipalsFinder(JSContext *, JSObject *)
ObjectPrincipalsFinder(JSObject *)
{
return sCurrentGlobalPrincipals;
}
JSSecurityCallbacks seccb = {
static const JSSecurityCallbacks seccb = {
NULL,
NULL,
NULL,
ObjectPrincipalsFinder,
NULL
};
static void
Destroy(JSContext *, JSPrincipals *)
{}
static JSBool
Subsume(JSPrincipals *, JSPrincipals *)
{
return true;
}
JSPrincipals *sOriginPrincipalsInErrorReporter = NULL;
static void
@ -35,14 +26,12 @@ ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
sOriginPrincipalsInErrorReporter = report->originPrincipals;
}
char p1str[] = "principal1";
JSPrincipals prin1 = { p1str, 0, Destroy, Subsume };
char p2str[] = "principal2";
JSPrincipals prin2 = { p2str, 0, Destroy, Subsume };
JSPrincipals prin1 = { 1 };
JSPrincipals prin2 = { 1 };
BEGIN_TEST(testOriginPrincipals)
{
JS_SetContextSecurityCallbacks(cx, &seccb);
JS_SetSecurityCallbacks(rt, &seccb);
/*
* Currently, the only way to set a non-trivial originPrincipal is to use

View File

@ -72,23 +72,11 @@ FreezeThaw(JSContext *cx, JSObject *funobj)
return FreezeThawImpl(cx, funobj, JS_XDRFunctionObject);
}
static JSBool
SubsumePrincipals(JSPrincipals *, JSPrincipals *)
{
return true;
}
static JSPrincipals testPrincipals[] = {
{ const_cast<char *>("foo.bar"), 1, NULL, SubsumePrincipals },
{ const_cast<char *>("dot.com"), 1, NULL, SubsumePrincipals },
{ 1 },
{ 1 },
};
static JSBool
CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, jsval *vp)
{
return true;
}
static JSBool
TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp)
{
@ -110,7 +98,7 @@ TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp)
if (index >= mozilla::ArrayLength(testPrincipals))
return false;
*principalsp = &testPrincipals[index];
JSPRINCIPALS_HOLD(xdr->cx, *principalsp);
JS_HoldPrincipals(*principalsp);
}
return true;
@ -118,14 +106,15 @@ TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp)
BEGIN_TEST(testXDR_principals)
{
static JSSecurityCallbacks seccb = {
CheckAccess,
static const JSSecurityCallbacks seccb = {
NULL,
NULL,
TranscodePrincipals,
NULL,
NULL
};
JS_SetRuntimeSecurityCallbacks(rt, &seccb);
JS_SetSecurityCallbacks(rt, &seccb);
JSScript *script;
for (int i = TEST_FIRST; i != TEST_END; ++i) {

View File

@ -696,6 +696,8 @@ JS_IsBuiltinFunctionConstructor(JSFunction *fun)
*/
static JSBool js_NewRuntimeWasCalled = JS_FALSE;
static const JSSecurityCallbacks NullSecurityCallbacks = { };
JSRuntime::JSRuntime()
: atomsCompartment(NULL),
#ifdef JS_THREADSAFE
@ -778,7 +780,8 @@ JSRuntime::JSRuntime()
gcHelperThread(thisFromCtor()),
#endif
debuggerMutations(0),
securityCallbacks(NULL),
securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
destroyPrincipals(NULL),
structuredCloneCallbacks(NULL),
telemetryCallback(NULL),
propertyRemovals(0),
@ -4451,55 +4454,31 @@ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
return CheckAccess(cx, obj, id, mode, vp, attrsp);
}
#ifdef JS_THREADSAFE
JS_PUBLIC_API(int)
JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
JS_PUBLIC_API(void)
JS_HoldPrincipals(JSPrincipals *principals)
{
return JS_ATOMIC_INCREMENT(&principals->refcount);
JS_ATOMIC_INCREMENT(&principals->refcount);
}
JS_PUBLIC_API(int)
JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
JS_PUBLIC_API(void)
JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals)
{
int rc = JS_ATOMIC_DECREMENT(&principals->refcount);
if (rc == 0)
principals->destroy(cx, principals);
return rc;
}
#endif
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks)
{
JSSecurityCallbacks *oldcallbacks;
oldcallbacks = rt->securityCallbacks;
rt->securityCallbacks = callbacks;
return oldcallbacks;
rt->destroyPrincipals(principals);
}
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetRuntimeSecurityCallbacks(JSRuntime *rt)
JS_PUBLIC_API(void)
JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *scb)
{
return rt->securityCallbacks;
JS_ASSERT(scb != &NullSecurityCallbacks);
rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
}
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks)
JS_PUBLIC_API(const JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSRuntime *rt)
{
JSSecurityCallbacks *oldcallbacks;
oldcallbacks = cx->securityCallbacks;
cx->securityCallbacks = callbacks;
return oldcallbacks;
}
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSContext *cx)
{
return cx->securityCallbacks
? cx->securityCallbacks
: cx->runtime->securityCallbacks;
return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : NULL;
}
JS_PUBLIC_API(void)
@ -4508,6 +4487,14 @@ JS_SetTrustedPrincipals(JSRuntime *rt, JSPrincipals *prin)
rt->setTrustedPrincipals(prin);
}
extern JS_PUBLIC_API(void)
JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals)
{
JS_ASSERT(destroyPrincipals);
JS_ASSERT(!rt->destroyPrincipals);
rt->destroyPrincipals = destroyPrincipals;
}
JS_PUBLIC_API(JSFunction *)
JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
JSObject *parent, const char *name)

View File

@ -1520,6 +1520,12 @@ typedef JSBool
* Security protocol types.
*/
typedef void
(* JSDestroyPrincipalsOp)(JSPrincipals *principals);
typedef JSBool
(* JSSubsumePrincipalsOp)(JSPrincipals *principals1, JSPrincipals *principals2);
/*
* XDR-encode or -decode a principals instance, based on whether xdr->mode is
* JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE,
@ -1539,7 +1545,7 @@ typedef JSBool
* callback's implementation.
*/
typedef JSPrincipals *
(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj);
(* JSObjectPrincipalsFinder)(JSObject *obj);
/*
* Used to check if a CSP instance wants to disable eval() and friends.
@ -4088,52 +4094,48 @@ JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v);
* Security protocol.
*/
struct JSPrincipals {
char *codebase;
/* Don't call "destroy"; use reference counting macros below. */
int refcount;
void (* destroy)(JSContext *cx, JSPrincipals *);
JSBool (* subsume)(JSPrincipals *, JSPrincipals *);
};
#ifdef JS_THREADSAFE
#define JSPRINCIPALS_HOLD(cx, principals) JS_HoldPrincipals(cx,principals)
#define JSPRINCIPALS_DROP(cx, principals) JS_DropPrincipals(cx,principals)
extern JS_PUBLIC_API(int)
JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals);
extern JS_PUBLIC_API(int)
JS_DropPrincipals(JSContext *cx, JSPrincipals *principals);
#else
#define JSPRINCIPALS_HOLD(cx, principals) (++(principals)->refcount)
#define JSPRINCIPALS_DROP(cx, principals) \
((--(principals)->refcount == 0) \
? ((*(principals)->destroy)((cx), (principals)), 0) \
: (principals)->refcount)
#ifdef DEBUG
/* A helper to facilitate principals debugging. */
uint32_t debugToken;
#endif
#ifdef __cplusplus
void setDebugToken(uint32_t token) {
# ifdef DEBUG
debugToken = token;
# endif
}
/*
* This is not defined by the JS engine but should be provided by the
* embedding.
*/
JS_PUBLIC_API(void) dump();
#endif
};
extern JS_PUBLIC_API(void)
JS_HoldPrincipals(JSPrincipals *principals);
extern JS_PUBLIC_API(void)
JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals);
struct JSSecurityCallbacks {
JSCheckAccessOp checkObjectAccess;
JSSubsumePrincipalsOp subsumePrincipals;
JSPrincipalsTranscoder principalsTranscoder;
JSObjectPrincipalsFinder findObjectPrincipals;
JSCSPEvalChecker contentSecurityPolicyAllows;
};
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks);
extern JS_PUBLIC_API(void)
JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *callbacks);
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetRuntimeSecurityCallbacks(JSRuntime *rt);
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks);
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSContext *cx);
extern JS_PUBLIC_API(const JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSRuntime *rt);
/*
* Code running with "trusted" principals will be given a deeper stack
@ -4150,6 +4152,14 @@ JS_GetSecurityCallbacks(JSContext *cx);
extern JS_PUBLIC_API(void)
JS_SetTrustedPrincipals(JSRuntime *rt, JSPrincipals *prin);
/*
* Initialize the callback that is called to destroy JSPrincipals instance
* when its reference counter drops to zero. The initialization can be done
* only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals);
/************************************************************************/
/*

View File

@ -988,7 +988,6 @@ JSContext::JSContext(JSRuntime *rt)
#ifdef JS_THREADSAFE
outstandingRequests(0),
#endif
securityCallbacks(NULL),
resolveFlags(0),
rngSeed(0),
iterValue(MagicValue(JS_NO_ITER_VALUE)),

View File

@ -509,11 +509,8 @@ struct JSRuntime : js::RuntimeFriendFields
uint32_t debuggerMutations;
/*
* Security callbacks set on the runtime are used by each context unless
* an override is set on the context.
*/
JSSecurityCallbacks *securityCallbacks;
const JSSecurityCallbacks *securityCallbacks;
JSDestroyPrincipalsOp destroyPrincipals;
/* Structured data callbacks are runtime-wide. */
const JSStructuredCloneCallbacks *structuredCloneCallbacks;
@ -1013,9 +1010,6 @@ struct JSContext : js::ContextFriendFields
#endif /* JSGC_ROOT_ANALYSIS */
/* Security callbacks that override any defined on the runtime. */
JSSecurityCallbacks *securityCallbacks;
/* Stored here to avoid passing it around as a parameter. */
unsigned resolveFlags;

View File

@ -304,8 +304,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
JS_ASSERT(exnObject->isError());
JS_ASSERT(!exnObject->getPrivate());
JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
JSCheckAccessOp checkAccess = callbacks ? callbacks->checkObjectAccess : NULL;
JSCheckAccessOp checkAccess = cx->runtime->securityCallbacks->checkObjectAccess;
Vector<JSStackTraceElem> frames(cx);
Vector<Value> values(cx);
@ -443,7 +442,7 @@ SetExnPrivate(JSContext *cx, JSObject *exnObject, JSExnPrivate *priv)
JS_ASSERT(exnObject->isError());
if (JSErrorReport *report = priv->errorReport) {
if (JSPrincipals *prin = report->originPrincipals)
JSPRINCIPALS_HOLD(cx, prin);
JS_HoldPrincipals(prin);
}
exnObject->setPrivate(priv);
}
@ -455,7 +454,7 @@ exn_finalize(JSContext *cx, JSObject *obj)
if (JSErrorReport *report = priv->errorReport) {
/* HOLD called by SetExnPrivate. */
if (JSPrincipals *prin = report->originPrincipals)
JSPRINCIPALS_DROP(cx, prin);
JS_DropPrincipals(cx->runtime, prin);
cx->free_(report);
}
cx->free_(priv);

View File

@ -2915,7 +2915,7 @@ SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
if (callback)
JS_ALWAYS_TRUE(callback(cx, compartment, JSCOMPARTMENT_DESTROY));
if (compartment->principals)
JSPRINCIPALS_DROP(cx, compartment->principals);
JS_DropPrincipals(rt, compartment->principals);
cx->delete_(compartment);
continue;
}
@ -3905,7 +3905,7 @@ NewCompartment(JSContext *cx, JSPrincipals *principals)
compartment->isSystemCompartment = principals && rt->trustedPrincipals() == principals;
if (principals) {
compartment->principals = principals;
JSPRINCIPALS_HOLD(cx, principals);
JS_HoldPrincipals(principals);
}
compartment->setGCLastBytes(8192, 8192, GC_NORMAL);

View File

@ -789,15 +789,15 @@ EvalCacheLookup(JSContext *cx, JSLinearString *str, StackFrame *caller, unsigned
JSVersion version = cx->findVersion();
JSScript *script;
JSSubsumePrincipalsOp subsume = cx->runtime->securityCallbacks->subsumePrincipals;
while ((script = *scriptp) != NULL) {
if (script->savedCallerFun &&
script->staticLevel == staticLevel &&
script->getVersion() == version &&
!script->hasSingletons &&
(script->principals == principals ||
(principals && script->principals &&
principals->subsume(principals, script->principals) &&
script->principals->subsume(script->principals, principals)))) {
(!subsume || script->principals == principals ||
(subsume(principals, script->principals) &&
subsume(script->principals, principals)))) {
/*
* Get the prior (cache-filling) eval's saved caller function.
* See frontend::CompileScript.
@ -1163,12 +1163,14 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsid id, jsval old,
jsval *nvp, void *closure)
{
JSObject *callable = (JSObject *) closure;
if (JSPrincipals *watcher = callable->principals(cx)) {
if (JSObject *scopeChain = cx->stack.currentScriptedScopeChain()) {
if (JSPrincipals *subject = scopeChain->principals(cx)) {
if (!watcher->subsume(watcher, subject)) {
/* Silently don't call the watch handler. */
return JS_TRUE;
if (JSSubsumePrincipalsOp subsume = cx->runtime->securityCallbacks->subsumePrincipals) {
if (JSPrincipals *watcher = callable->principals(cx)) {
if (JSObject *scopeChain = cx->stack.currentScriptedScopeChain()) {
if (JSPrincipals *subject = scopeChain->principals(cx)) {
if (!subsume(watcher, subject)) {
/* Silently don't call the watch handler. */
return true;
}
}
}
}
@ -5881,10 +5883,7 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
JSBool writing;
JSObject *pobj;
JSProperty *prop;
Class *clasp;
const Shape *shape;
JSSecurityCallbacks *callbacks;
JSCheckAccessOp check;
while (JS_UNLIKELY(obj->isWith()))
obj = obj->getProto();
@ -5948,12 +5947,9 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
* hook. This covers precompilation-based sharing and (possibly
* unintended) runtime sharing across trust boundaries.
*/
clasp = pobj->getClass();
check = clasp->checkAccess;
if (!check) {
callbacks = JS_GetSecurityCallbacks(cx);
check = callbacks ? callbacks->checkObjectAccess : NULL;
}
JSCheckAccessOp check = pobj->getClass()->checkAccess;
if (!check)
check = cx->runtime->securityCallbacks->checkObjectAccess;
return !check || check(cx, pobj, id, mode, vp);
}

View File

@ -1118,9 +1118,8 @@ JSObject::isCallable()
inline JSPrincipals *
JSObject::principals(JSContext *cx)
{
JSSecurityCallbacks *cb = JS_GetSecurityCallbacks(cx);
if (JSObjectPrincipalsFinder finder = cb ? cb->findObjectPrincipals : NULL)
return finder(cx, this);
if (JSObjectPrincipalsFinder find = cx->runtime->securityCallbacks->findObjectPrincipals)
return find(this);
return cx->compartment ? cx->compartment->principals : NULL;
}

View File

@ -703,11 +703,11 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
JS_ASSERT_IF(script->principals, script->originPrincipals);
if (xdr->principals) {
script->principals = xdr->principals;
JSPRINCIPALS_HOLD(cx, xdr->principals);
JS_HoldPrincipals(xdr->principals);
}
if (xdr->originPrincipals) {
script->originPrincipals = xdr->originPrincipals;
JSPRINCIPALS_HOLD(cx, xdr->originPrincipals);
JS_HoldPrincipals(xdr->originPrincipals);
}
}
@ -1256,14 +1256,14 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
script->principals = bce->parser->principals;
if (script->principals)
JSPRINCIPALS_HOLD(cx, script->principals);
JS_HoldPrincipals(script->principals);
/* Establish invariant: principals implies originPrincipals. */
script->originPrincipals = bce->parser->originPrincipals;
if (!script->originPrincipals)
script->originPrincipals = script->principals;
if (script->originPrincipals)
JSPRINCIPALS_HOLD(cx, script->originPrincipals);
JS_HoldPrincipals(script->originPrincipals);
script->sourceMap = (jschar *) bce->parser->tokenStream.releaseSourceMap();
@ -1462,9 +1462,9 @@ JSScript::finalize(JSContext *cx, bool background)
JS_ASSERT_IF(principals, originPrincipals);
if (principals)
JSPRINCIPALS_DROP(cx, principals);
JS_DropPrincipals(cx->runtime, principals);
if (originPrincipals)
JSPRINCIPALS_DROP(cx, originPrincipals);
JS_DropPrincipals(cx->runtime, originPrincipals);
if (types)
types->destroy();

View File

@ -559,7 +559,7 @@ XDRPrincipals(JSXDRState *xdr)
return false;
if (flags & (HAS_PRINCIPALS | HAS_ORIGIN)) {
JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(xdr->cx);
const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(xdr->cx->runtime);
if (xdr->mode == JSXDR_DECODE) {
if (!scb || !scb->principalsTranscoder) {
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
@ -581,7 +581,7 @@ XDRPrincipals(JSXDRState *xdr)
return false;
} else if (xdr->mode == JSXDR_DECODE && xdr->principals) {
xdr->originPrincipals = xdr->principals;
JSPRINCIPALS_HOLD(xdr->cx, xdr->principals);
JS_HoldPrincipals(xdr->principals);
}
}
@ -599,9 +599,9 @@ struct AutoDropXDRPrincipals {
~AutoDropXDRPrincipals() {
if (xdr->mode == JSXDR_DECODE) {
if (xdr->principals)
JSPRINCIPALS_DROP(xdr->cx, xdr->principals);
JS_DropPrincipals(xdr->cx->runtime, xdr->principals);
if (xdr->originPrincipals)
JSPRINCIPALS_DROP(xdr->cx, xdr->originPrincipals);
JS_DropPrincipals(xdr->cx->runtime, xdr->originPrincipals);
}
xdr->principals = NULL;
xdr->originPrincipals = NULL;

View File

@ -4867,22 +4867,11 @@ MaybeOverrideOutFileFromEnv(const char* const envVar,
}
}
JSBool
ShellPrincipalsSubsume(JSPrincipals *, JSPrincipals *)
{
return JS_TRUE;
}
JSPrincipals shellTrustedPrincipals = {
(char *)"[shell trusted principals]",
1,
NULL, /* nobody should be destroying this */
ShellPrincipalsSubsume
};
/* Set the initial counter to 1 so the principal will never be destroyed. */
JSPrincipals shellTrustedPrincipals = { 1 };
JSBool
CheckObjectAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp)
CheckObjectAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, jsval *vp)
{
return true;
}
@ -4891,6 +4880,7 @@ JSSecurityCallbacks securityCallbacks = {
CheckObjectAccess,
NULL,
NULL,
NULL,
NULL
};
@ -5033,7 +5023,7 @@ main(int argc, char **argv, char **envp)
JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff);
JS_SetTrustedPrincipals(rt, &shellTrustedPrincipals);
JS_SetRuntimeSecurityCallbacks(rt, &securityCallbacks);
JS_SetSecurityCallbacks(rt, &securityCallbacks);
JS_SetNativeStackQuota(rt, gMaxStackSize);

View File

@ -386,15 +386,12 @@ GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
{
HeapSlot &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
if (v.isUndefined()) {
JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
/*
* If there are callbacks, make sure that the CSP callback is installed
* and that it permits runtime code generation, then cache the result.
*/
v.set(this, RUNTIME_CODEGEN_ENABLED,
BooleanValue((!callbacks || !callbacks->contentSecurityPolicyAllows) ||
callbacks->contentSecurityPolicyAllows(cx)));
JSCSPEvalChecker allows = cx->runtime->securityCallbacks->contentSecurityPolicyAllows;
v.set(this, RUNTIME_CODEGEN_ENABLED, BooleanValue(!allows || allows(cx)));
}
return !v.isFalse();
}

View File

@ -80,6 +80,7 @@
#include "nsDOMFile.h"
#include "jsxdrapi.h"
#include "jsprf.h"
#include "nsJSPrincipals.h"
// For reporting errors with the console service
#include "nsIScriptError.h"
#include "nsIConsoleService.h"
@ -645,17 +646,6 @@ class ANSIFileAutoCloser
};
#endif
class JSPrincipalsHolder
{
public:
JSPrincipalsHolder(JSContext *cx, JSPrincipals *principals)
: mCx(cx), mPrincipals(principals) {}
~JSPrincipalsHolder() { JSPRINCIPALS_DROP(mCx, mPrincipals); }
private:
JSContext *mCx;
JSPrincipals *mPrincipals;
};
nsresult
mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
nsIURI *aURI,
@ -665,7 +655,6 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
{
nsresult rv;
JSPrincipals* jsPrincipals = nsnull;
JSCLContextHelper cx(this);
JS_AbortIfWrongThread(JS_GetRuntime(cx));
@ -673,11 +662,6 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
// preserve caller's compartment
js::AutoPreserveCompartment pc(cx);
rv = mSystemPrincipal->GetJSPrincipals(cx, &jsPrincipals);
NS_ENSURE_SUCCESS(rv, rv);
JSPrincipalsHolder princHolder(mContext, jsPrincipals);
nsCOMPtr<nsIXPCScriptable> backstagePass;
rv = mRuntimeService->GetBackstagePass(getter_AddRefs(backstagePass));
NS_ENSURE_SUCCESS(rv, rv);
@ -837,7 +821,9 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
return NS_ERROR_FAILURE;
}
script = JS_CompileScriptForPrincipalsVersion(cx, global, jsPrincipals, buf, fileSize32, nativePath.get(), 1,
script = JS_CompileScriptForPrincipalsVersion(cx, global,
nsJSPrincipals::get(mSystemPrincipal),
buf, fileSize32, nativePath.get(), 1,
JSVERSION_LATEST);
PR_MemUnmap(buf, fileSize32);
@ -880,7 +866,9 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
NS_WARNING("Failed to read file");
return NS_ERROR_FAILURE;
}
script = JS_CompileScriptForPrincipalsVersion(cx, global, jsPrincipals, buf, rlen, nativePath.get(), 1,
script = JS_CompileScriptForPrincipalsVersion(cx, global,
nsJSPrincipals::get(mSystemPrincipal),
buf, rlen, nativePath.get(), 1,
JSVERSION_LATEST);
free(buf);
@ -917,7 +905,9 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
buf[len] = '\0';
script = JS_CompileScriptForPrincipalsVersion(cx, global, jsPrincipals, buf, bytesRead, nativePath.get(), 1,
script = JS_CompileScriptForPrincipalsVersion(cx, global,
nsJSPrincipals::get(mSystemPrincipal),
buf, bytesRead, nativePath.get(), 1,
JSVERSION_LATEST);
}
// Propagate the exception, if one exists. Also, don't leave the stale

View File

@ -61,6 +61,7 @@
#include "jsapi.h"
#include "jsdbgapi.h"
#include "jsfriendapi.h"
#include "nsJSPrincipals.h"
#include "mozilla/FunctionTimer.h"
#include "mozilla/scache/StartupCache.h"
@ -111,7 +112,6 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob
{
nsCOMPtr<nsIChannel> chan;
nsCOMPtr<nsIInputStream> instream;
JSPrincipals *jsPrincipals;
JSErrorReporter er;
nsresult rv;
@ -140,14 +140,6 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob
if (NS_FAILED(rv))
return rv;
/* we can't hold onto jsPrincipals as a module var because the
* JSPRINCIPALS_DROP macro takes a JSContext, which we won't have in the
* destructor */
rv = principal->GetJSPrincipals(cx, &jsPrincipals);
if (NS_FAILED(rv) || !jsPrincipals) {
return ReportError(cx, LOAD_ERROR_NOPRINCIPALS);
}
/* set our own error reporter so we can report any bad things as catchable
* exceptions, including the source/line number */
er = JS_SetErrorReporter(cx, mozJSLoaderErrorReporter);
@ -158,21 +150,18 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob
charset, nsnull, script);
if (NS_FAILED(rv)) {
JSPRINCIPALS_DROP(cx, jsPrincipals);
return ReportError(cx, LOAD_ERROR_BADCHARSET);
}
*scriptp =
JS_CompileUCScriptForPrincipals(cx, target_obj, jsPrincipals,
JS_CompileUCScriptForPrincipals(cx, target_obj, nsJSPrincipals::get(principal),
reinterpret_cast<const jschar*>(script.get()),
script.Length(), uriStr, 1);
} else {
*scriptp = JS_CompileScriptForPrincipals(cx, target_obj, jsPrincipals, buf.get(),
len, uriStr, 1);
*scriptp = JS_CompileScriptForPrincipals(cx, target_obj, nsJSPrincipals::get(principal),
buf.get(), len, uriStr, 1);
}
JSPRINCIPALS_DROP(cx, jsPrincipals);
/* repent for our evil deeds */
JS_SetErrorReporter(cx, er);
@ -204,7 +193,7 @@ mozJSSubScriptLoader::LoadSubScript(const nsAString& url,
__LINE__, NS_LossyConvertUTF16toASCII(url).get());
#endif
/* set mJSPrincipals if it's not here already */
/* set the system principal if it's not here already */
if (!mSystemPrincipal) {
nsCOMPtr<nsIScriptSecurityManager> secman =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);

View File

@ -81,6 +81,7 @@
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsIXPCSecurityManager.h"
#include "nsJSPrincipals.h"
#include "xpcpublic.h"
#ifdef XP_MACOSX
#include "xpcshellMacUtils.h"
@ -1739,11 +1740,13 @@ GetCurrentWorkingDirectory(nsAString& workingDirectory)
}
static JSPrincipals *
FindObjectPrincipals(JSContext *cx, JSObject *obj)
FindObjectPrincipals(JSObject *obj)
{
return gJSPrincipals;
}
static JSSecurityCallbacks shellSecurityCallbacks;
int
main(int argc, char **argv, char **envp)
{
@ -1905,10 +1908,8 @@ main(int argc, char **argv, char **envp)
fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
} else {
// fetch the JS principals and stick in a global
rv = systemprincipal->GetJSPrincipals(cx, &gJSPrincipals);
if (NS_FAILED(rv)) {
fprintf(gErrFile, "+++ Failed to obtain JS principals from SystemPrincipal.\n");
}
gJSPrincipals = nsJSPrincipals::get(systemprincipal);
JS_HoldPrincipals(gJSPrincipals);
secman->SetSystemPrincipal(systemprincipal);
}
} else {
@ -1916,10 +1917,11 @@ main(int argc, char **argv, char **envp)
}
}
JSSecurityCallbacks *cb = JS_GetRuntimeSecurityCallbacks(rt);
NS_ASSERTION(cb, "We are assuming that nsScriptSecurityManager::Init() has been run");
NS_ASSERTION(!cb->findObjectPrincipals, "Your pigeon is in my hole!");
cb->findObjectPrincipals = FindObjectPrincipals;
const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(rt);
NS_ASSERTION(scb, "We are assuming that nsScriptSecurityManager::Init() has been run");
shellSecurityCallbacks = *scb;
shellSecurityCallbacks.findObjectPrincipals = FindObjectPrincipals;
JS_SetSecurityCallbacks(rt, &shellSecurityCallbacks);
#ifdef TEST_TranslateThis
nsCOMPtr<nsIXPCFunctionThisTranslator>
@ -2009,7 +2011,7 @@ main(int argc, char **argv, char **envp)
xpc->WrapJS(cx, glob, NS_GET_IID(nsIJSContextStack),
(void**) getter_AddRefs(bogus));
#endif
JSPRINCIPALS_DROP(cx, gJSPrincipals);
JS_DropPrincipals(rt, gJSPrincipals);
JS_ClearScope(cx, glob);
JS_GC(cx);
JSContext *oldcx;

View File

@ -3437,14 +3437,18 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
NS_ASSERTION(sop, "Invalid sandbox passed");
nsCOMPtr<nsIPrincipal> prin = sop->GetPrincipal();
JSPrincipals *jsPrincipals;
if (!prin ||
NS_FAILED(prin->GetJSPrincipals(cx, &jsPrincipals)) ||
!jsPrincipals) {
if (!prin) {
return NS_ERROR_FAILURE;
}
nsCAutoString filenameBuf;
if (!filename) {
// Default to the spec of the principal.
nsJSPrincipals::get(prin)->GetScriptLocation(filenameBuf);
filename = filenameBuf.get();
lineNo = 1;
}
JSObject *callingScope;
{
JSAutoRequest req(cx);
@ -3458,7 +3462,6 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
nsRefPtr<ContextHolder> sandcx = new ContextHolder(cx, sandbox);
if (!sandcx || !sandcx->GetJSContext()) {
JS_ReportError(cx, "Can't prepare context for evalInSandbox");
JSPRINCIPALS_DROP(cx, jsPrincipals);
return NS_ERROR_OUT_OF_MEMORY;
}
@ -3471,24 +3474,15 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
if (!stack->Push(sandcx->GetJSContext())) {
JS_ReportError(cx,
"Unable to initialize XPConnect with the sandbox context");
JSPRINCIPALS_DROP(cx, jsPrincipals);
return NS_ERROR_FAILURE;
}
}
if (!filename) {
// Default the filename to the codebase.
filename = jsPrincipals->codebase;
lineNo = 1;
}
nsresult rv = NS_OK;
{
JSAutoRequest req(sandcx->GetJSContext());
JSAutoEnterCompartment ac;
jsval v;
JSString *str = nsnull;
if (!ac.enter(sandcx->GetJSContext(), sandbox)) {
if (stack)
@ -3496,9 +3490,11 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
return NS_ERROR_FAILURE;
}
jsval v;
JSString *str = nsnull;
JSBool ok =
JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox,
jsPrincipals,
nsJSPrincipals::get(prin),
reinterpret_cast<const jschar *>
(PromiseFlatString(source).get()),
source.Length(), filename, lineNo,
@ -3571,8 +3567,6 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
if (stack)
unused << stack->Pop();
JSPRINCIPALS_DROP(cx, jsPrincipals);
return rv;
}

View File

@ -60,6 +60,8 @@
#include "jsfriendapi.h"
#include "js/MemoryMetrics.h"
#include "nsJSPrincipals.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
@ -1220,72 +1222,43 @@ XPCJSRuntime::~XPCJSRuntime()
XPCPerThreadData::ShutDown();
}
static void*
GetCompartmentNameHelper(JSCompartment *c, bool getAddress)
static void
GetCompartmentName(JSCompartment *c, bool getAddress, nsCString &name)
{
nsCString* name = new nsCString();
if (js::IsAtomsCompartment(c)) {
name->AssignLiteral("atoms");
name.AssignLiteral("atoms");
} else if (JSPrincipals *principals = JS_GetCompartmentPrincipals(c)) {
if (principals->codebase) {
name->Assign(principals->codebase);
nsJSPrincipals::get(principals)->GetScriptLocation(name);
// For system compartments we append the location, if there is one.
// And we append the address if |getAddress| is true, so that
// multiple system compartments (and there can be many) can be
// distinguished.
if (js::IsSystemCompartment(c)) {
xpc::CompartmentPrivate *compartmentPrivate =
static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(c));
if (compartmentPrivate &&
!compartmentPrivate->location.IsEmpty()) {
name->AppendLiteral(", ");
name->Append(compartmentPrivate->location);
}
if (getAddress) {
// ample; 64-bit address max is 18 chars
static const int maxLength = 31;
nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
name->Append(address);
}
// For system compartments we append the location, if there is one.
// And we append the address if |getAddress| is true, so that
// multiple system compartments (and there can be many) can be
// distinguished.
if (js::IsSystemCompartment(c)) {
xpc::CompartmentPrivate *compartmentPrivate =
static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(c));
if (compartmentPrivate && !compartmentPrivate->location.IsEmpty()) {
name.AppendLiteral(", ");
name.Append(compartmentPrivate->location);
}
if (getAddress) {
// ample; 64-bit address max is 18 chars
const int maxLength = 31;
nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
name.Append(address);
}
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
name->ReplaceChar('/', '\\');
} else {
name->AssignLiteral("null-codebase");
}
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
name.ReplaceChar('/', '\\');
} else {
name->AssignLiteral("null-principal");
name.AssignLiteral("null-principal");
}
return name;
}
static void*
GetCompartmentNameAndAddress(JSRuntime *rt, JSCompartment *c)
{
return GetCompartmentNameHelper(c, /* get address = */true);
}
namespace xpc {
void*
GetCompartmentName(JSRuntime *rt, JSCompartment *c)
{
return GetCompartmentNameHelper(c, /* get address = */false);
}
void
DestroyCompartmentName(void *string)
{
delete static_cast<nsCString*>(string);
}
} // namespace xpc
// We have per-compartment GC heap totals, so we can't put the total GC heap
// size in the explicit allocations tree. But it's a useful figure, so put it
// in the "others" list.
@ -1404,9 +1377,12 @@ inline const nsCString
MakePath(const nsACString &pathPrefix, const JS::CompartmentStats &cStats,
const char (&reporterName)[N])
{
return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
*static_cast<nsCString*>(cStats.name) +
NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName);
const char *name = static_cast<char *>(cStats.extra);
if (!name)
name = "error while initializing compartment name";
return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
nsDependentCString(name) + NS_LITERAL_CSTRING(")/") +
nsDependentCString(reporterName);
}
namespace mozilla {
@ -1694,18 +1670,15 @@ class JSCompartmentsMultiReporter : public nsIMemoryMultiReporter
static void CompartmentCallback(JSRuntime *rt, void* data, JSCompartment *c)
{
// silently ignore OOM errors
Paths *paths = static_cast<Paths *>(data);
nsCString *name =
static_cast<nsCString *>(xpc::GetCompartmentName(rt, c));
nsCString path;
if (js::IsSystemCompartment(c))
path = NS_LITERAL_CSTRING("compartments/system/") + *name;
else
path = NS_LITERAL_CSTRING("compartments/user/") + *name;
if (!paths->append(path))
return; // silent failure, but it's very unlikely
xpc::DestroyCompartmentName(name);
GetCompartmentName(c, /* getAddress = */ false, path);
path.Insert(js::IsSystemCompartment(c)
? NS_LITERAL_CSTRING("compartments/system/")
: NS_LITERAL_CSTRING("compartments/user/"),
0);
paths->append(path);
}
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *cb,
@ -1745,6 +1718,23 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(JSCompartmentsMultiReporter
, nsIMemoryMultiReporter
)
struct XPCJSRuntimeStats : public JS::RuntimeStats {
XPCJSRuntimeStats()
: JS::RuntimeStats(JsMallocSizeOf) { }
~XPCJSRuntimeStats() {
for (size_t i = 0; i != compartmentStatsVector.length(); ++i)
free(compartmentStatsVector[i].extra);
}
virtual void initExtraCompartmentStats(JSCompartment *c,
JS::CompartmentStats *cstats) MOZ_OVERRIDE {
nsCAutoString name;
GetCompartmentName(c, /* getAddress = */ true, name);
cstats->extra = strdup(name.get());
}
};
class JSMemoryMultiReporter : public nsIMemoryMultiReporter
{
public:
@ -1766,8 +1756,7 @@ public:
// the callback. Separating these steps is important because the
// callback may be a JS function, and executing JS while getting these
// stats seems like a bad idea.
JS::RuntimeStats rtStats(JsMallocSizeOf, GetCompartmentNameAndAddress,
xpc::DestroyCompartmentName);
XPCJSRuntimeStats rtStats;
if (!JS::CollectRuntimeStats(xpcrt->GetJSRuntime(), &rtStats))
return NS_ERROR_FAILURE;

View File

@ -1145,12 +1145,8 @@ CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
// 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);
JSObject *tempGlobal =
JS_NewCompartmentAndGlobalObject(cx, clasp, nsJSPrincipals::get(principal));
if (!tempGlobal)
return false;

View File

@ -222,9 +222,6 @@ bool Base64Decode(JSContext *cx, JS::Value val, JS::Value *out);
bool StringToJsval(JSContext *cx, nsAString &str, JS::Value *rval);
bool NonVoidStringToJsval(JSContext *cx, nsAString &str, JS::Value *rval);
void *GetCompartmentName(JSRuntime *rt, JSCompartment *c);
void DestroyCompartmentName(void *string);
#ifdef DEBUG
void DumpJSHeap(FILE* file);
#endif

View File

@ -61,8 +61,7 @@ namespace xpc {
nsIPrincipal *
GetCompartmentPrincipal(JSCompartment *compartment)
{
JSPrincipals *prin = JS_GetCompartmentPrincipals(compartment);
return prin ? static_cast<nsJSPrincipals *>(prin)->nsIPrincipalPtr : nsnull;
return nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment));
}
bool

View File

@ -2164,7 +2164,6 @@ NS_IMETHODIMP
nsCryptoRunnable::Run()
{
nsNSSShutDownPreventionLock locker;
JSPrincipals *principals;
JSContext *cx = m_args->m_cx;
JSAutoRequest ar(cx);
@ -2174,29 +2173,20 @@ nsCryptoRunnable::Run()
return NS_ERROR_FAILURE;
}
nsresult rv = m_args->m_principals->GetJSPrincipals(cx, &principals);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
// make sure the right context is on the stack. must not return w/out popping
nsCOMPtr<nsIJSContextStack> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
if (!stack || NS_FAILED(stack->Push(cx))) {
JSPRINCIPALS_DROP(cx, principals);
return NS_ERROR_FAILURE;
}
jsval retval;
if (JS_EvaluateScriptForPrincipals(cx, m_args->m_scope, principals,
m_args->m_jsCallback,
strlen(m_args->m_jsCallback),
nsnull, 0,
&retval) != JS_TRUE) {
rv = NS_ERROR_FAILURE;
}
JSBool ok =
JS_EvaluateScriptForPrincipals(cx, m_args->m_scope,
nsJSPrincipals::get(m_args->m_principals),
m_args->m_jsCallback,
strlen(m_args->m_jsCallback),
nsnull, 0, nsnull);
stack->Pop(nsnull);
JSPRINCIPALS_DROP(cx, principals);
return rv;
return ok ? NS_OK : NS_ERROR_FAILURE;
}
//Quick helper function to check if a newly issued cert