Bug 734891 - part 1: Decoupling URI based logic from caps/certificate related logic of nsPrincipal
authorGabor Krizsanits <gkrizsanits@mozilla.com>
Sat, 09 Jun 2012 15:19:26 -0700
changeset 101589 e9814ed8d9748f0f8c721e94a400f45317a3106a
parent 101588 708c967d2fd61d73d0d2ca5710cf320f2b9d37e6
child 101590 6dd8897c873be53815061d699ef15feba809f837
push id191
push userlsblakk@mozilla.com
push dateFri, 05 Oct 2012 17:12:53 +0000
treeherdermozilla-release@ddb22ac6c03b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs734891
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 734891 - part 1: Decoupling URI based logic from caps/certificate related logic of nsPrincipal
caps/include/nsPrincipal.h
caps/src/nsPrincipal.cpp
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -12,74 +12,59 @@
 #include "nsHashtable.h"
 #include "nsJSPrincipals.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
 
-class nsPrincipal : public nsJSPrincipals
+class nsBasePrincipal : public nsJSPrincipals
 {
 public:
-  nsPrincipal();
+  nsBasePrincipal();
 
 protected:
-  virtual ~nsPrincipal();
+  virtual ~nsBasePrincipal();
 
 public:
-  // Our refcount is managed by nsJSPrincipals.  Use this macro to avoid
-  // an extra refcount member.
-  NS_DECL_ISUPPORTS_INHERITED
+  NS_IMETHOD_(nsrefcnt) AddRef(void);
+  NS_IMETHOD_(nsrefcnt) Release(void);
+  NS_SCRIPTABLE NS_IMETHOD GetPreferences(char** prefBranch NS_OUTPARAM, char** id NS_OUTPARAM, char** subjectName NS_OUTPARAM, char** grantedList NS_OUTPARAM, char** deniedList NS_OUTPARAM, bool* isTrusted NS_OUTPARAM);
+  NS_IMETHOD GetSecurityPolicy(void** aSecurityPolicy);
+  NS_IMETHOD SetSecurityPolicy(void* aSecurityPolicy);
+  NS_IMETHOD CanEnableCapability(const char* capability, PRInt16* _retval NS_OUTPARAM);
+  NS_IMETHOD IsCapabilityEnabled(const char* capability, void* annotation, bool* _retval NS_OUTPARAM);
+  NS_IMETHOD EnableCapability(const char* capability, void** annotation NS_INOUTPARAM);
+  NS_IMETHOD GetHasCertificate(bool* aHasCertificate);
+  NS_IMETHOD GetFingerprint(nsACString& aFingerprint);
+  NS_IMETHOD GetPrettyName(nsACString& aPrettyName);
+  NS_IMETHOD GetSubjectName(nsACString& aSubjectName);
+  NS_IMETHOD GetCertificate(nsISupports** aCertificate);
+  NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp);
+  NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp);
 public:
 
-  NS_DECL_NSIPRINCIPAL
-  NS_DECL_NSISERIALIZABLE
-
-  // Either Init() or InitFromPersistent() must be called before
-  // the principal is in a usable state.
-  nsresult Init(const nsACString& aCertFingerprint,
-                const nsACString& aSubjectName,
-                const nsACString& aPrettyName,
-                nsISupports* aCert,
-                nsIURI *aCodebase);
-  nsresult InitFromPersistent(const char* aPrefName,
-                              const nsCString& aFingerprint,
-                              const nsCString& aSubjectName,
-                              const nsACString& aPrettyName,
-                              const char* aGrantedList,
-                              const char* aDeniedList,
-                              nsISupports* aCert,
-                              bool aIsCert,
-                              bool aTrusted);
-
   // Call this to ensure that this principal has a subject name, a pretty name,
   // and a cert pointer.  This method will throw if there is already a
   // different subject name or if this principal has no certificate.
   nsresult EnsureCertData(const nsACString& aSubjectName,
                           const nsACString& aPrettyName,
                           nsISupports* aCert);
 
   enum AnnotationValue { AnnotationEnabled=1, AnnotationDisabled };
 
