Bug 1302047 - Ignore userContextId and firstPartyDomain when matching permissions. r=baku
authorJonathan Hao <jhao@mozilla.com>
Tue, 20 Sep 2016 16:35:21 +0800
changeset 315681 299a09f24493acfbbe8b9457c36e2eccf318d787
parent 315680 b747b6b2db177893986051a8ab562dd0270caebd
child 315682 2ae90c76179f7b7b20483433c6032c5750b37f36
push id30753
push usercbook@mozilla.com
push dateThu, 29 Sep 2016 09:45:12 +0000
treeherdermozilla-central@f7d5008ee2ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1302047
milestone52.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 1302047 - Ignore userContextId and firstPartyDomain when matching permissions. r=baku
caps/BasePrincipal.cpp
caps/BasePrincipal.h
extensions/cookie/nsPermission.cpp
extensions/cookie/nsPermission.h
extensions/cookie/nsPermissionManager.cpp
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -61,16 +61,23 @@ PrincipalOriginAttributes::InheritFromNe
   mUserContextId = aAttrs.mUserContextId;
   mSignedPkg = aAttrs.mSignedPkg;
 
   mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
   mFirstPartyDomain = aAttrs.mFirstPartyDomain;
 }
 
 void
+PrincipalOriginAttributes::StripUserContextIdAndFirstPartyDomain()
+{
+  mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
+  mFirstPartyDomain.Truncate();
+}
+
+void
 DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs)
 {
   mAppId = aAttrs.mAppId;
   mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
 
   // addonId is computed from the principal URI and never propagated
   mUserContextId = aAttrs.mUserContextId;
 
@@ -712,16 +719,33 @@ BasePrincipal::CreateCodebasePrincipal(c
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
 }
 
+already_AddRefed<BasePrincipal>
+BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain()
+{
+  PrincipalOriginAttributes attrs = OriginAttributesRef();
+  attrs.StripUserContextIdAndFirstPartyDomain();
+
+  nsAutoCString originNoSuffix;
+  nsresult rv = GetOriginNoSuffix(originNoSuffix);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  nsCOMPtr<nsIURI> uri;
+  rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
+}
+
 bool
 BasePrincipal::AddonAllowsLoad(nsIURI* aURI)
 {
   if (mOriginAttributes.mAddonId.IsEmpty()) {
     return false;
   }
 
   nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -99,16 +99,18 @@ public:
   //
   // @param aAttrs  Origin Attributes of the docshell.
   // @param aURI    The URI of the document.
   void InheritFromDocShellToDoc(const DocShellOriginAttributes& aAttrs,
                                 const nsIURI* aURI);
 
   // Inherit OriginAttributes from Necko.
   void InheritFromNecko(const NeckoOriginAttributes& aAttrs);
+
+  void StripUserContextIdAndFirstPartyDomain();
 };
 
 // For OriginAttributes stored on docshells / loadcontexts / browsing contexts.
 class DocShellOriginAttributes : public OriginAttributes
 {
 public:
   DocShellOriginAttributes() {}
   DocShellOriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser)
@@ -309,16 +311,18 @@ public:
     eNullPrincipal,
     eCodebasePrincipal,
     eExpandedPrincipal,
     eSystemPrincipal
   };
 
   virtual PrincipalKind Kind() = 0;
 
+  already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain();
+
 protected:
   virtual ~BasePrincipal();
 
   virtual nsresult GetOriginInternal(nsACString& aOrigin) = 0;
   virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0;
 
   // Internal, side-effect-free check to determine whether the concrete
   // principal would allow the load ignoring any common behavior implemented in
