diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp index a99d8dce5517..680c505bc36e 100644 --- a/caps/BasePrincipal.cpp +++ b/caps/BasePrincipal.cpp @@ -27,6 +27,10 @@ #include "mozilla/dom/StorageUtils.h" #include "mozilla/dom/StorageUtils.h" #include "nsIURL.h" +#include "nsEffectiveTLDService.h" +#include "nsIURIMutator.h" +#include "mozilla/StaticPrefs_permissions.h" +#include "nsIURIMutator.h" #include "prnetdb.h" #include "nsIURIFixup.h" #include "mozilla/dom/StorageUtils.h" @@ -1028,6 +1032,49 @@ BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) { return NS_OK; } +NS_IMETHODIMP +BasePrincipal::GetNextSubDomainPrincipal( + nsIPrincipal** aNextSubDomainPrincipal) { + nsCOMPtr uri; + nsresult rv = GetURI(getter_AddRefs(uri)); + if (NS_FAILED(rv) || !uri) { + return NS_OK; + } + + nsAutoCString host; + rv = uri->GetHost(host); + if (NS_FAILED(rv) || host.IsEmpty()) { + return NS_OK; + } + + nsCString subDomain; + rv = nsEffectiveTLDService::GetInstance()->GetNextSubDomain(host, subDomain); + + if (NS_FAILED(rv) || subDomain.IsEmpty()) { + return NS_OK; + } + + nsCOMPtr subDomainURI; + rv = NS_MutateURI(uri).SetHost(subDomain).Finalize(subDomainURI); + if (NS_FAILED(rv) || !subDomainURI) { + return NS_OK; + } + // Copy the attributes over + mozilla::OriginAttributes attrs = OriginAttributesRef(); + + if (!StaticPrefs::permissions_isolateBy_userContext()) { + // Disable userContext for permissions. + attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID); + } + RefPtr principal = + mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI, attrs); + + if (!principal) { + return NS_OK; + } + principal.forget(aNextSubDomainPrincipal); + return NS_OK; +} NS_IMETHODIMP BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) { diff --git a/caps/BasePrincipal.h b/caps/BasePrincipal.h index 959fb60bbb8e..b123cf6d4880 100644 --- a/caps/BasePrincipal.h +++ b/caps/BasePrincipal.h @@ -157,6 +157,9 @@ class BasePrincipal : public nsJSPrincipals { NS_IMETHOD GetIsScriptAllowedByPolicy( bool* aIsScriptAllowedByPolicy) override; NS_IMETHOD GetStorageOriginKey(nsACString& aOriginKey) override; + + NS_IMETHOD GetNextSubDomainPrincipal( + nsIPrincipal** aNextSubDomainPrincipal) override; nsresult ToJSON(nsACString& aJSON); static already_AddRefed FromJSON(const nsACString& aJSON); // Method populates a passed Json::Value with serializable fields diff --git a/caps/nsIPrincipal.idl b/caps/nsIPrincipal.idl index 417e510c5a48..7f5b2ec774a7 100644 --- a/caps/nsIPrincipal.idl +++ b/caps/nsIPrincipal.idl @@ -475,6 +475,13 @@ interface nsIPrincipal : nsISerializable */ boolean isL10nAllowed(in nsIURI aDocumentURI); + /** + * Returns a nsIPrincipal, with one less Subdomain Segment + * Returns `nullptr` if there are no more segments to remove. + */ + + [infallible] readonly attribute nsIPrincipal nextSubDomainPrincipal; + /** * Returns if the principal is for an IP address. */ diff --git a/extensions/permissions/PermissionManager.cpp b/extensions/permissions/PermissionManager.cpp index 13ce4c832752..31df4e06ca66 100644 --- a/extensions/permissions/PermissionManager.cpp +++ b/extensions/permissions/PermissionManager.cpp @@ -323,38 +323,6 @@ already_AddRefed GetNextSubDomainURI(nsIURI* aURI) { return uri.forget(); } -// This function produces a nsIPrincipal which is identical to the current -// nsIPrincipal, except that it has one less subdomain segment. It returns -// `nullptr` if there are no more segments to remove. -already_AddRefed GetNextSubDomainPrincipal( - nsIPrincipal* aPrincipal) { - nsCOMPtr uri; - nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); - if (NS_FAILED(rv) || !uri) { - return nullptr; - } - - // Create a new principal which is identical to the current one, but with the - // new host - nsCOMPtr newURI = GetNextSubDomainURI(uri); - if (!newURI) { - return nullptr; - } - - // Copy the attributes over - OriginAttributes attrs = aPrincipal->OriginAttributesRef(); - - if (!StaticPrefs::permissions_isolateBy_userContext()) { - // Disable userContext for permissions. - attrs.StripAttributes(OriginAttributes::STRIP_USER_CONTEXT_ID); - } - - nsCOMPtr principal = - BasePrincipal::CreateContentPrincipal(newURI, attrs); - - return principal.forget(); -} - nsresult UpgradeHostToOriginAndInsert( const nsACString& aHost, const nsCString& aType, uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime, @@ -2548,7 +2516,7 @@ PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey( // If aExactHostMatch wasn't true, we can check if the base domain has a // permission entry. if (!aExactHostMatch) { - nsCOMPtr principal = GetNextSubDomainPrincipal(aPrincipal); + nsCOMPtr principal = aPrincipal->GetNextSubDomainPrincipal(); if (principal) { return GetPermissionHashKey(principal, aType, aExactHostMatch); } @@ -3117,9 +3085,8 @@ PermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) { GetKeyForPrincipal(prin, false, pair->first); Unused << GetOriginFromPrincipal(prin, false, pair->second); - + prin = prin->GetNextSubDomainPrincipal(); // Get the next subdomain principal and loop back around. - prin = GetNextSubDomainPrincipal(prin); } MOZ_ASSERT(pairs.Length() >= 1,