-  void SetURI(nsIURI *aURI);
-  nsresult SetCapability(const char *capability, void **annotation, 
+  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:
   // Formerly an IDL method. Now just a protected helper.
-  nsresult SetCanEnableCapability(const char *capability, PRInt16 canEnable);
+  nsresult SetCanEnableCapability(const char* capability, PRInt16 canEnable);
 
   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
@@ -103,31 +88,81 @@ protected:
   nsresult SetCertificate(const nsACString& aFingerprint,
                           const nsACString& aSubjectName,
                           const nsACString& aPrettyName,
                           nsISupports* aCert);
 
   // Checks whether this principal's certificate equals aOther's.
   bool CertificateEquals(nsIPrincipal *aOther);
 
+#ifdef DEBUG
+  virtual void dumpImpl() = 0;
+#endif
+
   // Keep this is a pointer, even though it may slightly increase the
   // cost of keeping a certificate, this is a good tradeoff though since
   // it is very rare that we actually have a certificate.
   nsAutoPtr<Certificate> mCert;
 
   DomainPolicy* mSecurityPolicy;
 
   nsCOMPtr<nsIContentSecurityPolicy> mCSP;
-  nsCOMPtr<nsIURI> mCodebase;
+  bool mTrusted;
+};
+
+class nsPrincipal : public nsBasePrincipal
+{
+public:
+  nsPrincipal();
+
+protected:
+  virtual ~nsPrincipal();
+
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSISERIALIZABLE
+  NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
+  NS_IMETHOD EqualsIgnoringDomain(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
+  NS_IMETHOD GetHashValue(PRUint32* aHashValue);
+  NS_IMETHOD GetURI(nsIURI** aURI);
+  NS_IMETHOD GetDomain(nsIURI** aDomain);
+  NS_IMETHOD SetDomain(nsIURI* aDomain);
+  NS_IMETHOD GetOrigin(char** aOrigin);
+  NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
+  NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval NS_OUTPARAM);
+  NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
+#ifdef DEBUG
+  virtual void dumpImpl();
+#endif
+  // Either Init() or InitFromPersistent() must be called before
+  // the principal is in a usable state.
+  nsresult Init(const nsACString& aCertFingerprint,
+                const nsACString& aSubjectName,
+                const nsACString& aPrettyName,
+                nsISupports* aCert,
+                nsIURI* aCodebase);
+  nsresult InitFromPersistent(const char* aPrefName,
+                              const nsCString& aFingerprint,
+                              const nsCString& aSubjectName,
+                              const nsACString& aPrettyName,
+                              const char* aGrantedList,
+                              const char* aDeniedList,
+                              nsISupports* aCert,
+                              bool aIsCert,
+                              bool aTrusted);
+
+  virtual void GetScriptLocation(nsACString& aStr) MOZ_OVERRIDE;
+  void SetURI(nsIURI* aURI);
+
   nsCOMPtr<nsIURI> mDomain;
-  bool mTrusted;
-  bool mInitialized;
+  nsCOMPtr<nsIURI> mCodebase;
   // If mCodebaseImmutable is true, mCodebase is non-null and immutable
   bool mCodebaseImmutable;
   bool mDomainImmutable;
+  bool mInitialized;
 };
 
 
 #define NS_PRINCIPAL_CLASSNAME  "principal"
 #define NS_PRINCIPAL_CONTRACTID "@mozilla.org/principal;1"
 #define NS_PRINCIPAL_CID \
   { 0x36102b6b, 0x7b62, 0x451a, \
     { 0xa1, 0xc8, 0xa0, 0xd4, 0x56, 0xc9, 0x2d, 0xc5 }}
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -39,103 +39,90 @@ static bool URIIsImmutable(nsIURI* aURI)
   bool isMutable;
   return
     mutableObj &&
     NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) &&
     !isMutable;                               
 }
 
 // Static member variables
-PRInt32 nsPrincipal::sCapabilitiesOrdinal = 0;
-const char nsPrincipal::sInvalid[] = "Invalid";
-
-
-NS_IMPL_CLASSINFO(nsPrincipal, NULL, nsIClassInfo::MAIN_THREAD_ONLY,
-                  NS_PRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal,
-                            nsIPrincipal,
-                            nsISerializable)
-NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal,
-                             nsIPrincipal,
-                             nsISerializable)
+PRInt32 nsBasePrincipal::sCapabilitiesOrdinal = 0;
+const char nsBasePrincipal::sInvalid[] = "Invalid";
 
 NS_IMETHODIMP_(nsrefcnt)