--- a/extensions/cookie/nsPermission.cpp
+++ b/extensions/cookie/nsPermission.cpp
@@ -22,16 +22,34 @@ nsPermission::nsPermission(nsIPrincipal*
  : mPrincipal(aPrincipal)
  , mType(aType)
  , mCapability(aCapability)
  , mExpireType(aExpireType)
  , mExpireTime(aExpireTime)
 {
 }
 
+already_AddRefed<nsPermission>
+nsPermission::Create(nsIPrincipal* aPrincipal,
+                     const nsACString &aType,
+                     uint32_t aCapability,
+                     uint32_t aExpireType,
+                     int64_t aExpireTime)
+{
+  NS_ENSURE_TRUE(aPrincipal, nullptr);
+  nsCOMPtr<nsIPrincipal> principal =
+    mozilla::BasePrincipal::Cast(aPrincipal)->CloneStrippingUserContextIdAndFirstPartyDomain();
+
+  NS_ENSURE_TRUE(principal, nullptr);
+
+  RefPtr<nsPermission> permission =
+    new nsPermission(principal, aType, aCapability, aExpireType, aExpireTime);
+  return permission.forget();
+}
+
 NS_IMETHODIMP
 nsPermission::GetPrincipal(nsIPrincipal** aPrincipal)
 {
   nsCOMPtr<nsIPrincipal> copy = mPrincipal;
   copy.forget(aPrincipal);
   return NS_OK;
 }
 
@@ -66,38 +84,46 @@ nsPermission::GetExpireTime(int64_t *aEx
 NS_IMETHODIMP
 nsPermission::Matches(nsIPrincipal* aPrincipal, bool aExactHost, bool* aMatches)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
   NS_ENSURE_ARG_POINTER(aMatches);
 
   *aMatches = false;
 
+  nsCOMPtr<nsIPrincipal> principal =
+    mozilla::BasePrincipal::Cast(aPrincipal)->CloneStrippingUserContextIdAndFirstPartyDomain();
+
+  if (!principal) {
+    *aMatches = false;
+    return NS_OK;
+  }
+
   // If the principals are equal, then they match.
-  if (mPrincipal->Equals(aPrincipal)) {
+  if (mPrincipal->Equals(principal)) {
     *aMatches = true;
     return NS_OK;
   }
 
   // If we are matching with an exact host, we're done now - the permissions don't match
   // otherwise, we need to start comparing subdomains!
   if (aExactHost) {
       return NS_OK;
   }
 
   // Compare their OriginAttributes
-  const mozilla::PrincipalOriginAttributes& theirAttrs = mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
+  const mozilla::PrincipalOriginAttributes& theirAttrs = mozilla::BasePrincipal::Cast(principal)->OriginAttributesRef();
   const mozilla::PrincipalOriginAttributes& ourAttrs = mozilla::BasePrincipal::Cast(mPrincipal)->OriginAttributesRef();
 
   if (theirAttrs != ourAttrs) {
       return NS_OK;
   }
 
   nsCOMPtr<nsIURI> theirURI;
-  nsresult rv = aPrincipal->GetURI(getter_AddRefs(theirURI));
+  nsresult rv = principal->GetURI(getter_AddRefs(theirURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURI> ourURI;
   rv = mPrincipal->GetURI(getter_AddRefs(ourURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Compare schemes
   nsAutoCString theirScheme;
--- a/extensions/cookie/nsPermission.h
+++ b/extensions/cookie/nsPermission.h
@@ -13,23 +13,29 @@
 
 class nsPermission : public nsIPermission
 {
 public:
   // nsISupports
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPERMISSION
 
+  static already_AddRefed<nsPermission> Create(nsIPrincipal* aPrincipal,
+                                               const nsACString &aType,
+                                               uint32_t aCapability,
+                                               uint32_t aExpireType,
+                                               int64_t aExpireTime);
+
+protected:
   nsPermission(nsIPrincipal* aPrincipal,
                const nsACString &aType,
                uint32_t aCapability,
                uint32_t aExpireType,
                int64_t aExpireTime);
 
-protected:
   virtual ~nsPermission() {};
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCString mType;
   uint32_t  mCapability;
   uint32_t  mExpireType;
   int64_t   mExpireTime;
 };
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -117,45 +117,35 @@ GetOriginFromPrincipal(nsIPrincipal* aPr
   if (!attrs.PopulateFromSuffix(suffix)) {
     return NS_ERROR_FAILURE;
   }
 
   // mPrivateBrowsingId must be set to false because PermissionManager is not supposed to have
   // any knowledge of private browsing. Allowing it to be true changes the suffix being hashed.
   attrs.mPrivateBrowsingId = 0;
 
-  // TODO: Bug 1302047 - Ignore userContextId and firstPartyDomain when matching permissions.
-
-  // set to default to disable user context isolation for permissions
-  attrs.mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
-
-  // set to default to disable firstParty isolation for permissions.
-  attrs.mFirstPartyDomain.Truncate();
+  // Disable userContext and firstParty isolation for permissions.
+  attrs.StripUserContextIdAndFirstPartyDomain();
 
   attrs.CreateSuffix(suffix);
   aOrigin.Append(suffix);
   return NS_OK;
 }
 
 nsresult
 GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal)
 {
   nsAutoCString originNoSuffix;
   mozilla::PrincipalOriginAttributes attrs;
   if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
     return NS_ERROR_FAILURE;
   }
 
-  // TODO: Bug 1302047 - Ignore userContextId and firstPartyDomain when matching permissions.
-
-  // set to default to disable user context isolation for permissions
-  attrs.mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
-
-  // set to default to disable firstParty isolation for permissions.
-  attrs.mFirstPartyDomain.Truncate();
+  // Disable userContext and firstParty isolation for permissions.
+  attrs.StripUserContextIdAndFirstPartyDomain();
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
   principal.forget(aPrincipal);
   return NS_OK;
@@ -2060,21 +2050,24 @@ nsPermissionManager::GetPermissionObject
     return NS_OK;
   }
 
   nsCOMPtr<nsIPrincipal> principal;
   nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PermissionEntry& perm = entry->GetPermissions()[idx];
-  nsCOMPtr<nsIPermission> r = new nsPermission(principal,
-                                               mTypeArray.ElementAt(perm.mType),
-                                               perm.mPermission,
-                                               perm.mExpireType,
-                                               perm.mExpireTime);
+  nsCOMPtr<nsIPermission> r = nsPermission::Create(principal,
+                                                   mTypeArray.ElementAt(perm.mType),
+                                                   perm.mPermission,
+                                                   perm.mExpireType,
+                                                   perm.mExpireTime);
+  if (NS_WARN_IF(!r)) {
+    return NS_ERROR_FAILURE;
+  }
   r.forget(aResult);
   return NS_OK;
 }
 
 nsresult
 nsPermissionManager::CommonTestPermission(nsIPrincipal* aPrincipal,
                                           const char *aType,
                                           uint32_t   *aPermission,
@@ -2203,23 +2196,18 @@ nsPermissionManager::GetPermissionHashKe
     if (NS_FAILED(rv)) {
       return nullptr;
     }
 
     // Copy the attributes over
     mozilla::PrincipalOriginAttributes attrs =
       mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
 
-    // TODO: Bug 1302047 - Ignore userContextId and firstPartyDomain when matching permissions.
-
-    // ensure that the user context isolation is disabled
-    attrs.mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
-
-    // ensure firstPartyIsolation is disabled.
-    attrs.mFirstPartyDomain.Truncate();
+    // Disable userContext and firstParty isolation for permissions.
+    attrs.StripUserContextIdAndFirstPartyDomain();
 
     nsCOMPtr<nsIPrincipal> principal =
       mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs);
 
     return GetPermissionHashKey(principal, aType, aExactHostMatch);
   }
 
   // No entry, really...
@@ -2243,22 +2231,26 @@ NS_IMETHODIMP nsPermissionManager::GetEn
 
       nsCOMPtr<nsIPrincipal> principal;
       nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin,
                                            getter_AddRefs(principal));
       if (NS_FAILED(rv)) {
         continue;
       }
 
-      array.AppendObject(
-        new nsPermission(principal,
-                         mTypeArray.ElementAt(permEntry.mType),
-                         permEntry.mPermission,
-                         permEntry.mExpireType,
-                         permEntry.mExpireTime));
+      nsCOMPtr<nsIPermission> permission =
+        nsPermission::Create(principal,
+                             mTypeArray.ElementAt(permEntry.mType),
+                             permEntry.mPermission,
+                             permEntry.mExpireType,
+                             permEntry.mExpireTime);
+      if (NS_WARN_IF(!permission)) {
+        continue;
+      }
+      array.AppendObject(permission);
     }
   }
 
   return NS_NewArrayEnumerator(aEnum, array);
 }
 
 NS_IMETHODIMP nsPermissionManager::GetAllForURI(nsIURI* aURI, nsISimpleEnumerator **aEnum)
 {
@@ -2273,22 +2265,26 @@ NS_IMETHODIMP nsPermissionManager::GetAl
 
   if (entry) {
     for (const auto& permEntry : entry->GetPermissions()) {
       // Only return custom permissions
       if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
         continue;
       }
 
-      array.AppendObject(
-        new nsPermission(principal,
-                         mTypeArray.ElementAt(permEntry.mType),
-                         permEntry.mPermission,
-                         permEntry.mExpireType,
-                         permEntry.mExpireTime));
+      nsCOMPtr<nsIPermission> permission =
+        nsPermission::Create(principal,
+                             mTypeArray.ElementAt(permEntry.mType),
+                             permEntry.mPermission,
+                             permEntry.mExpireType,
+                             permEntry.mExpireTime);
+      if (NS_WARN_IF(!permission)) {
+        continue;
+      }
+      array.AppendObject(permission);
     }
   }
 
   return NS_NewArrayEnumerator(aEnum, array);
 }
 
 NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
 {
@@ -2323,22 +2319,26 @@ nsPermissionManager::RemoveAllModifiedSi
 
       nsCOMPtr<nsIPrincipal> principal;
       nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin,
                                            getter_AddRefs(principal));
       if (NS_FAILED(rv)) {
         continue;
       }
 
