diff --git a/caps/idl/nsIPrincipal.idl b/caps/idl/nsIPrincipal.idl index 3a09ca8db51..cfc2bac4dfa 100644 --- a/caps/idl/nsIPrincipal.idl +++ b/caps/idl/nsIPrincipal.idl @@ -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. */ diff --git a/caps/include/nsJSPrincipals.h b/caps/include/nsJSPrincipals.h index 782ac029294..f983532cecb 100644 --- a/caps/include/nsJSPrincipals.h +++ b/caps/include/nsJSPrincipals.h @@ -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(principals); + MOZ_ASSERT_IF(self, self->debugToken == DEBUG_TOKEN); + return self; + } + + static nsJSPrincipals* get(nsIPrincipal *principal) { + nsJSPrincipals *self = static_cast(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__ */ diff --git a/caps/include/nsNullPrincipal.h b/caps/include/nsNullPrincipal.h index e342d287bb7..a2cbe139b0e 100644 --- a/caps/include/nsNullPrincipal.h +++ b/caps/include/nsNullPrincipal.h @@ -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 mURI; }; diff --git a/caps/include/nsPrincipal.h b/caps/include/nsPrincipal.h index 8f78db43ef6..1542dc6ba7d 100644 --- a/caps/include/nsPrincipal.h +++ b/caps/include/nsPrincipal.h @@ -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 > mAnnotations; nsHashtable* mCapabilities; nsCString mPrefName; diff --git a/caps/include/nsScriptSecurityManager.h b/caps/include/nsScriptSecurityManager.h index ca0a9fb7079..94e5e469a15 100644 --- a/caps/include/nsScriptSecurityManager.h +++ b/caps/include/nsScriptSecurityManager.h @@ -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); diff --git a/caps/include/nsSystemPrincipal.h b/caps/include/nsSystemPrincipal.h index d9154a6c4b1..25eaee25427 100644 --- a/caps/include/nsSystemPrincipal.h +++ b/caps/include/nsSystemPrincipal.h @@ -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 }; diff --git a/caps/src/nsJSPrincipals.cpp b/caps/src/nsJSPrincipals.cpp index f86f0d38a33..5907b35ffea 100644 --- a/caps/src/nsJSPrincipals.cpp +++ b/caps/src/nsJSPrincipals.cpp @@ -50,46 +50,44 @@ #include "nsMemory.h" #include "nsStringBuffer.h" -static JSBool -nsJSPrincipalsSubsume(JSPrincipals *jsprin, JSPrincipals *other) -{ - nsJSPrincipals *nsjsprin = static_cast(jsprin); - nsJSPrincipals *nsother = static_cast(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(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(*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 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(buf->Data()); + if (debugToken == nsJSPrincipals::DEBUG_TOKEN) { + static_cast(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(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 diff --git a/caps/src/nsNullPrincipal.cpp b/caps/src/nsNullPrincipal.cpp index 8851652d71c..8f69ade01b5 100644 --- a/caps/src/nsNullPrincipal.cpp +++ b/caps/src/nsNullPrincipal.cpp @@ -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) { diff --git a/caps/src/nsPrincipal.cpp b/caps/src/nsPrincipal.cpp index 97005d838ad..e7b0897005e 100644 --- a/caps/src/nsPrincipal.cpp +++ b/caps/src/nsPrincipal.cpp @@ -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; diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index bf2b8424a49..169edef4f24 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -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(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 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)) { diff --git a/caps/src/nsSystemPrincipal.cpp b/caps/src/nsSystemPrincipal.cpp index c223d07cfb6..2b3f5b499bc 100644 --- a/caps/src/nsSystemPrincipal.cpp +++ b/caps/src/nsSystemPrincipal.cpp @@ -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() { } diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 179d9af871e..7cc0d44a874 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -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(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; diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index e867b87b83f..94b8f64bf73 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -518,11 +518,10 @@ NS_ScriptErrorReporter(JSContext *cx, innerWindowID = innerWin->WindowID(); } } - JSPrincipals *prin = report->originPrincipals; - nsIPrincipal *principal = - prin ? static_cast(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 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 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(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 principal = aPrincipal; + if (!aPrincipal) { nsCOMPtr 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 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(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(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(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 principal; if (global) { // XXXbe why the two-step QI? speed up via a new GetGlobalObjectData func? nsCOMPtr 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(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 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); } diff --git a/dom/workers/Principal.cpp b/dom/workers/Principal.cpp index 8427db586b6..678092b32f4 100644 --- a/dom/workers/Principal.cpp +++ b/dom/workers/Principal.cpp @@ -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(gPrincipalCodebase), - 1, PrincipalDestroy, PrincipalSubsume + 1 +#ifdef DEBUG + , kJSPrincipalsDebugToken +#endif }; } // anonymous namespace -BEGIN_WORKERS_NAMESPACE - JSPrincipals* GetWorkerPrincipal() { diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 059b05cb79f..1881f22079a 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -157,6 +157,22 @@ SwapToISupportsArray(SmartPtr& 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(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; diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h index 52944c1ee94..4451c2c8473 100644 --- a/dom/workers/Workers.h +++ b/dom/workers/Workers.h @@ -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__ */ diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 4a5f56e7988..c985744f7d8 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -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 { diff --git a/js/public/MemoryMetrics.h b/js/public/MemoryMetrics.h index c79f8b9454e..513db5b5e26 100644 --- a/js/public/MemoryMetrics.h +++ b/js/public/MemoryMetrics.h @@ -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 diff --git a/js/src/MemoryMetrics.cpp b/js/src/MemoryMetrics.cpp index bd96b7f5dcc..39b4e011163 100644 --- a/js/src/MemoryMetrics.cpp +++ b/js/src/MemoryMetrics.cpp @@ -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. diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 29465f3258f..e40b0023be8 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -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 * diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index 65cdc01ad95..097f8a8a2eb 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -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. */ diff --git a/js/src/jsapi-tests/testChromeBuffer.cpp b/js/src/jsapi-tests/testChromeBuffer.cpp index fb72c15a4e3..49a60cc18ee 100644 --- a/js/src/jsapi-tests/testChromeBuffer.cpp +++ b/js/src/jsapi-tests/testChromeBuffer.cpp @@ -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, diff --git a/js/src/jsapi-tests/testCloneScript.cpp b/js/src/jsapi-tests/testCloneScript.cpp index 13da8a0a56f..f246348a410 100644 --- a/js/src/jsapi-tests/testCloneScript.cpp +++ b/js/src/jsapi-tests/testCloneScript.cpp @@ -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(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(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; diff --git a/js/src/jsapi-tests/testOriginPrincipals.cpp b/js/src/jsapi-tests/testOriginPrincipals.cpp index ae448e5ab8e..8ff3fe4ae46 100644 --- a/js/src/jsapi-tests/testOriginPrincipals.cpp +++ b/js/src/jsapi-tests/testOriginPrincipals.cpp @@ -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 diff --git a/js/src/jsapi-tests/testXDR.cpp b/js/src/jsapi-tests/testXDR.cpp index c20b8378565..8a23f9b3711 100644 --- a/js/src/jsapi-tests/testXDR.cpp +++ b/js/src/jsapi-tests/testXDR.cpp @@ -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("foo.bar"), 1, NULL, SubsumePrincipals }, - { const_cast("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) { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 61ae14ce681..a214fd41fd0 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -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(&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) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 536e6aebd7d..e23ac859a10 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -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); + /************************************************************************/ /* diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 6e900691ab8..6711f473edf 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -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)), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index cb8e4cb3b72..3434c394e32 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -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; diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index d05144b3807..3c83f78e55d 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -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 frames(cx); Vector 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); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 8ad28fd7b6f..32e58abb2bb 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -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); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index f1eef386499..e7385d1277e 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -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); } diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index a9c8aa4c195..4f62733e014 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -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; } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index fd4fa7036c2..2440f3656a3 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -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(); diff --git a/js/src/jsxdrapi.cpp b/js/src/jsxdrapi.cpp index cfddb60323e..29b5572251d 100644 --- a/js/src/jsxdrapi.cpp +++ b/js/src/jsxdrapi.cpp @@ -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; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 77e6732a4f2..7e5edcc0227 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -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); diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index fa0946724ee..2b3201e72e0 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -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(); } diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 85eb682d27a..1cdd03dd854 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -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 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 diff --git a/js/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/xpconnect/loader/mozJSSubScriptLoader.cpp index 2eacc2fd992..10fcb9773e8 100644 --- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -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 chan; nsCOMPtr 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(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 secman = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 82a198cf5b9..4ec492f7593 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -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 @@ -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; diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 66c285f35cb..a2a110270a4 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3437,14 +3437,18 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, NS_ASSERTION(sop, "Invalid sandbox passed"); nsCOMPtr 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 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 (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; } diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 1ef4c20c3a0..1ea2a130b40 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -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(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(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(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(cStats.name) + - NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName); + const char *name = static_cast(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(data); - nsCString *name = - static_cast(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; diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 138f0467283..2912907805c 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -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 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; diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 9191ca0f68a..2e72278785a 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -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 diff --git a/js/xpconnect/wrappers/AccessCheck.cpp b/js/xpconnect/wrappers/AccessCheck.cpp index 6f0364572cd..9e17cf49a8a 100644 --- a/js/xpconnect/wrappers/AccessCheck.cpp +++ b/js/xpconnect/wrappers/AccessCheck.cpp @@ -61,8 +61,7 @@ namespace xpc { nsIPrincipal * GetCompartmentPrincipal(JSCompartment *compartment) { - JSPrincipals *prin = JS_GetCompartmentPrincipals(compartment); - return prin ? static_cast(prin)->nsIPrincipalPtr : nsnull; + return nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment)); } bool diff --git a/security/manager/ssl/src/nsCrypto.cpp b/security/manager/ssl/src/nsCrypto.cpp index 1f532dc77f9..3a5a7898864 100644 --- a/security/manager/ssl/src/nsCrypto.cpp +++ b/security/manager/ssl/src/nsCrypto.cpp @@ -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 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