-nsPrincipal::AddRef()
+nsBasePrincipal::AddRef()
 {
   NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt");
   // XXXcaa does this need to be threadsafe?  See bug 143559.
   nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount);
-  NS_LOG_ADDREF(this, count, "nsPrincipal", sizeof(*this));
+  NS_LOG_ADDREF(this, count, "nsBasePrincipal", sizeof(*this));
   return count;
 }
 
 NS_IMETHODIMP_(nsrefcnt)
-nsPrincipal::Release()
+nsBasePrincipal::Release()
 {
   NS_PRECONDITION(0 != refcount, "dup release");
   nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount);
-  NS_LOG_RELEASE(this, count, "nsPrincipal");
+  NS_LOG_RELEASE(this, count, "nsBasePrincipal");
   if (count == 0) {
     delete this;
   }
 
   return count;
 }
 
-nsPrincipal::nsPrincipal()
+nsBasePrincipal::nsBasePrincipal()
   : mCapabilities(nsnull),
     mSecurityPolicy(nsnull),
-    mTrusted(false),
-    mInitialized(false),
-    mCodebaseImmutable(false),
-    mDomainImmutable(false)
+    mTrusted(false)
 {
   if (!gIsObservingCodeBasePrincipalSupport) {
     nsresult rv =
       Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
                                    "signed.applets.codebase_principal_support",
                                    false);
     gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv);
     NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport,
                      "Installing gCodeBasePrincipalSupport failed!");
   }
 }
 
