--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -40,16 +40,18 @@
#ifndef nsPrincipal_h__
#define nsPrincipal_h__
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
#include "nsHashtable.h"
#include "nsJSPrincipals.h"
+#include "nsTArray.h"
+#include "nsAutoPtr.h"
class nsIObjectInputStream;
class nsIObjectOutputStream;
class nsPrincipal : public nsIPrincipal
{
public:
nsPrincipal();
@@ -95,17 +97,17 @@ public:
void SetURI(nsIURI *aURI);
nsresult SetCapability(const char *capability, void **annotation,
AnnotationValue value);
static const char sInvalid[];
protected:
nsJSPrincipals mJSPrincipals;
- nsVoidArray mAnnotations;
+ 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.
struct Certificate
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -145,28 +145,18 @@ nsPrincipal::Init(const nsACString& aCer
}
}
NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrincipal::Init() failed");
return rv;
}
-
-PR_STATIC_CALLBACK(PRBool)
-deleteElement(void* aElement, void *aData)
-{
- nsHashtable *ht = (nsHashtable *) aElement;
- delete ht;
- return PR_TRUE;
-}
-
nsPrincipal::~nsPrincipal(void)
{
- mAnnotations.EnumerateForwards(deleteElement, nsnull);
SetSecurityPolicy(nsnull);
}
NS_IMETHODIMP
nsPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin)
{
NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitialized!");
@@ -481,33 +471,39 @@ nsPrincipal::RevertCapability(const char
return NS_OK;
}
nsresult
nsPrincipal::SetCapability(const char *capability, void **annotation,
AnnotationValue value)
{
if (*annotation == nsnull) {
- *annotation = new nsHashtable(5);
- if (!*annotation) {
+ nsHashtable* ht = new nsHashtable(5);
+
+ if (!ht) {
return NS_ERROR_OUT_OF_MEMORY;
}
// This object owns its annotations. Save them so we can release
// them when we destroy this object.
- mAnnotations.AppendElement(*annotation);
+ if (!mAnnotations.AppendElement(ht)) {
+ delete ht;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ *annotation = ht;
}
const char *start = capability;
for(;;) {
const char *space = PL_strchr(start, ' ');
int len = space ? space - start : strlen(start);
nsCAutoString capString(start, len);
nsCStringKey key(capString);
- nsHashtable *ht = (nsHashtable *) *annotation;
+ nsHashtable *ht = static_cast<nsHashtable *>(*annotation);
ht->Put(&key, (void *) value);
if (!space) {
break;
}
start = space + 1;
}
@@ -668,17 +664,17 @@ nsPrincipal::InitFromPersistent(const ch
const char* aGrantedList,
const char* aDeniedList,
nsISupports* aCert,
PRBool aIsCert,
PRBool aTrusted)
{
NS_PRECONDITION(mCapabilities.Count() == 0,
"mCapabilities was already initialized?");
- NS_PRECONDITION(mAnnotations.Count() == 0,
+ NS_PRECONDITION(mAnnotations.Length() == 0,
"mAnnotations was already initialized?");
NS_PRECONDITION(!mInitialized, "We were already initialized?");
mInitialized = PR_TRUE;
nsresult rv;
if (aIsCert) {
rv = SetCertificate(aToken, aSubjectName, aPrettyName, aCert);
@@ -906,97 +902,182 @@ FreeAnnotationEntry(nsIObjectInputStream
void* aData)
{
delete aKey;
}
NS_IMETHODIMP
nsPrincipal::Read(nsIObjectInputStream* aStream)
{
- PRUint32 annotationCount;
- nsresult rv = aStream->Read32(&annotationCount);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- for (PRInt32 i = 0, n = PRInt32(annotationCount); i < n; i++) {
- nsHashtable *ht = new nsHashtable(aStream,
- ReadAnnotationEntry,
- FreeAnnotationEntry,
- &rv);
- if (!ht) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- if (NS_FAILED(rv)) {
- delete ht;
- return rv;
- }
-
- if (!mAnnotations.InsertElementAt(reinterpret_cast<void*>(ht), i)) {
- delete ht;
- return NS_ERROR_OUT_OF_MEMORY;
- }
- }
-
PRBool hasCapabilities;
- rv = aStream->ReadBoolean(&hasCapabilities);
+ nsresult rv = aStream->ReadBoolean(&hasCapabilities);
if (NS_SUCCEEDED(rv) && hasCapabilities) {
- mCapabilities = nsHashtable(aStream,
- ReadAnnotationEntry,
- FreeAnnotationEntry,
- &rv);
+ // We want to use one of the nsHashtable constructors, but don't want to
+ // generally have mCapabilities be a pointer... and nsHashtable has no
+ // reasonable copy-constructor. Placement-new to the rescue!
+ mCapabilities.~nsHashtable();
+ new (&mCapabilities) nsHashtable(aStream, ReadAnnotationEntry,
+ FreeAnnotationEntry, &rv);
}
if (NS_FAILED(rv)) {
return rv;
}
rv = NS_ReadOptionalCString(aStream, mPrefName);
if (NS_FAILED(rv)) {
return rv;
}
+ const char* ordinalBegin = PL_strpbrk(mPrefName.get(), "1234567890");
+ if (ordinalBegin) {
+ PRIntn n = atoi(ordinalBegin);
+ if (sCapabilitiesOrdinal <= n) {
+ sCapabilitiesOrdinal = n + 1;
+ }
+ }
+
+ PRBool haveCert;
+ rv = aStream->ReadBoolean(&haveCert);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ nsCString fingerprint;
+ nsCString subjectName;
+ nsCString prettyName;
+ nsCOMPtr<nsISupports> cert;
+ if (haveCert) {
+ rv = NS_ReadOptionalCString(aStream, fingerprint);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = NS_ReadOptionalCString(aStream, subjectName);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = NS_ReadOptionalCString(aStream, prettyName);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = aStream->ReadObject(PR_TRUE, getter_AddRefs(cert));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+
+ nsCOMPtr<nsIURI> codebase;
+ rv = NS_ReadOptionalObject(aStream, PR_TRUE, getter_AddRefs(codebase));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = Init(fingerprint, subjectName, prettyName, cert, codebase);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIURI> domain;
+ rv = NS_ReadOptionalObject(aStream, PR_TRUE, getter_AddRefs(domain));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ SetDomain(domain);
+
+ rv = aStream->Read8(&mTrusted);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
return NS_OK;
}
PR_STATIC_CALLBACK(nsresult)
WriteScalarValue(nsIObjectOutputStream* aStream, void* aData)
{
PRUint32 value = NS_PTR_TO_INT32(aData);
return aStream->Write32(value);
}
NS_IMETHODIMP
nsPrincipal::Write(nsIObjectOutputStream* aStream)
{
- PRUint32 annotationCount = PRUint32(mAnnotations.Count());
- nsresult rv = aStream->Write32(annotationCount);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- for (PRInt32 i = 0, n = PRInt32(annotationCount); i < n; i++) {
- nsHashtable *ht = reinterpret_cast<nsHashtable *>(mAnnotations[i]);
- rv = ht->Write(aStream, WriteScalarValue);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
-
+ NS_ENSURE_STATE(mCert || mCodebase);
+
+ // mAnnotations is transient data associated to specific JS stack frames. We
+ // don't want to serialize that.
+
PRBool hasCapabilities = (mCapabilities.Count() > 0);
- rv = aStream->WriteBoolean(hasCapabilities);
+ nsresult rv = aStream->WriteBoolean(hasCapabilities);
if (NS_SUCCEEDED(rv) && hasCapabilities) {
rv = mCapabilities.Write(aStream, WriteScalarValue);
}
if (NS_FAILED(rv)) {
return rv;
}
rv = NS_WriteOptionalStringZ(aStream, mPrefName.get());
if (NS_FAILED(rv)) {
return rv;
}
+ rv = aStream->WriteBoolean(mCert != nsnull);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (mCert) {
+ NS_ENSURE_STATE(mCert->cert);
+
+ rv = NS_WriteOptionalStringZ(aStream, mCert->fingerprint.get());
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = NS_WriteOptionalStringZ(aStream, mCert->subjectName.get());
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = NS_WriteOptionalStringZ(aStream, mCert->prettyName.get());
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = aStream->WriteCompoundObject(mCert->cert, NS_GET_IID(nsISupports),
+ PR_TRUE);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+
+ // mSecurityPolicy is an optimization; it'll get looked up again as needed.
+ // Don't bother saving and restoring it, esp. since it might change if
+ // preferences change.
+
+ rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI),
+ PR_TRUE);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = NS_WriteOptionalCompoundObject(aStream, mDomain, NS_GET_IID(nsIURI),
+ PR_TRUE);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ // mOrigin is an optimization; don't bother serializing it.
+
+ rv = aStream->Write8(mTrusted);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ // mCodebaseImmutable and mDomainImmutable will be recomputed based
+ // on the deserialized URIs in Read().
+
return NS_OK;
}