-      array.AppendObject(
-        new nsPermission(principal,
-                         mTypeArray.ElementAt(permEntry.mType),
-                         permEntry.mPermission,
-                         permEntry.mExpireType,
-                         permEntry.mExpireTime));
+      nsCOMPtr<nsIPermission> permission =
+        nsPermission::Create(principal,
+                             mTypeArray.ElementAt(permEntry.mType),
+                             permEntry.mPermission,
+                             permEntry.mExpireType,
+                             permEntry.mExpireTime);
+      if (NS_WARN_IF(!permission)) {
+        continue;
+      }
+      array.AppendObject(permission);
     }
   }
 
   for (int32_t i = 0; i<array.Count(); ++i) {
     nsCOMPtr<nsIPrincipal> principal;
     nsAutoCString type;
 
     nsresult rv = array[i]->GetPrincipal(getter_AddRefs(principal));
@@ -2395,22 +2395,26 @@ nsPermissionManager::RemovePermissionsWi
       continue;
     }
 
     if (!aPattern.Matches(mozilla::BasePrincipal::Cast(principal)->OriginAttributesRef())) {
       continue;
     }
 
     for (const auto& permEntry : entry->GetPermissions()) {
-      permissions.AppendObject(
-        new nsPermission(principal,
-                         mTypeArray.ElementAt(permEntry.mType),
-                         permEntry.mPermission,
-                         permEntry.mExpireType,
-                         permEntry.mExpireTime));
+      nsCOMPtr<nsIPermission> permission =
+        nsPermission::Create(principal,
+                             mTypeArray.ElementAt(permEntry.mType),
+                             permEntry.mPermission,
+                             permEntry.mExpireType,
+                             permEntry.mExpireTime);
+      if (NS_WARN_IF(!permission)) {
+        continue;
+      }
+      permissions.AppendObject(permission);
     }
   }
 
   for (int32_t i = 0; i < permissions.Count(); ++i) {
     nsCOMPtr<nsIPrincipal> principal;
     nsAutoCString type;
 
     permissions[i]->GetPrincipal(getter_AddRefs(principal));
@@ -2531,18 +2535,18 @@ void
 nsPermissionManager::NotifyObserversWithPermission(nsIPrincipal*     aPrincipal,
                                                    const nsCString  &aType,
                                                    uint32_t          aPermission,
                                                    uint32_t          aExpireType,
                                                    int64_t           aExpireTime,
                                                    const char16_t  *aData)
 {
   nsCOMPtr<nsIPermission> permission =
-    new nsPermission(aPrincipal, aType, aPermission,
-                     aExpireType, aExpireTime);
+    nsPermission::Create(aPrincipal, aType, aPermission,
+                         aExpireType, aExpireTime);
   if (permission)
     NotifyObservers(permission, aData);
 }
 
 // notify observers that the permission list changed. there are four possible
 // values for aData:
 // "deleted" means a permission was deleted. aPermission is the deleted permission.
 // "added"   means a permission was added. aPermission is the added permission.