-nsPrincipal::~nsPrincipal(void)
+nsBasePrincipal::~nsBasePrincipal(void)
 {
   SetSecurityPolicy(nsnull); 
   delete mCapabilities;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetSecurityPolicy(void** aSecurityPolicy)
+nsBasePrincipal::GetSecurityPolicy(void** aSecurityPolicy)
 {
   if (mSecurityPolicy && mSecurityPolicy->IsInvalid()) 
     SetSecurityPolicy(nsnull);
   
   *aSecurityPolicy = (void *) mSecurityPolicy;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::SetSecurityPolicy(void* aSecurityPolicy)
+nsBasePrincipal::SetSecurityPolicy(void* aSecurityPolicy)
 {
   DomainPolicy *newPolicy = reinterpret_cast<DomainPolicy *>(aSecurityPolicy);
   if (newPolicy)
     newPolicy->Hold();
  
   if (mSecurityPolicy)
     mSecurityPolicy->Drop();
   
   mSecurityPolicy = newPolicy;
   return NS_OK;
 }
 
 bool
-nsPrincipal::CertificateEquals(nsIPrincipal *aOther)
+nsBasePrincipal::CertificateEquals(nsIPrincipal *aOther)
 {
   bool otherHasCert;
   aOther->GetHasCertificate(&otherHasCert);
   if (otherHasCert != (mCert != nsnull)) {
     // One has a cert while the other doesn't.  Not equal.
     return false;
   }
 
@@ -155,46 +142,43 @@ nsPrincipal::CertificateEquals(nsIPrinci
     aOther->GetSubjectName(str);
     return str.Equals(mCert->subjectName) || str.IsEmpty();
   }
 
   return true;
 }
 
 NS_IMETHODIMP
-nsPrincipal::CanEnableCapability(const char *capability, PRInt16 *result)
+nsBasePrincipal::CanEnableCapability(const char *capability, PRInt16 *result)
 {
   // If this principal is marked invalid, can't enable any capabilities
   if (mCapabilities) {
     nsCStringKey invalidKey(sInvalid);
     if (mCapabilities->Exists(&invalidKey)) {
       *result = nsIPrincipal::ENABLE_DENIED;
 
       return NS_OK;
     }
   }
 
   if (!mCert && !mTrusted) {
-    NS_ASSERTION(mInitialized, "Trying to enable a capability on an "
-                               "uninitialized principal");
-
     // If we are a non-trusted codebase principal, capabilities can not
     // be enabled if the user has not set the pref allowing scripts to
     // request enhanced capabilities; however, the file: and resource:
     // schemes are special and may be able to get extra capabilities
     // even with the pref disabled.
-
-    if (!gCodeBasePrincipalSupport) {
-      bool mightEnable = false;
-      nsresult rv = mCodebase->SchemeIs("file", &mightEnable);
+    nsCOMPtr<nsIURI> codebase;
+    GetURI(getter_AddRefs(codebase));
+    if (!gCodeBasePrincipalSupport && codebase) {
+      bool mightEnable = false;     
+      nsresult rv = codebase->SchemeIs("file", &mightEnable);
       if (NS_FAILED(rv) || !mightEnable) {
-        rv = mCodebase->SchemeIs("resource", &mightEnable);
+        rv = codebase->SchemeIs("resource", &mightEnable);
         if (NS_FAILED(rv) || !mightEnable) {
           *result = nsIPrincipal::ENABLE_DENIED;
-
           return NS_OK;
         }
       }
     }
   }
 
   const char *start = capability;
   *result = nsIPrincipal::ENABLE_GRANTED;
@@ -221,18 +205,18 @@ nsPrincipal::CanEnableCapability(const c
 
     start = space + 1;
   }
 
   return NS_OK;
 }
 
 nsresult
-nsPrincipal::SetCanEnableCapability(const char *capability,
-                                    PRInt16 canEnable)
+nsBasePrincipal::SetCanEnableCapability(const char *capability,
+                                        PRInt16 canEnable)
 {
   // If this principal is marked invalid, can't enable any capabilities
   if (!mCapabilities) {
     mCapabilities = new nsHashtable(7);  // XXXbz gets bumped up to 16 anyway
     NS_ENSURE_TRUE(mCapabilities, NS_ERROR_OUT_OF_MEMORY);
   }
 
   nsCStringKey invalidKey(sInvalid);
@@ -257,18 +241,18 @@ nsPrincipal::SetCanEnableCapability(cons
 
     start = space + 1;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::IsCapabilityEnabled(const char *capability, void *annotation,
-                                 bool *result)
+nsBasePrincipal::IsCapabilityEnabled(const char *capability, void *annotation,
+                                     bool *result)
 {
   *result = false;
   nsHashtable *ht = (nsHashtable *) annotation;
   if (!ht) {
     return NS_OK;
   }
   const char *start = capability;
   for(;;) {
@@ -288,24 +272,24 @@ nsPrincipal::IsCapabilityEnabled(const c
 
     start = space + 1;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::EnableCapability(const char *capability, void **annotation)
+nsBasePrincipal::EnableCapability(const char *capability, void **annotation)
 {
   return SetCapability(capability, annotation, AnnotationEnabled);
 }
 
 nsresult
-nsPrincipal::SetCapability(const char *capability, void **annotation,
-                           AnnotationValue value)
+nsBasePrincipal::SetCapability(const char *capability, void **annotation,
+                               AnnotationValue value)
 {
   if (*annotation == nsnull) {
     nsHashtable* ht = new nsHashtable(5);
 
     if (!ht) {
        return NS_ERROR_OUT_OF_MEMORY;
      }
 
@@ -333,108 +317,108 @@ nsPrincipal::SetCapability(const char *c
 
     start = space + 1;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetHasCertificate(bool* aResult)
+nsBasePrincipal::GetHasCertificate(bool* aResult)
 {
   *aResult = (mCert != nsnull);
 
   return NS_OK;
 }
 
 nsresult
-nsPrincipal::SetCertificate(const nsACString& aFingerprint,
-                            const nsACString& aSubjectName,
-                            const nsACString& aPrettyName,
-                            nsISupports* aCert)
+nsBasePrincipal::SetCertificate(const nsACString& aFingerprint,
+                                const nsACString& aSubjectName,
+                                const nsACString& aPrettyName,
+                                nsISupports* aCert)
 {
   NS_ENSURE_STATE(!mCert);
 
   if (aFingerprint.IsEmpty()) {
     return NS_ERROR_INVALID_ARG;
   }
 
   mCert = new Certificate(aFingerprint, aSubjectName, aPrettyName, aCert);
   if (!mCert) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetFingerprint(nsACString& aFingerprint)
+nsBasePrincipal::GetFingerprint(nsACString& aFingerprint)
 {
   NS_ENSURE_STATE(mCert);
 
   aFingerprint = mCert->fingerprint;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetPrettyName(nsACString& aName)
+nsBasePrincipal::GetPrettyName(nsACString& aName)
 {
   NS_ENSURE_STATE(mCert);
 
   aName = mCert->prettyName;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetSubjectName(nsACString& aName)
+nsBasePrincipal::GetSubjectName(nsACString& aName)
 {
   NS_ENSURE_STATE(mCert);
 
   aName = mCert->subjectName;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetCertificate(nsISupports** aCertificate)
+nsBasePrincipal::GetCertificate(nsISupports** aCertificate)
 {
   if (mCert) {
     NS_IF_ADDREF(*aCertificate = mCert->cert);
   }
   else {
     *aCertificate = nsnull;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
+nsBasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
 {
   NS_IF_ADDREF(*aCsp = mCSP);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
+nsBasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
 {
   // If CSP was already set, it should not be destroyed!  Instead, it should
   // get set anew when a new principal is created.
   if (mCSP)
     return NS_ERROR_ALREADY_INITIALIZED;
 
   mCSP = aCsp;
   return NS_OK;
 }
 
 nsresult
-nsPrincipal::EnsureCertData(const nsACString& aSubjectName,
-                            const nsACString& aPrettyName,
-                            nsISupports* aCert)
+nsBasePrincipal::EnsureCertData(const nsACString& aSubjectName,
+                                const nsACString& aPrettyName,
+                                nsISupports* aCert)
 {
   NS_ENSURE_STATE(mCert);
 
   if (!mCert->subjectName.IsEmpty() &&
       !mCert->subjectName.Equals(aSubjectName)) {
     return NS_ERROR_INVALID_ARG;
   }
 
@@ -464,20 +448,20 @@ AppendCapability(nsHashKey *aKey, void *
     capList->denied->Append(key->GetString(), key->GetStringLength());
     capList->denied->Append(' ');
   }
 
   return true;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetPreferences(char** aPrefName, char** aID,
-                            char** aSubjectName,
-                            char** aGrantedList, char** aDeniedList,
-                            bool* aIsTrusted)
+nsBasePrincipal::GetPreferences(char** aPrefName, char** aID,
+                                char** aSubjectName,
+                                char** aGrantedList, char** aDeniedList,
+                                bool* aIsTrusted)
 {
   if (mPrefName.IsEmpty()) {
     if (mCert) {
       mPrefName.Assign("capability.principal.certificate.p");
     }
     else {
       mPrefName.Assign("capability.principal.codebase.p");
     }
@@ -614,16 +598,36 @@ FreeAnnotationEntry(nsIObjectInputStream
 void nsPrincipal::dumpImpl()
 {
   nsCAutoString str;
   GetScriptLocation(str);
   fprintf(stderr, "nsPrincipal (%p) = %s\n", this, str.get());
 }
 #endif 
 
+NS_IMPL_CLASSINFO(nsPrincipal, NULL, nsIClassInfo::MAIN_THREAD_ONLY,
+                  NS_PRINCIPAL_CID)
+NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal,
+                            nsIPrincipal,
+                            nsISerializable)
+NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal,
+                             nsIPrincipal,
+                             nsISerializable)
+NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal);
+NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal);
+
+nsPrincipal::nsPrincipal()
+  : mInitialized(false),
+    mCodebaseImmutable(false),
+    mDomainImmutable(false)
+{ }
+
+nsPrincipal::~nsPrincipal()
+{ }
+
 nsresult
 nsPrincipal::Init(const nsACString& aCertFingerprint,
                   const nsACString& aSubjectName,
                   const nsACString& aPrettyName,
                   nsISupports* aCert,
                   nsIURI *aCodebase)
 {
   NS_ENSURE_STATE(!mInitialized);