Bug 413161: Make nsIPrincipal::Origin ignore changes to document.domain. r/sr=dveditz
authorjonas@sicking.cc
Tue, 18 Mar 2008 17:27:56 -0700
changeset 13284 1d07cdf5f1b04dfe6da4189f0118ec66d91dc905
parent 13283 a13e15e91e8d781d8c888b940270e9775bc42368
child 13285 ea8ea9c1fadf6433091765da159abf96ef1883e9
push idunknown
push userunknown
push dateunknown
bugs413161
milestone1.9b5pre
Bug 413161: Make nsIPrincipal::Origin ignore changes to document.domain. r/sr=dveditz
caps/idl/nsIPrincipal.idl
caps/include/nsPrincipal.h
caps/src/nsPrincipal.cpp
caps/src/nsScriptSecurityManager.cpp
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -46,17 +46,17 @@ struct JSContext;
 struct JSPrincipals;
 %}
 
 interface nsIURI;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 
-[scriptable, uuid(7292475e-2821-4602-9d00-228476696428)]
+[scriptable, uuid(b8268b9a-2403-44ed-81e3-614075c92034)]
 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;
@@ -137,19 +137,18 @@ interface nsIPrincipal : nsISerializable
     /**
      * The domain URI to which this principal pertains.
      * This is congruent with HTMLDocument.domain, and may be null.
      * Setting this has no effect on the URI.
      */
     [noscript] attribute nsIURI domain;
 
     /**
-     * The origin of this principal's domain, if non-null, or its
-     * codebase URI otherwise. An origin is defined as:
-     * scheme + host + port.
+     * The origin of this principal's codebase URI.
+     * An origin is defined as: scheme + host + port.
      */
     // XXXcaa this should probably be turned into an nsIURI.
     // The system principal's origin should be some caps namespace
     // with a chrome URI.  All of chrome should probably be the same.
     [noscript] readonly attribute string origin;
 
     /**
      * Whether this principal is associated with a certificate.
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -135,17 +135,16 @@ protected:
   // 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<nsIURI> mCodebase;
   nsCOMPtr<nsIURI> mDomain;
-  nsCOMPtr<nsIURI> mOrigin;
   PRPackedBool mTrusted;
   PRPackedBool mInitialized;
   // If mCodebaseImmutable is true, mCodebase is non-null and immutable
   PRPackedBool mCodebaseImmutable;
   PRPackedBool mDomainImmutable;
 };
 
 
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -123,19 +123,16 @@ nsPrincipal::Init(const nsACString& aCer
   NS_ENSURE_STATE(!mInitialized);
   NS_ENSURE_ARG(!aCertFingerprint.IsEmpty() || aCodebase); // better have one of these.
 
   mInitialized = PR_TRUE;
 
   mCodebase = NS_TryToMakeImmutable(aCodebase);
   mCodebaseImmutable = URIIsImmutable(mCodebase);
 
-  // Invalidate our cached origin
-  mOrigin = nsnull;
-
   nsresult rv;
   if (!aCertFingerprint.IsEmpty()) {
     rv = SetCertificate(aCertFingerprint, aSubjectName, aPrettyName, aCert);
     if (NS_SUCCEEDED(rv)) {
       rv = mJSPrincipals.Init(this, mCert->fingerprint);
     }
   }
   else {
@@ -167,51 +164,49 @@ nsPrincipal::GetJSPrincipals(JSContext *
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPrincipal::GetOrigin(char **aOrigin)
 {
   *aOrigin = nsnull;
 
-  if (!mOrigin) {
-    nsIURI* uri = mDomain ? mDomain : mCodebase;
-    if (uri) {
-      mOrigin = NS_GetInnermostURI(uri);
-    }
+  nsCOMPtr<nsIURI> origin;
+  if (mCodebase) {
+    origin = NS_GetInnermostURI(mCodebase);
   }
   
-  if (!mOrigin) {
+  if (!origin) {
     NS_ASSERTION(mCert, "No Domain or Codebase for a non-cert principal");
     return NS_ERROR_FAILURE;
   }
 
   nsCAutoString hostPort;
 
   // chrome: URLs don't have a meaningful origin, so make
   // sure we just get the full spec for them.
   // XXX this should be removed in favor of the solution in
   // bug 160042.
   PRBool isChrome;
-  nsresult rv = mOrigin->SchemeIs("chrome", &isChrome);
+  nsresult rv = origin->SchemeIs("chrome", &isChrome);
   if (NS_SUCCEEDED(rv) && !isChrome) {
-    rv = mOrigin->GetHostPort(hostPort);
+    rv = origin->GetHostPort(hostPort);
   }
 
   if (NS_SUCCEEDED(rv) && !isChrome) {
     nsCAutoString scheme;
-    rv = mOrigin->GetScheme(scheme);
+    rv = origin->GetScheme(scheme);
     NS_ENSURE_SUCCESS(rv, rv);
     *aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort);
   }
   else {
     // Some URIs (e.g., nsSimpleURI) don't support host. Just
     // get the full spec.
     nsCAutoString spec;
-    rv = mOrigin->GetSpec(spec);
+    rv = origin->GetSpec(spec);
     NS_ENSURE_SUCCESS(rv, rv);
     *aOrigin = ToNewCString(spec);
   }
 
   return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 NS_IMETHODIMP
@@ -560,19 +555,16 @@ nsPrincipal::GetURI(nsIURI** aURI)
   return NS_EnsureSafeToReturn(mCodebase, aURI);
 }
 
 void
 nsPrincipal::SetURI(nsIURI* aURI)
 {
   mCodebase = NS_TryToMakeImmutable(aURI);
   mCodebaseImmutable = URIIsImmutable(mCodebase);
-
-  // Invalidate our cached origin
-  mOrigin = nsnull;
 }
 
 
 nsresult
 nsPrincipal::SetCertificate(const nsACString& aFingerprint,
                             const nsACString& aSubjectName,
                             const nsACString& aPrettyName,
                             nsISupports* aCert)
@@ -671,19 +663,16 @@ NS_IMETHODIMP
 nsPrincipal::SetDomain(nsIURI* aDomain)
 {
   mDomain = NS_TryToMakeImmutable(aDomain);
   mDomainImmutable = URIIsImmutable(mDomain);
   
   // Domain has changed, forget cached security policy
   SetSecurityPolicy(nsnull);
 
-  // Invalidate our cached origin
-  mOrigin = nsnull;
-
   return NS_OK;
 }
 
 nsresult
 nsPrincipal::InitFromPersistent(const char* aPrefName,
                                 const nsCString& aToken,
                                 const nsCString& aSubjectName,
                                 const nsACString& aPrettyName,
@@ -715,19 +704,16 @@ nsPrincipal::InitFromPersistent(const ch
       NS_ERROR("Malformed URI in capability.principal preference.");
       return rv;
     }
 
     NS_TryToSetImmutable(mCodebase);
     mCodebaseImmutable = URIIsImmutable(mCodebase);
 
     mTrusted = aTrusted;
-
-    // Invalidate our cached origin
-    mOrigin = nsnull;
   }
 
   rv = mJSPrincipals.Init(this, aToken);
   NS_ENSURE_SUCCESS(rv, rv);
 
   //-- Save the preference name
   mPrefName = aPrefName;
 
@@ -1089,18 +1075,16 @@ nsPrincipal::Write(nsIObjectOutputStream
   }
 
   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().
 
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -1063,16 +1063,50 @@ nsScriptSecurityManager::CheckSameOrigin
         return NS_OK;
 
     /*
     ** Access tests failed, so now report error.
     */
     return NS_ERROR_DOM_PROP_ACCESS_DENIED;
 }
 
