Loading dom/ipc/ContentParent.cpp +6 −3 Original line number Diff line number Diff line Loading @@ -5096,9 +5096,12 @@ ContentParent::TransmitPermissionsFor(nsIChannel* aChannel) NS_ENSURE_SUCCESS(rv, rv); // Create the key, and send it down to the content process. nsAutoCString key; nsPermissionManager::GetKeyForPrincipal(principal, key); nsTArray<nsCString> keys = nsPermissionManager::GetAllKeysForPrincipal(principal); MOZ_ASSERT(keys.Length() >= 1); for (auto& key : keys) { EnsurePermissionsByKey(key); } #endif return NS_OK; Loading extensions/cookie/nsPermissionManager.cpp +90 −58 Original line number Diff line number Diff line Loading @@ -176,6 +176,54 @@ GetNextSubDomainForHost(const nsACString& aHost) return subDomain; } // 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<nsIPrincipal> GetNextSubDomainPrincipal(nsIPrincipal* aPrincipal) { nsCOMPtr<nsIURI> uri; nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_FAILED(rv) || !uri) { return nullptr; } nsAutoCString host; rv = uri->GetHost(host); if (NS_FAILED(rv)) { return nullptr; } nsCString domain = GetNextSubDomainForHost(host); if (domain.IsEmpty()) { return nullptr; } // Create a new principal which is identical to the current one, but with the new host nsCOMPtr<nsIURI> newURI; rv = uri->Clone(getter_AddRefs(newURI)); if (NS_FAILED(rv)) { return nullptr; } rv = newURI->SetHost(domain); if (NS_FAILED(rv)) { return nullptr; } // Copy the attributes over mozilla::OriginAttributes attrs = aPrincipal->OriginAttributesRef(); // Disable userContext and firstParty isolation for permissions. attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID | mozilla::OriginAttributes::STRIP_FIRST_PARTY_DOMAIN); nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs); return principal.forget(); } class ClearOriginDataObserver final : public nsIObserver { ~ClearOriginDataObserver() {} Loading Loading @@ -2185,47 +2233,12 @@ nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal, // If aExactHostMatch wasn't true, we can check if the base domain has a permission entry. if (!aExactHostMatch) { nsCOMPtr<nsIURI> uri; nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_FAILED(rv)) { return nullptr; } nsAutoCString host; rv = uri->GetHost(host); if (NS_FAILED(rv)) { return nullptr; } nsCString domain = GetNextSubDomainForHost(host); if (domain.IsEmpty()) { return nullptr; } // Create a new principal which is identical to the current one, but with the new host nsCOMPtr<nsIURI> newURI; rv = uri->Clone(getter_AddRefs(newURI)); if (NS_FAILED(rv)) { return nullptr; } rv = newURI->SetHost(domain); if (NS_FAILED(rv)) { return nullptr; } // Copy the attributes over mozilla::OriginAttributes attrs = aPrincipal->OriginAttributesRef(); // Disable userContext and firstParty isolation for permissions. attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID | mozilla::OriginAttributes::STRIP_FIRST_PARTY_DOMAIN); nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs); GetNextSubDomainPrincipal(aPrincipal); if (principal) { return GetPermissionHashKey(principal, aType, aExactHostMatch); } } // No entry, really... return nullptr; Loading Loading @@ -3014,7 +3027,6 @@ nsPermissionManager::SetPermissionsWithKey(const nsACString& aPermissionKey, return NS_OK; } // XXX: Support file URIs here as well! /* static */ void nsPermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aKey) { Loading @@ -3027,31 +3039,51 @@ nsPermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aK // NOTE: We don't propagate the error here, instead we produce the default // "" permission key. This means that we can assign every principal a key, // even if the GetURI operation on that principal is not meaningful. aKey.Truncate(); return; } // If the URI isn't of one of the supported schemes, it has the "" permission // key. We can do an early return in that case. nsAutoCString scheme; uri->GetScheme(scheme); if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https") && !scheme.EqualsLiteral("ftp")) { rv = uri->GetScheme(scheme); if (NS_WARN_IF(NS_FAILED(rv))) { // NOTE: Produce the default "" key as a fallback. aKey.Truncate(); return; } // We key sets of permissions to be sent over IPC based on their eTLD+1, or in // the case where that isn't meaningful, on their IP address or spec. nsCOMPtr<nsIEffectiveTLDService> etldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); rv = etldService->GetBaseDomain(uri, 0, aKey); if (NS_FAILED(rv)) { rv = uri->GetHost(aKey); // URIs which have schemes other than http, https and ftp share the "" // permission key. if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https") || scheme.EqualsLiteral("ftp")) { rv = GetOriginFromPrincipal(aPrincipal, aKey); if (NS_SUCCEEDED(rv)) { return; } if (NS_FAILED(rv)) { rv = uri->GetSpec(aKey); } if (NS_FAILED(rv)) { // NOTE: Produce the default "" key as a fallback. aKey.Truncate(); return; } /* static */ nsTArray<nsCString> nsPermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) { MOZ_ASSERT(aPrincipal); nsTArray<nsCString> keys; nsCOMPtr<nsIPrincipal> prin = aPrincipal; while (prin) { // Add the key to the list nsCString* key = keys.AppendElement(); GetKeyForPrincipal(prin, *key); // Get the next subdomain principal and loop back around. prin = GetNextSubDomainPrincipal(prin); } MOZ_ASSERT(keys.Length() >= 1, "Every principal should have at least one key."); return keys; } extensions/cookie/nsPermissionManager.h +17 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,23 @@ public: */ static void GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aPermissionKey); /** * See `nsIPermissionManager::GetPermissionsWithKey` for more info on * permission keys. * * Get all permissions keys which could correspond to the given principal. * This method, like GetKeyForPrincipal, is infallible and should always * produce at least one key. * * Unlike GetKeyForPrincipal, this method also gets the keys for base domains * of the given principal. All keys returned by this method must be avaliable * in the content process for a given URL to successfully have its permissions * checked in the `aExactHostMatch = false` situation. * * @param aPrincipal The Principal which the key is to be extracted from. */ static nsTArray<nsCString> GetAllKeysForPrincipal(nsIPrincipal* aPrincipal); private: virtual ~nsPermissionManager(); Loading Loading
dom/ipc/ContentParent.cpp +6 −3 Original line number Diff line number Diff line Loading @@ -5096,9 +5096,12 @@ ContentParent::TransmitPermissionsFor(nsIChannel* aChannel) NS_ENSURE_SUCCESS(rv, rv); // Create the key, and send it down to the content process. nsAutoCString key; nsPermissionManager::GetKeyForPrincipal(principal, key); nsTArray<nsCString> keys = nsPermissionManager::GetAllKeysForPrincipal(principal); MOZ_ASSERT(keys.Length() >= 1); for (auto& key : keys) { EnsurePermissionsByKey(key); } #endif return NS_OK; Loading
extensions/cookie/nsPermissionManager.cpp +90 −58 Original line number Diff line number Diff line Loading @@ -176,6 +176,54 @@ GetNextSubDomainForHost(const nsACString& aHost) return subDomain; } // 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<nsIPrincipal> GetNextSubDomainPrincipal(nsIPrincipal* aPrincipal) { nsCOMPtr<nsIURI> uri; nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_FAILED(rv) || !uri) { return nullptr; } nsAutoCString host; rv = uri->GetHost(host); if (NS_FAILED(rv)) { return nullptr; } nsCString domain = GetNextSubDomainForHost(host); if (domain.IsEmpty()) { return nullptr; } // Create a new principal which is identical to the current one, but with the new host nsCOMPtr<nsIURI> newURI; rv = uri->Clone(getter_AddRefs(newURI)); if (NS_FAILED(rv)) { return nullptr; } rv = newURI->SetHost(domain); if (NS_FAILED(rv)) { return nullptr; } // Copy the attributes over mozilla::OriginAttributes attrs = aPrincipal->OriginAttributesRef(); // Disable userContext and firstParty isolation for permissions. attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID | mozilla::OriginAttributes::STRIP_FIRST_PARTY_DOMAIN); nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs); return principal.forget(); } class ClearOriginDataObserver final : public nsIObserver { ~ClearOriginDataObserver() {} Loading Loading @@ -2185,47 +2233,12 @@ nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal, // If aExactHostMatch wasn't true, we can check if the base domain has a permission entry. if (!aExactHostMatch) { nsCOMPtr<nsIURI> uri; nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_FAILED(rv)) { return nullptr; } nsAutoCString host; rv = uri->GetHost(host); if (NS_FAILED(rv)) { return nullptr; } nsCString domain = GetNextSubDomainForHost(host); if (domain.IsEmpty()) { return nullptr; } // Create a new principal which is identical to the current one, but with the new host nsCOMPtr<nsIURI> newURI; rv = uri->Clone(getter_AddRefs(newURI)); if (NS_FAILED(rv)) { return nullptr; } rv = newURI->SetHost(domain); if (NS_FAILED(rv)) { return nullptr; } // Copy the attributes over mozilla::OriginAttributes attrs = aPrincipal->OriginAttributesRef(); // Disable userContext and firstParty isolation for permissions. attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID | mozilla::OriginAttributes::STRIP_FIRST_PARTY_DOMAIN); nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs); GetNextSubDomainPrincipal(aPrincipal); if (principal) { return GetPermissionHashKey(principal, aType, aExactHostMatch); } } // No entry, really... return nullptr; Loading Loading @@ -3014,7 +3027,6 @@ nsPermissionManager::SetPermissionsWithKey(const nsACString& aPermissionKey, return NS_OK; } // XXX: Support file URIs here as well! /* static */ void nsPermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aKey) { Loading @@ -3027,31 +3039,51 @@ nsPermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aK // NOTE: We don't propagate the error here, instead we produce the default // "" permission key. This means that we can assign every principal a key, // even if the GetURI operation on that principal is not meaningful. aKey.Truncate(); return; } // If the URI isn't of one of the supported schemes, it has the "" permission // key. We can do an early return in that case. nsAutoCString scheme; uri->GetScheme(scheme); if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https") && !scheme.EqualsLiteral("ftp")) { rv = uri->GetScheme(scheme); if (NS_WARN_IF(NS_FAILED(rv))) { // NOTE: Produce the default "" key as a fallback. aKey.Truncate(); return; } // We key sets of permissions to be sent over IPC based on their eTLD+1, or in // the case where that isn't meaningful, on their IP address or spec. nsCOMPtr<nsIEffectiveTLDService> etldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); rv = etldService->GetBaseDomain(uri, 0, aKey); if (NS_FAILED(rv)) { rv = uri->GetHost(aKey); // URIs which have schemes other than http, https and ftp share the "" // permission key. if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https") || scheme.EqualsLiteral("ftp")) { rv = GetOriginFromPrincipal(aPrincipal, aKey); if (NS_SUCCEEDED(rv)) { return; } if (NS_FAILED(rv)) { rv = uri->GetSpec(aKey); } if (NS_FAILED(rv)) { // NOTE: Produce the default "" key as a fallback. aKey.Truncate(); return; } /* static */ nsTArray<nsCString> nsPermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) { MOZ_ASSERT(aPrincipal); nsTArray<nsCString> keys; nsCOMPtr<nsIPrincipal> prin = aPrincipal; while (prin) { // Add the key to the list nsCString* key = keys.AppendElement(); GetKeyForPrincipal(prin, *key); // Get the next subdomain principal and loop back around. prin = GetNextSubDomainPrincipal(prin); } MOZ_ASSERT(keys.Length() >= 1, "Every principal should have at least one key."); return keys; }
extensions/cookie/nsPermissionManager.h +17 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,23 @@ public: */ static void GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aPermissionKey); /** * See `nsIPermissionManager::GetPermissionsWithKey` for more info on * permission keys. * * Get all permissions keys which could correspond to the given principal. * This method, like GetKeyForPrincipal, is infallible and should always * produce at least one key. * * Unlike GetKeyForPrincipal, this method also gets the keys for base domains * of the given principal. All keys returned by this method must be avaliable * in the content process for a given URL to successfully have its permissions * checked in the `aExactHostMatch = false` situation. * * @param aPrincipal The Principal which the key is to be extracted from. */ static nsTArray<nsCString> GetAllKeysForPrincipal(nsIPrincipal* aPrincipal); private: virtual ~nsPermissionManager(); Loading