--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -47,17 +47,17 @@ struct JSPrincipals;
%}
interface nsIURI;
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
{
/**
* Values of capabilities for each principal. Order is
* significant: if an operation is performed on a set
* of capabilities, the minimum is computed.
*/
const short ENABLE_DENIED = 1;
@@ -92,22 +92,16 @@ interface nsIPrincipal : nsISerializable
boolean equalsIgnoringDomain(in nsIPrincipal other);
/**
* Returns a hash value for the principal.
*/
[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.
*/
// XXXcaa should this be here? The script security manager is the only
// thing that should care about this. Wouldn't storing this data in one
// of the hashtables in nsScriptSecurityManager be better?
// XXXbz why is this writable? Who should have write access to this? What
// happens if this principal is in our hashtable and we pass it out of the
// security manager and someone writes to this field? Especially if they
--- a/caps/include/nsJSPrincipals.h
+++ b/caps/include/nsJSPrincipals.h
@@ -38,19 +38,52 @@
#ifndef nsJSPrincipals_h__
#define nsJSPrincipals_h__
#include "jsapi.h"
#include "nsIPrincipal.h"
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);
+
+ /*
+ * 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;
+ }
- nsIPrincipal *nsIPrincipalPtr; // [WEAK] it owns us.
+ 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__ */
--- a/caps/include/nsNullPrincipal.h
+++ b/caps/include/nsNullPrincipal.h
@@ -54,33 +54,38 @@ class nsIURI;
#define NS_NULLPRINCIPAL_CLASSNAME "nullprincipal"
#define NS_NULLPRINCIPAL_CID \
{ 0xdd156d62, 0xd26f, 0x4441, \
{ 0x9c, 0xdb, 0xe8, 0xf0, 0x91, 0x07, 0xc2, 0x73 } }
#define NS_NULLPRINCIPAL_CONTRACTID "@mozilla.org/nullprincipal;1"
#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
NS_DECL_NSISERIALIZABLE
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;
};
#endif // nsNullPrincipal_h__
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -46,26 +46,26 @@
#include "nsHashtable.h"
#include "nsJSPrincipals.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
class nsIObjectInputStream;
class nsIObjectOutputStream;
-class nsPrincipal : public nsIPrincipal
+class nsPrincipal : public nsJSPrincipals
{
public:
nsPrincipal();
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:
NS_DECL_NSIPRINCIPAL
NS_DECL_NSISERIALIZABLE
// Either Init() or InitFromPersistent() must be called before
@@ -95,18 +95,23 @@ public:
enum AnnotationValue { AnnotationEnabled=1, AnnotationDisabled };
void SetURI(nsIURI *aURI);
nsresult SetCapability(const char *capability, void **annotation,
AnnotationValue value);
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;
static PRInt32 sCapabilitiesOrdinal;
// XXXcaa This is a semi-hack. The best solution here is to keep
// a reference to an interface here, except there is no interface
// that we can use yet.
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -423,16 +423,19 @@ private:
nsScriptSecurityManager();
virtual ~nsScriptSecurityManager();
static JSBool
CheckObjectAccess(JSContext *cx, JSObject *obj,
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);
// Returns null if a principal cannot be found; generally callers
// should error out at that point.
static nsIPrincipal*
doGetObjectPrincipal(JSObject *obj
--- a/caps/include/nsSystemPrincipal.h
+++ b/caps/include/nsSystemPrincipal.h
@@ -45,30 +45,33 @@
#define NS_SYSTEMPRINCIPAL_CLASSNAME "systemprincipal"
#define NS_SYSTEMPRINCIPAL_CID \
{ 0x4a6212db, 0xaccb, 0x11d3, \
{ 0xb7, 0x65, 0x0, 0x60, 0xb0, 0xb6, 0xce, 0xcb }}
#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;
- nsSystemPrincipal();
+#ifdef DEBUG
+ virtual void dumpImpl() MOZ_OVERRIDE;
+#endif
protected:
virtual ~nsSystemPrincipal(void);
- nsJSPrincipals mJSPrincipals;
// XXX Probably unnecessary. See bug 143559.
NS_DECL_OWNINGTHREAD
};
#endif // nsSystemPrincipal_h__
--- a/caps/src/nsJSPrincipals.cpp
+++ b/caps/src/nsJSPrincipals.cpp
@@ -45,56 +45,54 @@
#include "nsCOMPtr.h"
#include "jsapi.h"
#include "jsxdrapi.h"
#include "nsIJSRuntimeService.h"
#include "nsIServiceManager.h"
#include "nsMemory.h"
#include "nsStringBuffer.h"
-static JSBool
-nsJSPrincipalsSubsume(JSPrincipals *jsprin, JSPrincipals *other)
+// for mozilla::dom::workers::kJSPrincipalsDebugToken
+#include "mozilla/dom/workers/Workers.h"
+
+/* static */ JSBool
+nsJSPrincipals::Subsume(JSPrincipals *jsprin, JSPrincipals *other)
{
- nsJSPrincipals *nsjsprin = static_cast<nsJSPrincipals *>(jsprin);
- nsJSPrincipals *nsother = static_cast<nsJSPrincipals *>(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;
if (xdr->mode == JSXDR_ENCODE) {
nsIObjectOutputStream *stream =
reinterpret_cast<nsIObjectOutputStream*>(xdr->userdata);
// Flush xdr'ed data to the underlying object output stream.
@@ -102,22 +100,17 @@ nsTranscodeJSPrincipals(JSXDRState *xdr,
char *data = (char*) ::JS_XDRMemGetData(xdr, &size);
rv = stream->Write32(size);
if (NS_SUCCEEDED(rv)) {
rv = stream->WriteBytes(data, size);
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 {
NS_ASSERTION(JS_XDRMemDataLeft(xdr) == 0, "XDR out of sync?!");
nsIObjectInputStream *stream =
reinterpret_cast<nsIObjectInputStream*>(xdr->userdata);
nsCOMPtr<nsIPrincipal> prin;
@@ -136,89 +129,43 @@ nsTranscodeJSPrincipals(JSXDRState *xdr,
// Any decode-mode JSXDRState whose userdata points to an
// nsIObjectInputStream instance must use nsMemory to Alloc
// and Free its data buffer. Swap the new buffer we just
// read for the old, exhausted data.
olddata = (char*) ::JS_XDRMemGetData(xdr, &oldsize);
nsMemory::Free(olddata);
::JS_XDRMemSetData(xdr, data, size);
- prin->GetJSPrincipals(xdr->cx, jsprinp);
+ *jsprinp = nsJSPrincipals::get(prin);
+ JS_HoldPrincipals(*jsprinp);
}
}
}
}
if (NS_FAILED(rv)) {
::JS_ReportError(xdr->cx, "can't %scode principals (failure code %x)",
(xdr->mode == JSXDR_ENCODE) ? "en" : "de",
(unsigned int) rv);
return JS_FALSE;
}
return JS_TRUE;
}
-nsresult
-nsJSPrincipals::Startup()
-{
- 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!");
+#ifdef DEBUG
- NS_ASSERTION(!callbacks->principalsTranscoder,
- "oops, JS_SetPrincipalsTranscoder wars!");
-
- callbacks->principalsTranscoder = nsTranscodeJSPrincipals;
- return NS_OK;
-}
-
-nsJSPrincipals::nsJSPrincipals()
+// Defined here so one can do principals->dump() in the debugger
+JS_EXPORT_API(void)
+JSPrincipals::dump()
{
- codebase = nsnull;
- refcount = 0;
- destroy = nsDestroyJSPrincipals;
- subsume = nsJSPrincipalsSubsume;
- nsIPrincipalPtr = nsnull;
+ 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 {
+ fprintf(stderr,
+ "!!! JSPrincipals (%p) is not nsJSPrincipals instance - bad token: "
+ "actual=0x%x expected=0x%x\n",
+ this, unsigned(debugToken), unsigned(nsJSPrincipals::DEBUG_TOKEN));
+ }
}
-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());
- } 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();
- }
-}
+#endif
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -64,27 +64,27 @@ NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrinci
nsISerializable)
NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
nsIPrincipal,
nsISerializable)
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;
}
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;
}
return count;
}
@@ -128,19 +128,34 @@ nsNullPrincipal::Init()
if (str.Length() != prefixLen + suffixLen) {
NS_WARNING("Out of memory allocating null-principal URI");
return NS_ERROR_OUT_OF_MEMORY;
}
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
*/
NS_IMETHODIMP
nsNullPrincipal::GetPreferences(char** aPrefName, char** aID,
char** aSubjectName,
char** aGrantedList, char** aDeniedList,
@@ -175,27 +190,16 @@ nsNullPrincipal::EqualsIgnoringDomain(ns
NS_IMETHODIMP
nsNullPrincipal::GetHashValue(PRUint32 *aResult)
{
*aResult = (NS_PTR_TO_INT32(this) >> 2);
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)
{
// We don't actually do security policy caching. And it's not like anyone
// can set a security policy for us anyway.
*aSecurityPolicy = nsnull;
return NS_OK;
}
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -88,28 +88,28 @@ NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal,
nsISerializable)
NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal,
nsIPrincipal,
nsISerializable)
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;
}
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;
}
return count;
}
@@ -142,51 +142,46 @@ nsPrincipal::Init(const nsACString& aCer
NS_ENSURE_STATE(!mInitialized);
NS_ENSURE_ARG(!aCertFingerprint.IsEmpty() || aCodebase); // better have one of these.
mInitialized = true;
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)
{
SetSecurityPolicy(nsnull);
delete mCapabilities;
}
-NS_IMETHODIMP
-nsPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin)
+void
+nsPrincipal::GetScriptLocation(nsACString &aStr)
{
- NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitialized!");
+ if (mCert) {
+ aStr.Assign(mCert->fingerprint);
+ } else {
+ mCodebase->GetSpec(aStr);
+ }
+}
- JSPRINCIPALS_HOLD(cx, &mJSPrincipals);
- *jsprin = &mJSPrincipals;
- return NS_OK;
+#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)
{
*aOrigin = nsnull;
nsCOMPtr<nsIURI> origin;
if (mCodebase) {
@@ -878,19 +873,16 @@ nsPrincipal::InitFromPersistent(const ch
}
NS_TryToSetImmutable(mCodebase);
mCodebaseImmutable = URIIsImmutable(mCodebase);
mTrusted = aTrusted;
}
- rv = mJSPrincipals.Init(this, aToken);
- NS_ENSURE_SUCCESS(rv, rv);
-
//-- Save the preference name
mPrefName = aPrefName;
const char* ordinalBegin = PL_strpbrk(aPrefName, "1234567890");
if (ordinalBegin) {
PRIntn n = atoi(ordinalBegin);
if (sCapabilitiesOrdinal <= n) {
sCapabilitiesOrdinal = n + 1;
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -512,16 +512,23 @@ NS_IMPL_ISUPPORTS4(nsScriptSecurityManag
nsIChannelEventSink,
nsIObserver)
///////////////////////////////////////////////////
// Methods implementing nsIScriptSecurityManager //
///////////////////////////////////////////////////
///////////////// Security Checks /////////////////
+
+/* static */ JSPrincipals *
+nsScriptSecurityManager::ObjectPrincipalFinder(JSObject *aObj)
+{
+ return nsJSPrincipals::get(doGetObjectPrincipal(aObj));
+}
+
JSBool
nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
{
// Get the security manager
nsScriptSecurityManager *ssm =
nsScriptSecurityManager::GetScriptSecurityManager();
NS_ASSERTION(ssm, "Failed to get security manager service");
@@ -532,17 +539,17 @@ nsScriptSecurityManager::ContentSecurity
nsIPrincipal* subjectPrincipal = ssm->GetSubjectPrincipal(cx, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get nsIPrincipal from js context");
if (NS_FAILED(rv))
return JS_FALSE; // Not just absence of principal, but failure.
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;
}
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get CSP from principal.");
@@ -2174,21 +2181,17 @@ nsScriptSecurityManager::GetScriptPrinci
return nsnull;
}
JSPrincipals *jsp = JS_GetScriptPrincipals(cx, script);
if (!jsp) {
*rv = NS_ERROR_FAILURE;
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
nsIPrincipal*
nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
JSObject *obj,
JSStackFrame *fp,
nsresult *rv)
@@ -3325,17 +3328,16 @@ nsScriptSecurityManager::nsScriptSecurit
mPolicyPrefsChanged(true)
{
NS_ASSERTION(sizeof(PRWord) == sizeof(void*),
"PRWord and void* have different lengths on this platform. "
"This may cause a security failure with the SecurityLevel union.");
mPrincipals.Init(31);
}
-
nsresult nsScriptSecurityManager::Init()
{
nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
if (!xpconnect)
return NS_ERROR_FAILURE;
NS_ADDREF(sXPConnect = xpconnect);
NS_ADDREF(sJSContextStack = xpconnect);
@@ -3360,45 +3362,40 @@ nsresult nsScriptSecurityManager::Init()
rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle);
NS_ENSURE_SUCCESS(rv, rv);
// Create our system principal singleton
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
// Currently this is used to control access to function.caller
nsCOMPtr<nsIJSRuntimeService> runtimeService =
do_QueryInterface(sXPConnect, &rv);
NS_ENSURE_SUCCESS(rv, rv);
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!");
-
- JS_SetTrustedPrincipals(sRuntime, jsprin);
+ MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
+ JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
+ JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
+
+ JS_SetTrustedPrincipals(sRuntime, system);
return NS_OK;
}
static nsScriptSecurityManager *gScriptSecMan = nsnull;
jsid nsScriptSecurityManager::sEnabledID = JSID_VOID;
@@ -3412,17 +3409,17 @@ nsScriptSecurityManager::~nsScriptSecuri
delete mCapabilities;
gScriptSecMan = nsnull;
}
void
nsScriptSecurityManager::Shutdown()
{
if (sRuntime) {
- JS_SetRuntimeSecurityCallbacks(sRuntime, NULL);
+ JS_SetSecurityCallbacks(sRuntime, NULL);
JS_SetTrustedPrincipals(sRuntime, NULL);
sRuntime = nsnull;
}
sEnabledID = JSID_VOID;
NS_IF_RELEASE(sIOService);
NS_IF_RELEASE(sXPConnect);
NS_IF_RELEASE(sJSContextStack);
@@ -3440,23 +3437,16 @@ nsScriptSecurityManager::GetScriptSecuri
nsresult rv;
rv = ssManager->Init();
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to initialize nsScriptSecurityManager");
if (NS_FAILED(rv)) {
delete ssManager;
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)) {
NS_WARNING("Failed to install xpconnect security manager!");
delete ssManager;
return nsnull;
}
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -57,42 +57,55 @@ NS_IMPL_QUERY_INTERFACE2_CI(nsSystemPrin
nsISerializable)
NS_IMPL_CI_INTERFACE_GETTER2(nsSystemPrincipal,
nsIPrincipal,
nsISerializable)
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;
}
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;
}
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,
char** aGrantedList, char** aDeniedList,
bool* aIsTrusted)
{
// The system principal should never be streamed out
*aPrefName = nsnull;
@@ -275,26 +288,16 @@ nsSystemPrincipal::GetSecurityPolicy(voi
}
NS_IMETHODIMP
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 //
//////////////////////////////////////////
NS_IMETHODIMP
nsSystemPrincipal::Read(nsIObjectInputStream* aStream)
{
@@ -312,29 +315,11 @@ nsSystemPrincipal::Write(nsIObjectOutput
/////////////////////////////////////////////
// Constructor, Destructor, initialization //
/////////////////////////////////////////////
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()
{
}
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -38,16 +38,17 @@
#include "ContentChild.h"
#include "ContentParent.h"
#include "nsFrameMessageManager.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsJSUtils.h"
+#include "nsJSPrincipals.h"
#include "nsNetUtil.h"
#include "nsScriptLoader.h"
#include "nsIJSContextStack.h"
#include "nsIXULRuntime.h"
#include "nsIScriptError.h"
#include "nsIConsoleService.h"
#include "nsIProtocolHandler.h"
#include "nsIScriptSecurityManager.h"
@@ -806,25 +807,23 @@ nsFrameScriptExecutor::LoadFrameScriptIn
nsContentUtils::ThreadJSContextStack()->Push(mCx);
{
// Need to scope JSAutoRequest to happen after Push but before Pop,
// at least for now. See bug 584673.
JSAutoRequest ar(mCx);
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);
JS_SetOptions(mCx, oldopts);
if (script) {
nsCAutoString scheme;
uri->GetScheme(scheme);
@@ -834,18 +833,16 @@ nsFrameScriptExecutor::LoadFrameScriptIn
new nsFrameJSScriptExecutorHolder(script);
// Root the object also for caching.
JS_AddNamedScriptRoot(mCx, &(holder->mScript),
"Cached message manager script");
sCachedScripts->Put(aURL, holder);
}
(void) JS_ExecuteScript(mCx, global, script, nsnull);
}
- //XXX Argh, JSPrincipals are manually refcounted!
- JSPRINCIPALS_DROP(mCx, jsprin);
}
}
JSContext* unused;
nsContentUtils::ThreadJSContextStack()->Pop(&unused);
}
}
bool
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -513,21 +513,20 @@ NS_ScriptErrorReporter(JSContext *cx,
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
PRUint64 innerWindowID = 0;
if (win) {
nsCOMPtr<nsPIDOMWindow> innerWin = win->GetCurrentInnerWindow();
if (innerWin) {
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,
innerWindowID));
}
}
#ifdef DEBUG
@@ -1213,52 +1212,45 @@ nsJSContext::EvaluateStringWithValue(con
}
return NS_OK;
}
// 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();
if (!global)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
do_QueryInterface(global, &rv);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
principal = objPrincipal->GetPrincipal();
if (!principal)
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;
}
// Push our JSContext on the current thread's context stack so JS called
// from native code via XPConnect uses the right context. Do this whether
// or not the SecurityManager said "ok", in order to simplify control flow
// below where we pop before returning.
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;
}
jsval val;
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
NS_ENSURE_SUCCESS(rv, rv);
@@ -1268,26 +1260,25 @@ nsJSContext::EvaluateStringWithValue(con
// 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);
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, aScopeObject)) {
- JSPRINCIPALS_DROP(mContext, jsprin);
stack->Pop(nsnull);
return NS_ERROR_FAILURE;
}
++mExecuteDepth;
ok = ::JS_EvaluateUCScriptForPrincipalsVersion(mContext,
aScopeObject,
- jsprin,
+ nsJSPrincipals::get(principal),
static_cast<const jschar*>(PromiseFlatString(aScript).get()),
aScript.Length(),
aURL,
aLineNo,
&val,
JSVersion(aVersion));
--mExecuteDepth;
@@ -1296,19 +1287,16 @@ nsJSContext::EvaluateStringWithValue(con
// Tell XPConnect about any pending exceptions. This is needed
// to avoid dropping JS exceptions in case we got here through
// nested calls through XPConnect.
ReportPendingException();
}
}
- // 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) {
*aIsUndefined = JSVAL_IS_VOID(val);
}
*aRetValue = val;
// XXX - nsScriptObjectHolder should be used once this method moves to
@@ -1422,63 +1410,41 @@ nsJSContext::EvaluateString(const nsAStr
if (!aScopeObject) {
aScopeObject = JS_GetGlobalObject(mContext);
}
// 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)
return NS_ERROR_FAILURE;
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;
}
// Push our JSContext on the current thread's context stack so JS called
// from native code via XPConnect uses the right context. Do this whether
// or not the SecurityManager said "ok", in order to simplify control flow
// below where we pop before returning.
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;
}
// The result of evaluation, used only if there were no errors. This need
// not be a GC root currently, provided we run the GC only from the
// operation callback or from ScriptEvaluated.
jsval val = JSVAL_VOID;
jsval* vp = aRetValue ? &val : NULL;
@@ -1493,43 +1459,34 @@ nsJSContext::EvaluateString(const nsAStr
// SecurityManager said "ok", but don't compile if 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);
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));
if (!ok) {
// Tell XPConnect about any pending exceptions. This is needed
// to avoid dropping JS exceptions in case we got here through
// nested calls through XPConnect.
ReportPendingException();
}
}
- // 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);
JSAutoEnterCompartment ac;
if (!ac.enter(mContext, aScopeObject)) {
stack->Pop(nsnull);
}
rv = JSValueToAString(mContext, val, aRetValue, aIsUndefined);
@@ -1568,57 +1525,48 @@ nsJSContext::CompileScript(const PRUnich
nsScriptObjectHolder<JSScript>& aScriptObject)
{
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_ARG_POINTER(aPrincipal);
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);
-
- 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;
- }
+ if (!ok || JSVersion(aVersion) == JSVERSION_UNKNOWN)
+ return NS_OK;
+
+ JSAutoRequest ar(mContext);
+
+ 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
nsJSContext::ExecuteScript(JSScript* aScriptObject,
JSObject* aScopeObject,
nsAString* aRetValue,
bool* aIsUndefined)
{
@@ -1831,46 +1779,43 @@ nsJSContext::CompileFunction(JSObject* a
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
// Don't compile if aVersion is unknown. Since the caller is responsible for
// parsing the version strings, we just check it isn't JSVERSION_UNKNOWN.
if ((JSVersion)aVersion == JSVERSION_UNKNOWN) {
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);
}
}
JSObject *target = aTarget;
JSAutoRequest ar(mContext);
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()),
aBody.Length(),
aURL, aLineNo,
JSVersion(aVersion));
- if (jsprin)
- JSPRINCIPALS_DROP(mContext, jsprin);
if (!fun)
return NS_ERROR_FAILURE;
*aFunctionObject = JS_GetFunctionObject(fun);
return NS_OK;
}
nsresult
@@ -3763,43 +3708,16 @@ SetMemoryGCSliceTimePrefChangedCallback(
{
PRInt32 pref = Preferences::GetInt(aPrefName, -1);
// handle overflow and negative pref values
if (pref > 0 && pref < 100000)
JS_SetGCParameter(nsJSRuntime::sRuntime, JSGC_SLICE_TIME_BUDGET, pref);
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,
uint32_t tag,
uint32_t data,
void* closure)
{
// We don't currently support any extensions to structured cloning.
@@ -3848,21 +3766,16 @@ nsJSRuntime::Init()
rv = sRuntimeService->GetRuntime(&sRuntime);
NS_ENSURE_SUCCESS(rv, rv);
// Let's make sure that our main thread is the same as the xpcom main thread.
NS_ASSERTION(NS_IsMainThread(), "bad");
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,
NS_DOMWriteStructuredClone,
NS_DOMStructuredCloneError
};
JS_SetStructuredCloneCallbacks(sRuntime, &cloneCallbacks);
@@ -3950,24 +3863,16 @@ nsJSRuntime::Shutdown()
nsJSContext::KillCCTimer();
NS_IF_RELEASE(gNameSpaceManager);
if (!sContextCount) {
// 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);
}
sDidShutdown = true;
}
// Script object mananagement - note duplicate implementation
--- a/dom/workers/Principal.cpp
+++ b/dom/workers/Principal.cpp
@@ -35,40 +35,28 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "Principal.h"
#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()
{
return &gPrincipal;
}
END_WORKERS_NAMESPACE
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -152,16 +152,32 @@ SwapToISupportsArray(SmartPtr<T>& aSrc,
nsISupports* rawSupports =
static_cast<typename ISupportsBaseInfo<T>::ISupportsBase*>(raw);
dest->swap(rawSupports);
}
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;
nsCString mAddressString;
nsCString mPathPrefix;
public:
NS_DECL_ISUPPORTS
@@ -235,18 +251,17 @@ public:
}
NS_IMETHOD
CollectReports(nsIMemoryMultiReporterCallback* aCallback,
nsISupports* aClosure)
{
AssertIsOnMainThread();
- JS::RuntimeStats rtStats(JsWorkerMallocSizeOf, xpc::GetCompartmentName,
- xpc::DestroyCompartmentName);
+ WorkerJSRuntimeStats rtStats;
nsresult rv = CollectForRuntime(/* isQuick = */false, &rtStats);
if (NS_FAILED(rv)) {
return rv;
}
// Always report, even if we're disabled, so that we at least get an entry
// in about::memory.
rv = ReportJSRuntimeExplicitTreeStats(rtStats, mPathPrefix, aCallback, aClosure);
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -118,11 +118,14 @@ protected:
// Must be acquired *before* the WorkerPrivate's mutex, when they're both held.
mozilla::Mutex mMutex;
WorkerPrivate* mPrivate;
};
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__ */
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -62,16 +62,17 @@
#include "nsIJSRuntimeService.h"
#include "nsIPrincipal.h"
#include "nsIScriptSecurityManager.h"
#include "nsIURI.h"
#include "nsIXPConnect.h"
#include "nsIXPCScriptable.h"
#include "nsJSUtils.h"
+#include "nsJSPrincipals.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "TestShellChild.h"
#include "TestShellParent.h"
#define EXITCODE_RUNTIME_ERROR 3
#define EXITCODE_FILE_NOT_FOUND 4
@@ -1053,17 +1054,17 @@ XPCShellEnvironment::~XPCShellEnvironmen
}
mGlobalHolder.Release();
JS_GC(mCx);
mCxStack = nsnull;
if (mJSPrincipals) {
- JSPRINCIPALS_DROP(mCx, mJSPrincipals);
+ JS_DropPrincipals(JS_GetRuntime(mCx), mJSPrincipals);
}
JSRuntime* rt = gOldContextCallback ? JS_GetRuntime(mCx) : NULL;
JS_EndRequest(mCx);
JS_DestroyContext(mCx);
if (gOldContextCallback) {
@@ -1135,20 +1136,18 @@ XPCShellEnvironment::Init()
nsCOMPtr<nsIScriptSecurityManager> securityManager =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && securityManager) {
rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
if (NS_FAILED(rv)) {
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 {
fprintf(stderr, "+++ Failed to get ScriptSecurityManager service, running without principals");
}
nsCOMPtr<nsIJSContextStack> cxStack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -1,9 +1,12 @@
-/* ***** 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
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
@@ -56,41 +59,23 @@ namespace JS {
struct TypeInferenceSizes
{
size_t scripts;
size_t objects;
size_t tables;
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;
size_t gcHeapObjectsNonFunction;
size_t gcHeapObjectsFunction;
size_t gcHeapStrings;
size_t gcHeapShapesTree;
@@ -114,18 +99,17 @@ struct CompartmentStats
size_t mjitCode;
size_t mjitData;
#endif
TypeInferenceSizes typeInferenceSizes;
};
struct RuntimeStats
{
- RuntimeStats(JSMallocSizeOfFun mallocSizeOf, GetNameCallback getNameCb,
- DestroyNameCallback destroyNameCb)
+ RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
: runtimeObject(0)
, runtimeAtomsTable(0)
, runtimeContexts(0)
, runtimeNormal(0)
, runtimeTemporary(0)
, runtimeRegexpCode(0)
, runtimeStackCommitted(0)
, runtimeGCMarker(0)
@@ -144,18 +128,16 @@ struct RuntimeStats
#ifdef JS_METHODJIT
, totalMjit(0)
#endif
, totalTypeInference(0)
, totalAnalysisTemp(0)
, compartmentStatsVector()
, currCompartmentStats(NULL)
, mallocSizeOf(mallocSizeOf)
- , getNameCb(getNameCb)
- , destroyNameCb(destroyNameCb)
{}
size_t runtimeObject;
size_t runtimeAtomsTable;
size_t runtimeContexts;
size_t runtimeNormal;
size_t runtimeTemporary;
size_t runtimeRegexpCode;
@@ -178,18 +160,18 @@ struct RuntimeStats
#endif
size_t totalTypeInference;
size_t totalAnalysisTemp;
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
CompartmentStats *currCompartmentStats;
JSMallocSizeOfFun mallocSizeOf;
- GetNameCallback getNameCb;
- DestroyNameCallback destroyNameCb;
+
+ virtual void initExtraCompartmentStats(JSCompartment *c, CompartmentStats *cstats) = 0;
};
#ifdef JS_THREADSAFE
extern JS_PUBLIC_API(bool)
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats);
extern JS_PUBLIC_API(int64_t)
--- a/js/src/MemoryMetrics.cpp
+++ b/js/src/MemoryMetrics.cpp
@@ -58,17 +58,17 @@ static void
StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
{
// Append a new CompartmentStats to the vector.
RuntimeStats *rtStats = static_cast<RuntimeStats *>(data);
// 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.
#ifdef JS_METHODJIT
cStats.mjitCode = compartment->sizeOfMjitCode();
#endif
compartment->sizeOfTypeInferenceData(&cStats.typeInferenceSizes, rtStats->mallocSizeOf);
cStats.shapesCompartmentTables = compartment->sizeOfShapeTable(rtStats->mallocSizeOf);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -151,33 +151,33 @@ Parser::init(const jschar *base, size_t
}
return true;
}
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--;
}
void
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 *
Parser::newObjectBox(JSObject *obj)
{
/*
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
* on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -153,17 +153,17 @@ js::IsIdentifier(JSLinearString *str)
#endif
/* Initialize members that aren't initialized in |init|. */
TokenStream::TokenStream(JSContext *cx, JSPrincipals *prin, JSPrincipals *originPrin)
: tokens(), cursor(), lookahead(), flags(), listenerTSData(), tokenbuf(cx),
cx(cx), originPrincipals(JSScript::normalizeOriginPrincipals(prin, originPrin))
{
if (originPrincipals)
- JSPRINCIPALS_HOLD(cx, originPrincipals);
+ JS_HoldPrincipals(originPrincipals);
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
bool
TokenStream::init(const jschar *base, size_t length, const char *fn, unsigned ln, JSVersion v)
@@ -243,17 +243,17 @@ TokenStream::init(const jschar *base, si
TokenStream::~TokenStream()
{
if (flags & TSF_OWNFILENAME)
cx->free_((void *) filename);
if (sourceMap)
cx->free_(sourceMap);
if (originPrincipals)
- JSPRINCIPALS_DROP(cx, originPrincipals);
+ JS_DropPrincipals(cx->runtime, originPrincipals);
}
/* Use the fastest available getc. */
#if defined(HAVE_GETC_UNLOCKED)
# define fast_getc getc_unlocked
#elif defined(HAVE__GETC_NOLOCK)
# define fast_getc _getc_nolock
#else
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -1,23 +1,14 @@
#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,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_StrictPropertyStub,
JS_EnumerateStub,
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -47,72 +47,56 @@ BEGIN_TEST(test_cloneScript)
CHECK(JS_CloneFunctionObject(cx, obj, B));
}
return true;
}
END_TEST(test_cloneScript)
void
-DestroyPrincipals(JSContext *cx, JSPrincipals *principals)
+DestroyPrincipals(JSPrincipals *principals)
{
delete 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;
CHECK(A = createGlobal(principalsA));
CHECK(B = createGlobal(principalsB));
const char *argnames[] = { "arg" };
const char *source = "return function() { return arg; }";
--- a/js/src/jsapi-tests/testOriginPrincipals.cpp
+++ b/js/src/jsapi-tests/testOriginPrincipals.cpp
@@ -1,53 +1,42 @@
#include "tests.h"
#include "jsdbgapi.h"
#include "jsobjinlines.h"
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
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
* JS_EvaluateUCScriptForPrincipalsVersionOrigin. This does not expose the
* compiled script, so we can only test nested scripts.
*/
CHECK(testOuter("function f() {return 1}; f;"));
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -67,34 +67,22 @@ FreezeThaw(JSContext *cx, JSScript *scri
}
static JSObject *
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)
{
uint32_t index;
if (xdr->mode == JSXDR_ENCODE) {
JSPrincipals *p = *principalsp;
for (index = 0; ; ++index) {
if (index == mozilla::ArrayLength(testPrincipals))
return false;
@@ -105,32 +93,33 @@ TranscodePrincipals(JSXDRState *xdr, JSP
if (!JS_XDRUint32(xdr, &index))
return false;
if (xdr->mode == JSXDR_DECODE) {
if (index >= mozilla::ArrayLength(testPrincipals))
return false;
*principalsp = &testPrincipals[index];
- JSPRINCIPALS_HOLD(xdr->cx, *principalsp);
+ JS_HoldPrincipals(*principalsp);
}
return true;
}
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) {
script = createScriptViaXDR(NULL, NULL, i);
CHECK(script);
CHECK(!JS_GetScriptPrincipals(cx, script));
CHECK(!JS_GetScriptOriginPrincipals(cx, script));
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -691,16 +691,18 @@ JS_IsBuiltinFunctionConstructor(JSFuncti
/*
* Has a new runtime ever been created? This flag is used to detect unsafe
* changes to js_CStringsAreUTF8 after a runtime has been created, and to
* control things that should happen only once across all runtimes.
*/
static JSBool js_NewRuntimeWasCalled = JS_FALSE;
+static const JSSecurityCallbacks NullSecurityCallbacks = { };
+
JSRuntime::JSRuntime()
: atomsCompartment(NULL),
#ifdef JS_THREADSAFE
ownerThread_(NULL),
#endif
tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
execAlloc_(NULL),
bumpAlloc_(NULL),
@@ -773,17 +775,18 @@ JSRuntime::JSRuntime()
profilingScripts(false),
hadOutOfMemory(false),
data(NULL),
#ifdef JS_THREADSAFE
gcLock(NULL),
gcHelperThread(thisFromCtor()),
#endif
debuggerMutations(0),
- securityCallbacks(NULL),
+ securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
+ destroyPrincipals(NULL),
structuredCloneCallbacks(NULL),
telemetryCallback(NULL),
propertyRemovals(0),
thousandsSeparator(0),
decimalSeparator(0),
numGrouping(0),
anynameObject(NULL),
functionNamespaceObject(NULL),
@@ -4446,73 +4449,57 @@ JS_CheckAccess(JSContext *cx, JSObject *
jsval *vp, unsigned *attrsp)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
return CheckAccess(cx, obj, id, mode, vp, attrsp);
}
-#ifdef JS_THREADSAFE
-JS_PUBLIC_API(int)
-JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
-{
- return JS_ATOMIC_INCREMENT(&principals->refcount);
-}
-
-JS_PUBLIC_API(int)
-JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
+JS_PUBLIC_API(void)
+JS_HoldPrincipals(JSPrincipals *principals)
+{
+ JS_ATOMIC_INCREMENT(&principals->refcount);
+}
+
+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;
-}
-
-JS_PUBLIC_API(JSSecurityCallbacks *)
-JS_GetRuntimeSecurityCallbacks(JSRuntime *rt)
-{
- return rt->securityCallbacks;
-}
-
-JS_PUBLIC_API(JSSecurityCallbacks *)
-JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks)
-{
- 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;
+ rt->destroyPrincipals(principals);
+}
+
+JS_PUBLIC_API(void)
+JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *scb)
+{
+ JS_ASSERT(scb != &NullSecurityCallbacks);
+ rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
+}
+
+JS_PUBLIC_API(const JSSecurityCallbacks *)
+JS_GetSecurityCallbacks(JSRuntime *rt)
+{
+ return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : NULL;
}
JS_PUBLIC_API(void)
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)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
JSAtom *atom;
AssertNoGC(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1515,16 +1515,22 @@ typedef JSBool
typedef JSBool
(* JSLocaleToUnicode)(JSContext *cx, const char *src, jsval *rval);
/*
* 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,
* in which case implementations must return a held (via JSPRINCIPALS_HOLD),
* non-null *principalsp out parameter. Return true on success, false on any
* error, which the implementation must have reported.
*/
typedef JSBool
@@ -1534,17 +1540,17 @@ typedef JSBool
* Return a weak reference to the principals associated with obj, possibly via
* the immutable parent chain leading from obj to a top-level container (e.g.,
* a window object in the DOM level 0). If there are no principals associated
* with obj, return null. Therefore null does not mean an error was reported;
* in no event should an error be reported or an exception be thrown by this
* 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.
* See js_CheckCSPPermitsJSAction() in jsobj.
*/
typedef JSBool
(* JSCSPEvalChecker)(JSContext *cx);
@@ -4083,78 +4089,82 @@ extern JS_PUBLIC_API(void)
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 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
};
-#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)
-#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(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(void)
+JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *callbacks);
+
+extern JS_PUBLIC_API(const JSSecurityCallbacks *)
+JS_GetSecurityCallbacks(JSRuntime *rt);
/*
* Code running with "trusted" principals will be given a deeper stack
* allocation than ordinary scripts. This allows trusted script to run after
* untrusted script has exhausted the stack. This function sets the
* runtime-wide trusted principal.
*
* This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals) since
* there is no available JSContext. Instead, the caller must ensure that the
* given principals stays valid for as long as 'rt' may point to it. If the
* principals would be destroyed before 'rt', JS_SetTrustedPrincipals must be
* called again, passing NULL for 'prin'.
*/
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);
+
/************************************************************************/
/*
* Functions and scripts.
*/
extern JS_PUBLIC_API(JSFunction *)
JS_NewFunction(JSContext *cx, JSNative call, unsigned nargs, unsigned flags,
JSObject *parent, const char *name);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -983,17 +983,16 @@ JSContext::JSContext(JSRuntime *rt)
lastMessage(NULL),
errorReporter(NULL),
operationCallback(NULL),
data(NULL),
data2(NULL),
#ifdef JS_THREADSAFE
outstandingRequests(0),
#endif
- securityCallbacks(NULL),
resolveFlags(0),
rngSeed(0),
iterValue(MagicValue(JS_NO_ITER_VALUE)),
#ifdef JS_METHODJIT
methodJitEnabled(false),
#endif
inferenceEnabled(false),
#ifdef MOZ_TRACE_JSCALLS
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -504,21 +504,18 @@ struct JSRuntime : js::RuntimeFriendFiel
/* These combine to interlock the GC and new requests. */
PRLock *gcLock;
js::GCHelperThread gcHelperThread;
#endif /* JS_THREADSAFE */
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;
/* Call this to accumulate telemetry data. */
JSAccumulateTelemetryDataCallback telemetryCallback;
/*
@@ -1008,19 +1005,16 @@ struct JSContext : js::ContextFriendFiel
* location as holding a relocatable pointer, but have no other effect on
* GC behavior.
*/
js::CheckRoot *checkGCRooters;
#endif
#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;
/* Random number generator state, used by jsmath.cpp. */
int64_t rngSeed;
/* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */
js::Value iterValue;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -299,18 +299,17 @@ SetExnPrivate(JSContext *cx, JSObject *e
static bool
InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
JSString *filename, unsigned lineno, JSErrorReport *report, int exnType)
{
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);
{
SuppressErrorsGuard seg(cx);
for (FrameRegsIter i(cx); !i.done(); ++i) {
/*
* An exception object stores stack values from 'fp' which may be
@@ -438,29 +437,29 @@ exn_trace(JSTracer *trc, JSObject *obj)
/* NB: An error object's private must be set through this function. */
static void
SetExnPrivate(JSContext *cx, JSObject *exnObject, JSExnPrivate *priv)
{
JS_ASSERT(!exnObject->getPrivate());
JS_ASSERT(exnObject->isError());
if (JSErrorReport *report = priv->errorReport) {
if (JSPrincipals *prin = report->originPrincipals)
- JSPRINCIPALS_HOLD(cx, prin);
+ JS_HoldPrincipals(prin);
}
exnObject->setPrivate(priv);
}
static void
exn_finalize(JSContext *cx, JSObject *obj)
{
if (JSExnPrivate *priv = GetExnPrivate(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);
}
}
static JSBool
exn_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2910,17 +2910,17 @@ SweepCompartments(JSContext *cx, JSGCInv
if (!compartment->hold &&
(compartment->arenas.arenaListsAreEmpty() || !rt->hasContexts()))
{
compartment->arenas.checkEmptyFreeLists();
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;
}
*write++ = compartment;
}
rt->compartments.resize(write - rt->compartments.begin());
}
@@ -3900,17 +3900,17 @@ NewCompartment(JSContext *cx, JSPrincipa
JSCompartment *compartment = cx->new_<JSCompartment>(rt);
if (compartment && compartment->init(cx)) {
// Any compartment with the trusted principals -- and there can be
// multiple -- is a system compartment.
compartment->isSystemCompartment = principals && rt->trustedPrincipals() == principals;
if (principals) {
compartment->principals = principals;
- JSPRINCIPALS_HOLD(cx, principals);
+ JS_HoldPrincipals(principals);
}
compartment->setGCLastBytes(8192, 8192, GC_NORMAL);
/*
* Before reporting the OOM condition, |lock| needs to be cleaned up,
* hence the scoping.
*/
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -784,25 +784,25 @@ EvalCacheLookup(JSContext *cx, JSLinearS
* to avoid caching nested evals in functions (thus potentially mismatching
* on strict mode), and we could cache evals in global code if desired.
*/
unsigned count = 0;
JSScript **scriptp = bucket;
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.
*/
JSFunction *fun = script->getCallerFunction();
if (fun == caller->fun()) {
/*
@@ -1158,22 +1158,24 @@ PrincipalsForCompiledCode(const CallRece
#if JS_HAS_OBJ_WATCHPOINT
static JSBool
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;
+ }
}
}
}
}
/* Avoid recursion on (obj, id) already being watched on cx. */
AutoResolving resolving(cx, obj, id, AutoResolving::WATCH);
if (resolving.alreadyStarted())
@@ -5876,20 +5878,17 @@ namespace js {
JSBool
CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
Value *vp, unsigned *attrsp)
{
JSBool writing;
JSObject *pobj;
JSProperty *prop;
- Class *clasp;
const Shape *shape;
- JSSecurityCallbacks *callbacks;
- JSCheckAccessOp check;
while (JS_UNLIKELY(obj->isWith()))
obj = obj->getProto();
writing = (mode & JSACC_WRITE) != 0;
switch (mode & JSACC_TYPEMASK) {
case JSACC_PROTO:
pobj = obj;
@@ -5943,22 +5942,19 @@ CheckAccess(JSContext *cx, JSObject *obj
* We don't want to require all classes to supply a checkAccess hook; we
* need that hook only for certain classes used when precompiling scripts
* and functions ("brutal sharing"). But for general safety of built-in
* magic properties like __proto__, we route all access checks, even for
* classes that stub out checkAccess, through the global checkObjectAccess
* 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);
}
}
JSType
js_TypeOf(JSContext *cx, JSObject *obj)
{
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1113,19 +1113,18 @@ inline bool
JSObject::isCallable()
{
return isFunction() || getClass()->call;
}
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;
}
inline uint32_t
JSObject::slotSpan() const
{
if (inDictionaryMode())
return lastProperty()->base()->slotSpan();
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -698,21 +698,21 @@ XDRScript(JSXDRState *xdr, JSScript **sc
if (xdr->mode == JSXDR_DECODE) {
JS_ASSERT(!script->principals);
JS_ASSERT(!script->originPrincipals);
/* The origin principals must be normalized at this point. */
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);
}
}
if (xdr->mode == JSXDR_DECODE) {
script->lineno = (unsigned)lineno;
script->nslots = uint16_t(nslots);
script->staticLevel = uint16_t(nslots >> 16);
}
@@ -1251,24 +1251,24 @@ JSScript::NewScriptFromEmitter(JSContext
"script");
return NULL;
}
script->nslots = script->nfixed + bce->maxStackDepth;
script->staticLevel = uint16_t(bce->staticLevel);
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();
if (!FinishTakingSrcNotes(cx, bce, script->notes()))
return NULL;
if (bce->ntrynotes != 0)
FinishTakingTryNotes(bce, script->trynotes());
if (bce->objectList.length != 0)
@@ -1457,19 +1457,19 @@ void
JSScript::finalize(JSContext *cx, bool background)
{
CheckScript(NULL);
js_CallDestroyScriptHook(cx, this);
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();
#ifdef JS_METHODJIT
mjit::ReleaseScriptCode(cx, this);
#endif
--- a/js/src/jsxdrapi.cpp
+++ b/js/src/jsxdrapi.cpp
@@ -554,17 +554,17 @@ XDRPrincipals(JSXDRState *xdr)
if (xdr->originPrincipals && xdr->originPrincipals != xdr->principals)
flags |= HAS_ORIGIN;
}
if (!JS_XDRUint8(xdr, &flags))
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,
JSMSG_CANT_DECODE_PRINCIPALS);
return false;
}
} else {
JS_ASSERT(scb);
@@ -576,17 +576,17 @@ XDRPrincipals(JSXDRState *xdr)
return false;
}
if (flags & HAS_ORIGIN) {
if (!scb->principalsTranscoder(xdr, &xdr->originPrincipals))
return false;
} else if (xdr->mode == JSXDR_DECODE && xdr->principals) {
xdr->originPrincipals = xdr->principals;
- JSPRINCIPALS_HOLD(xdr->cx, xdr->principals);
+ JS_HoldPrincipals(xdr->principals);
}
}
return true;
}
namespace {
@@ -594,19 +594,19 @@ struct AutoDropXDRPrincipals {
JSXDRState *const xdr;
AutoDropXDRPrincipals(JSXDRState *xdr)
: xdr(xdr) { }
~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;
}
};
} /* namespace anonymous */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4862,40 +4862,30 @@ MaybeOverrideOutFileFromEnv(const char*
FILE** outFile)
{
const char* outPath = getenv(envVar);
if (!outPath || !*outPath || !(*outFile = fopen(outPath, "w"))) {
*outFile = defaultOut;
}
}
-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;
}
JSSecurityCallbacks securityCallbacks = {
CheckObjectAccess,
NULL,
NULL,
+ NULL,
NULL
};
int
main(int argc, char **argv, char **envp)
{
int stackDummy;
JSRuntime *rt;
@@ -5028,17 +5018,17 @@ main(int argc, char **argv, char **envp)
/* Use the same parameters as the browser in xpcjsruntime.cpp. */
rt = JS_NewRuntime(32L * 1024L * 1024L);
if (!rt)
return 1;
JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff);
JS_SetTrustedPrincipals(rt, &shellTrustedPrincipals);
- JS_SetRuntimeSecurityCallbacks(rt, &securityCallbacks);
+ JS_SetSecurityCallbacks(rt, &securityCallbacks);
JS_SetNativeStackQuota(rt, gMaxStackSize);
if (!InitWatchdog(rt))
return 1;
cx = NewContext(rt);
if (!cx)
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -381,25 +381,22 @@ GlobalObject::clear(JSContext *cx)
#endif
}
bool
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();
}
JSFunction *
GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom *name,
unsigned length, gc::AllocKind kind)
{
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -75,16 +75,17 @@
#include "nsIScriptSecurityManager.h"
#include "nsIURI.h"
#include "nsIFileURL.h"
#include "nsIJARURI.h"
#include "nsNetUtil.h"
#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"
#include "nsIStorageStream.h"
#include "nsIStringStream.h"
#include "prmem.h"
#if defined(XP_WIN)
#include "nsILocalFileWin.h"
@@ -640,49 +641,32 @@ class ANSIFileAutoCloser
public:
explicit ANSIFileAutoCloser(FILE *file) : mFile(file) {}
~ANSIFileAutoCloser() { fclose(mFile); }
private:
FILE *mFile;
};
#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,
JSObject **aGlobal,
char **aLocation,
jsval *exception)
{
nsresult rv;
- JSPrincipals* jsPrincipals = nsnull;
JSCLContextHelper cx(this);
JS_AbortIfWrongThread(JS_GetRuntime(cx));
// 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);
JSCLAutoErrorReporterSetter aers(cx, mozJSLoaderErrorReporter);
nsCOMPtr<nsIXPConnect> xpc =
do_GetService(kXPConnectServiceContractID, &rv);
@@ -832,17 +816,19 @@ mozJSComponentLoader::GlobalForLocation(
char *buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32));
if (!buf) {
NS_WARNING("Failed to map file");
JS_SetOptions(cx, oldopts);
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);
#else /* HAVE_PR_MEMMAP */
/**
* No memmap implementation, so fall back to
@@ -875,17 +861,19 @@ mozJSComponentLoader::GlobalForLocation(
size_t rlen = fread(buf, 1, len, fileHandle);
if (rlen != (PRUint64)len) {
free(buf);
JS_SetOptions(cx, oldopts);
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);
#endif /* HAVE_PR_MEMMAP */
} else {
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
NS_ENSURE_SUCCESS(rv, rv);
@@ -912,17 +900,19 @@ mozJSComponentLoader::GlobalForLocation(
/* read the file in one swoop */
rv = scriptStream->Read(buf, len, &bytesRead);
if (bytesRead != len)
return NS_BASE_STREAM_OSERROR;
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
// exception on this context.
JS_SetOptions(cx, oldopts);
if (!script && exception) {
JS_GetPendingException(cx, exception);
JS_ClearPendingException(cx);
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -56,16 +56,17 @@
#include "nsNetUtil.h"
#include "nsIProtocolHandler.h"
#include "nsIFileURL.h"
#include "nsScriptLoader.h"
#include "jsapi.h"
#include "jsdbgapi.h"
#include "jsfriendapi.h"
+#include "nsJSPrincipals.h"
#include "mozilla/FunctionTimer.h"
#include "mozilla/scache/StartupCache.h"
#include "mozilla/scache/StartupCacheUtils.h"
using namespace mozilla::scache;
/* load() error msgs, XXX localize? */
@@ -106,17 +107,16 @@ ReportError(JSContext *cx, const char *m
nsresult
mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_obj,
const nsAString& charset, const char *uriStr,
nsIIOService *serv, nsIPrincipal *principal,
JSScript **scriptp)
{
nsCOMPtr<nsIChannel> chan;
nsCOMPtr<nsIInputStream> instream;
- JSPrincipals *jsPrincipals;
JSErrorReporter er;
nsresult rv;
// Instead of calling NS_OpenURI, we create the channel ourselves and call
// SetContentType, to avoid expensive MIME type lookups (bug 632490).
rv = NS_NewChannel(getter_AddRefs(chan), uri, serv,
nsnull, nsnull, nsIRequest::LOAD_NORMAL);
if (NS_SUCCEEDED(rv)) {
@@ -135,49 +135,38 @@ mozJSSubScriptLoader::ReadScript(nsIURI
return ReportError(cx, LOAD_ERROR_NOCONTENT);
}
nsCString buf;
rv = NS_ReadInputStreamToString(instream, buf, len);
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);
if (!charset.IsVoid()) {
nsString script;
rv = nsScriptLoader::ConvertToUTF16(nsnull, reinterpret_cast<const PRUint8*>(buf.get()), len,
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);
return NS_OK;
}
NS_IMETHODIMP
mozJSSubScriptLoader::LoadSubScript(const nsAString& url,
@@ -199,17 +188,17 @@ mozJSSubScriptLoader::LoadSubScript(cons
nsresult rv = NS_OK;
#ifdef NS_FUNCTION_TIMER
NS_TIME_FUNCTION_FMT("%s (line %d) (url: %s)", MOZ_FUNCTION_NAME,
__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);
if (!secman)
return NS_OK;
rv = secman->GetSystemPrincipal(getter_AddRefs(mSystemPrincipal));
if (NS_FAILED(rv) || !mSystemPrincipal)
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -76,16 +76,17 @@
#include "nsCOMArray.h"
#include "nsDirectoryServiceUtils.h"
#include "nsMemory.h"
#include "nsISupportsImpl.h"
#include "nsIJSRuntimeService.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsIXPCSecurityManager.h"
+#include "nsJSPrincipals.h"
#include "xpcpublic.h"
#ifdef XP_MACOSX
#include "xpcshellMacUtils.h"
#endif
#ifdef XP_WIN
#include <windows.h>
#endif
@@ -1734,21 +1735,23 @@ GetCurrentWorkingDirectory(nsAString& wo
cwd.SetLength(strlen(result) + 1);
cwd.Replace(cwd.Length() - 1, 1, '/');
workingDirectory = NS_ConvertUTF8toUTF16(cwd);
#endif
return true;
}
static JSPrincipals *
-FindObjectPrincipals(JSContext *cx, JSObject *obj)
+FindObjectPrincipals(JSObject *obj)
{
return gJSPrincipals;
}
+static JSSecurityCallbacks shellSecurityCallbacks;
+
int
main(int argc, char **argv, char **envp)
{
#ifdef XP_MACOSX
InitAutoreleasePool();
#endif
JSRuntime *rt;
JSContext *cx;
@@ -1900,31 +1903,30 @@ main(int argc, char **argv, char **envp)
nsCOMPtr<nsIScriptSecurityManager> securityManager =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && securityManager) {
rv = securityManager->GetSystemPrincipal(getter_AddRefs(systemprincipal));
if (NS_FAILED(rv)) {
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 {
fprintf(gErrFile, "+++ Failed to get ScriptSecurityManager service, running without principals");
}
}
- 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>
translator(new nsXPCFunctionThisTranslator);
xpc->SetFunctionThisTranslator(NS_GET_IID(nsITestXPCFunctionCallback), translator, nsnull);
#endif
nsCOMPtr<nsIJSContextStack> cxstack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
@@ -2004,17 +2006,17 @@ main(int argc, char **argv, char **envp)
//#define TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN 1
#ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
// test of late call and release (see below)
nsCOMPtr<nsIJSContextStack> bogus;
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;
cxstack->Pop(&oldcx);
NS_ASSERTION(oldcx == cx, "JS thread context push/pop mismatch");
cxstack = nsnull;
JS_GC(cx);
} //this scopes the JSAutoCrossCompartmentCall
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3432,78 +3432,74 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
return NS_ERROR_INVALID_ARG;
}
nsIScriptObjectPrincipal *sop =
(nsIScriptObjectPrincipal*)xpc_GetJSPrivate(sandbox);
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);
callingScope = JS_GetGlobalForScopeChain(cx);
if (!callingScope) {
return NS_ERROR_FAILURE;
}
}
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;
}
if (jsVersion != JSVERSION_DEFAULT)
JS_SetVersion(sandcx->GetJSContext(), jsVersion);
XPCPerThreadData *data = XPCPerThreadData::GetData(cx);
XPCJSContextStack *stack = nsnull;
if (data && (stack = data->GetJSContextStack())) {
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)
unused << stack->Pop();
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,
&v);
if (ok && returnStringOnly && !(JSVAL_IS_VOID(v))) {
ok = !!(str = JS_ValueToString(sandcx->GetJSContext(), v));
}
@@ -3566,18 +3562,16 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
*rval = v;
}
}
}
if (stack)
unused << stack->Pop();
- JSPRINCIPALS_DROP(cx, jsPrincipals);
-
return rv;
}
/* JSObject import (in AUTF8String registryLocation,
* [optional] in JSObject targetObj);
*/
NS_IMETHODIMP
nsXPCComponents_Utils::Import(const nsACString& registryLocation,
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -55,16 +55,18 @@
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "nsContentUtils.h"
#include "nsCCUncollectableMarker.h"
#include "jsfriendapi.h"
#include "js/MemoryMetrics.h"
+#include "nsJSPrincipals.h"
+
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
using namespace mozilla;
using namespace mozilla::xpconnect::memory;
/***************************************************************************/
@@ -1215,82 +1217,53 @@ XPCJSRuntime::~XPCJSRuntime()
#ifdef DEBUG_shaver_off
fprintf(stderr, "nJRSI: destroyed runtime %p\n", (void *)mJSRuntime);
#endif
}
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);
-
- // 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);
- }
- }
+ nsJSPrincipals::get(principals)->GetScriptLocation(name);
- // 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");
+ // 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-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.
static PRInt64
GetGCChunkTotalBytes()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
@@ -1399,19 +1372,22 @@ NS_MEMORY_REPORTER_IMPLEMENT(
} \
} while (0)
template <int N>
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 {
namespace xpconnect {
namespace memory {
static nsresult
ReportCompartmentStats(const JS::CompartmentStats &cStats,
@@ -1689,28 +1665,25 @@ class JSCompartmentsMultiReporter : publ
name.AssignLiteral("compartments");
return NS_OK;
}
typedef js::Vector<nsCString, 0, js::SystemAllocPolicy> Paths;
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,
nsISupports *closure)
{
// First we collect the compartment paths. Then we report them. Doing
// the two steps interleaved is a bad idea, because calling |cb|
// from within CompartmentCallback() leads to all manner of assertions.
@@ -1740,16 +1713,33 @@ class JSCompartmentsMultiReporter : publ
return NS_OK;
}
};
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:
NS_DECL_ISUPPORTS
NS_IMETHOD GetName(nsACString &name)
{
name.AssignLiteral("js");
@@ -1761,18 +1751,17 @@ public:
{
XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance();
// In the first step we get all the stats and stash them in a local
// data structure. In the second step we pass all the stashed stats to
// 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;
size_t xpconnect =
xpcrt->SizeOfIncludingThis(JsMallocSizeOf) +
XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(JsMallocSizeOf);
NS_NAMED_LITERAL_CSTRING(pathPrefix, "explicit/js/");
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1140,22 +1140,18 @@ static bool
CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
xpc::CompartmentPrivate *priv, JSObject **global,
JSCompartment **compartment)
{
// We take ownership of |priv|. Ensure that either we free it in the case
// of failure or give ownership to the compartment in case of success (in
// that case it will be free'd in CompartmentCallback during GC).
nsAutoPtr<xpc::CompartmentPrivate> priv_holder(priv);
- JSPrincipals *principals = nsnull;
- if (principal)
- principal->GetJSPrincipals(cx, &principals);
- JSObject *tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals);
- if (principals)
- JSPRINCIPALS_DROP(cx, principals);
+ JSObject *tempGlobal =
+ JS_NewCompartmentAndGlobalObject(cx, clasp, nsJSPrincipals::get(principal));
if (!tempGlobal)
return false;
*global = tempGlobal;
*compartment = js::GetObjectCompartment(tempGlobal);
JS_SetCompartmentPrivate(*compartment, priv_holder.forget());
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -217,19 +217,16 @@ bool Base64Decode(JSContext *cx, JS::Val
/**
* Convert an nsString to jsval, returning true on success.
* Note, the ownership of the string buffer may be moved from str to rval.
* If that happens, str will point to an empty string after this call.
*/
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
} // namespace xpc
class nsIMemoryMultiReporterCallback;
namespace mozilla {
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -56,18 +56,17 @@
using namespace mozilla;
using namespace js;
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
AccessCheck::isSameOrigin(JSCompartment *a, JSCompartment *b)
{
nsIPrincipal *aprin = GetCompartmentPrincipal(a);
nsIPrincipal *bprin = GetCompartmentPrincipal(b);
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -2159,49 +2159,39 @@ nsCryptoRunnable::~nsCryptoRunnable()
}
//Implementation that runs the callback passed to
//crypto.generateCRMFRequest as an event.
NS_IMETHODIMP
nsCryptoRunnable::Run()
{
nsNSSShutDownPreventionLock locker;
- JSPrincipals *principals;
JSContext *cx = m_args->m_cx;
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, m_args->m_scope)) {
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
//already exists in the user's database.
static bool
nsCertAlreadyExists(SECItem *derCert)
{
CERTCertDBHandle *handle = CERT_GetDefaultCertDB();