+static
+nsresult
+GetPrincipalDomainOrigin(nsIPrincipal* aPrincipal,
+                         nsACString& aOrigin)
+{
+  aOrigin.Truncate();
+
+  nsCOMPtr<nsIURI> uri;
+  aPrincipal->GetDomain(getter_AddRefs(uri));
+  if (!uri) {
+    aPrincipal->GetURI(getter_AddRefs(uri));
+  }
+
+  NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
+
+  nsCAutoString hostPort;
+
+  nsresult rv = uri->GetHostPort(hostPort);
+  if (NS_SUCCEEDED(rv)) {
+    nsCAutoString scheme;
+    rv = uri->GetScheme(scheme);
+    NS_ENSURE_SUCCESS(rv, rv);
+    aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort;
+  }
+  else {
+    // Some URIs (e.g., nsSimpleURI) don't support host. Just
+    // get the full spec.
+    rv = uri->GetSpec(aOrigin);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
+}
+
 nsresult
 nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
                                       ClassInfoData& aClassData,
                                       jsval aProperty,
                                       PRUint32 aAction,
                                       ClassPolicy** aCachedClassPolicy,
                                       SecurityLevel* result)
 {
@@ -1094,19 +1128,19 @@ nsScriptSecurityManager::LookupPolicy(ns
 
     if (!dpolicy && mOriginToPolicyMap)
     {
         //-- Look up the relevant domain policy, if any
 #ifdef DEBUG_CAPS_LookupPolicy
         printf("DomainLookup ");
 #endif
 
-        nsXPIDLCString origin;
-        if (NS_FAILED(rv = aPrincipal->GetOrigin(getter_Copies(origin))))
-            return rv;
+        nsCAutoString origin;
+        rv = GetPrincipalDomainOrigin(aPrincipal, origin);
+        NS_ENSURE_SUCCESS(rv, rv);
  
         char *start = origin.BeginWriting();
         const char *nextToLastDot = nsnull;
         const char *lastDot = nsnull;
         const char *colon = nsnull;
         char *p = start;
 
         //-- search domain (stop at the end of the string or at the 3rd slash)
@@ -2665,23 +2699,23 @@ nsScriptSecurityManager::CheckConfirmDia
         return PR_FALSE;
 
     nsXPIDLString noStr;
     rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("No").get(),
                                        getter_Copies(noStr));
     if (NS_FAILED(rv))
         return PR_FALSE;
 
-    nsXPIDLCString val;
+    nsCAutoString val;
     PRBool hasCert;
     aPrincipal->GetHasCertificate(&hasCert);
     if (hasCert)
         rv = aPrincipal->GetPrettyName(val);
     else
-        rv = aPrincipal->GetOrigin(getter_Copies(val));
+        rv = GetPrincipalDomainOrigin(aPrincipal, val);
 
     if (NS_FAILED(rv))
         return PR_FALSE;
 
     NS_ConvertUTF8toUTF16 location(val);
     NS_ConvertASCIItoUTF16 capability(aCapability);
     FormatCapabilityString(capability);
     const PRUnichar *formatStrings[] = { location.get(), capability.get() };
@@ -2786,24 +2820,24 @@ nsScriptSecurityManager::EnableCapabilit
         return NS_OK;
 
     PRInt16 canEnable;
     if (NS_FAILED(RequestCapability(principal, capability, &canEnable)))
         return NS_ERROR_FAILURE;
 
     if (canEnable != nsIPrincipal::ENABLE_GRANTED)
     {
-        nsXPIDLCString val;
+        nsCAutoString val;
         PRBool hasCert;
         nsresult rv;
         principal->GetHasCertificate(&hasCert);
         if (hasCert)
             rv = principal->GetPrettyName(val);
         else
-            rv = principal->GetOrigin(getter_Copies(val));
+            rv = GetPrincipalDomainOrigin(principal, val);
 
         if (NS_FAILED(rv))
             return rv;
 
         NS_ConvertUTF8toUTF16 location(val);
         NS_ConvertUTF8toUTF16 cap(capability);
         const PRUnichar *formatStrings[] = { location.get(), cap.get() };