blob: 14aec5a9dde01f28ce664d2cfbdfe26ef1f8d708 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/net/profile_network_context_service.h"
#include <string>
#include <string_view>
#include "ash/constants/ash_features.h"
#include "base/base64.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/containers/flat_map.h"
#include "base/containers/to_vector.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/domain_reliability/service_factory.h"
#include "chrome/browser/first_party_sets/first_party_sets_policy_service.h"
#include "chrome/browser/first_party_sets/first_party_sets_policy_service_factory.h"
#include "chrome/browser/ip_protection/ip_protection_core_host.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
#include "chrome/browser/privacy_sandbox/tracking_protection_settings_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/sct_reporting_service.h"
#include "chrome/browser/ssl/sct_reporting_service_factory.h"
#include "chrome/browser/webid/federated_identity_permission_context.h"
#include "chrome/browser/webid/federated_identity_permission_context_factory.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/pref_names.h"
#include "components/certificate_transparency/pref_names.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/embedder_support/pref_names.h"
#include "components/embedder_support/switches.h"
#include "components/language/core/browser/language_prefs.h"
#include "components/language/core/browser/pref_names.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/permissions/features.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/first_party_sets_handler.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/url_constants.h"
#include "crypto/crypto_buildflags.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/features.h"
#include "net/cert/asn1_util.h"
#include "net/http/http_auth_preferences.h"
#include "net/http/http_util.h"
#include "net/net_buildflags.h"
#include "net/ssl/client_cert_store.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/cpp/cors/origin_access_list.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/first_party_sets_access_delegate.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/features.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/certificate_provider/certificate_provider.h"
#include "chrome/browser/certificate_provider/certificate_provider_service.h"
#include "chrome/browser/certificate_provider/certificate_provider_service_factory.h"
#include "chrome/browser/policy/networking/policy_cert_service.h"
#include "chrome/browser/policy/networking/policy_cert_service_factory.h"
#include "chromeos/components/kiosk/kiosk_utils.h"
#include "chromeos/constants/chromeos_features.h"
#include "net/cert/x509_util.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_switches.h"
#include "chrome/browser/ash/kcer/kcer_factory_ash.h"
#include "chrome/browser/ash/net/client_cert_store_ash.h"
#include "chrome/browser/ash/net/client_cert_store_kcer.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#endif
#if BUILDFLAG(USE_NSS_CERTS)
#include "chrome/browser/ui/crypto_module_delegate_nss.h"
#include "net/ssl/client_cert_store_nss.h"
#endif // BUILDFLAG(USE_NSS_CERTS)
#if BUILDFLAG(IS_WIN)
#include "net/ssl/client_cert_store_win.h"
#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_MAC)
#include "net/ssl/client_cert_store_mac.h"
#endif // BUILDFLAG(IS_MAC)
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/common/constants.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "base/check_is_test.h"
#include "chrome/browser/lacros/cert/cert_db_initializer_factory.h"
#include "chrome/browser/lacros/cert/client_cert_store_lacros.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chromeos/startup/browser_params_proxy.h"
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
#include "chrome/browser/enterprise/client_certificates/certificate_provisioning_service_factory.h"
#include "components/enterprise/client_certificates/core/certificate_provisioning_service.h"
#include "components/enterprise/client_certificates/core/client_certificates_service.h"
#include "components/enterprise/client_certificates/core/features.h"
#endif
#if BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
#include "chrome/browser/net/server_certificate_database.h" // nogncheck
#include "chrome/browser/net/server_certificate_database.pb.h" // nogncheck
#include "chrome/browser/net/server_certificate_database_service.h" // nogncheck
#include "chrome/browser/net/server_certificate_database_service_factory.h" // nogncheck
#endif
namespace {
bool* g_discard_domain_reliability_uploads_for_testing = nullptr;
const char kHttpCacheFinchExperimentGroups[] =
"profile_network_context_service.http_cache_finch_experiment_groups";
std::vector<std::string> TranslateStringArray(const base::Value::List& list) {
std::vector<std::string> strings;
for (const base::Value& value : list) {
DCHECK(value.is_string());
strings.push_back(value.GetString());
}
return strings;
}
std::string ComputeAcceptLanguageFromPref(const std::string& language_pref) {
std::string accept_languages_str =
net::HttpUtil::ExpandLanguageList(language_pref);
return net::HttpUtil::GenerateAcceptLanguageHeader(accept_languages_str);
}
// Tests allowing ambient authentication with default credentials based on the
// profile type.
bool IsAmbientAuthAllowedForProfile(Profile* profile) {
// Ambient authentication is always enabled for regular and system profiles.
// System profiles (used in profile picker) may require authentication to
// let user login.
if (profile->IsRegularProfile() || profile->IsSystemProfile())
return true;
// Non-primary OTR profiles are not used to create browser windows and are
// only technical means for a task that does not need to leave state after
// it's completed.
if (profile->IsOffTheRecord() && !profile->IsPrimaryOTRProfile())
return true;
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
DCHECK(local_state->FindPreference(
prefs::kAmbientAuthenticationInPrivateModesEnabled));
net::AmbientAuthAllowedProfileTypes type =
static_cast<net::AmbientAuthAllowedProfileTypes>(local_state->GetInteger(
prefs::kAmbientAuthenticationInPrivateModesEnabled));
if (profile->IsGuestSession()) {
return type == net::AmbientAuthAllowedProfileTypes::kGuestAndRegular ||
type == net::AmbientAuthAllowedProfileTypes::kAll;
} else if (profile->IsIncognitoProfile()) {
return type == net::AmbientAuthAllowedProfileTypes::kIncognitoAndRegular ||
type == net::AmbientAuthAllowedProfileTypes::kAll;
}
// Profile type not yet supported.
NOTREACHED_IN_MIGRATION();
return false;
}
void UpdateAntiAbuseSettings(Profile* profile) {
ContentSetting content_setting =
HostContentSettingsMapFactory::GetForProfile(profile)
->GetDefaultContentSetting(ContentSettingsType::ANTI_ABUSE, nullptr);
const bool block_trust_tokens = content_setting == CONTENT_SETTING_BLOCK;
profile->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()->SetBlockTrustTokens(
block_trust_tokens);
});
}
bool IsContentSettingsTypeEnabled(ContentSettingsType type) {
switch (type) {
case ContentSettingsType::STORAGE_ACCESS:
case ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS:
return true;
default:
return content_settings::CookieSettings::GetContentSettingsTypes()
.contains(type);
}
}
void UpdateCookieSettings(Profile* profile, ContentSettingsType type) {
if (!IsContentSettingsTypeEnabled(type)) {
return;
}
ContentSettingsForOneType settings;
if (type == ContentSettingsType::FEDERATED_IDENTITY_SHARING) {
// Note: FederatedIdentityPermissionContext also syncs the permissions
// directly, in order to avoid a race condition. (Namely,
// FederatedIdentityPermissionContext must guarantee that the permissions
// have propagated before it calls its callback. However, the syncing that
// occurs in this class is unsynchronized, so it would be racy to rely on
// this update finishing before calling the context's callback.) This
// unfortunately triggers a double-update here.
if (FederatedIdentityPermissionContext* fedcm_context =
FederatedIdentityPermissionContextFactory::GetForProfile(profile);
fedcm_context) {
settings = fedcm_context->GetSharingPermissionGrantsAsContentSettings();
}
} else {
settings = HostContentSettingsMapFactory::GetForProfile(profile)
->GetSettingsForOneType(type);
}
profile->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetCookieManagerForBrowserProcess()
->SetContentSettings(type, settings, base::NullCallback());
});
}
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
std::unique_ptr<net::ClientCertStore> GetWrappedCertStore(
Profile* profile,
std::unique_ptr<net::ClientCertStore> platform_store) {
if (!profile || !client_certificates::features::
IsManagedClientCertificateForUserEnabled()) {
return platform_store;
}
auto* provisioning_service =
client_certificates::CertificateProvisioningServiceFactory::GetForProfile(
profile);
if (!provisioning_service) {
return platform_store;
}
return client_certificates::ClientCertificatesService::Create(
provisioning_service, std::move(platform_store));
}
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
} // namespace
ProfileNetworkContextService::ProfileNetworkContextService(Profile* profile)
: profile_(profile), proxy_config_monitor_(profile) {
TRACE_EVENT0("startup", "ProfileNetworkContextService::ctor");
PrefService* profile_prefs = profile->GetPrefs();
quic_allowed_.Init(prefs::kQuicAllowed, profile_prefs,
base::BindRepeating(
&ProfileNetworkContextService::DisableQuicIfNotAllowed,
base::Unretained(this)));
pref_accept_language_.Init(
language::prefs::kAcceptLanguages, profile_prefs,
base::BindRepeating(&ProfileNetworkContextService::UpdateAcceptLanguage,
base::Unretained(this)));
enable_referrers_.Init(
prefs::kEnableReferrers, profile_prefs,
base::BindRepeating(&ProfileNetworkContextService::UpdateReferrersEnabled,
base::Unretained(this)));
cookie_settings_ = CookieSettingsFactory::GetForProfile(profile);
cookie_settings_observation_.Observe(cookie_settings_.get());
DisableQuicIfNotAllowed();
// Observe content settings so they can be synced to the network service.
HostContentSettingsMapFactory::GetForProfile(profile_)->AddObserver(this);
pref_change_registrar_.Init(profile_prefs);
// When any of the following CT preferences change, we schedule an update
// to aggregate the actual update using a |ct_policy_update_timer_|.
pref_change_registrar_.Add(
certificate_transparency::prefs::kCTExcludedHosts,
base::BindRepeating(&ProfileNetworkContextService::ScheduleUpdateCTPolicy,
base::Unretained(this)));
pref_change_registrar_.Add(
certificate_transparency::prefs::kCTExcludedSPKIs,
base::BindRepeating(&ProfileNetworkContextService::ScheduleUpdateCTPolicy,
base::Unretained(this)));
// When any of the following Certificate preferences change, we schedule an
// update to aggregate the actual update using a |cert_policy_update_timer_|.
base::RepeatingClosure schedule_update_cert_policy = base::BindRepeating(
&ProfileNetworkContextService::ScheduleUpdateCertificatePolicy,
base::Unretained(this));
pref_change_registrar_.Add(prefs::kCACertificates,
schedule_update_cert_policy);
pref_change_registrar_.Add(prefs::kCACertificatesWithConstraints,
schedule_update_cert_policy);
pref_change_registrar_.Add(prefs::kCADistrustedCertificates,
schedule_update_cert_policy);
pref_change_registrar_.Add(prefs::kCAHintCertificates,
schedule_update_cert_policy);
#if !BUILDFLAG(IS_CHROMEOS)
pref_change_registrar_.Add(prefs::kCAPlatformIntegrationEnabled,
schedule_update_cert_policy);
#endif
pref_change_registrar_.Add(
prefs::kGloballyScopeHTTPAuthCacheEnabled,
base::BindRepeating(&ProfileNetworkContextService::
UpdateSplitAuthCacheByNetworkIsolationKey,
base::Unretained(this)));
pref_change_registrar_.Add(
prefs::kCorsNonWildcardRequestHeadersSupport,
base::BindRepeating(&ProfileNetworkContextService::
UpdateCorsNonWildcardRequestHeadersSupport,
base::Unretained(this)));
#if BUILDFLAG(ENABLE_REPORTING)
if (base::FeatureList::IsEnabled(
net::features::kReportingApiEnableEnterpriseCookieIssues)) {
pref_change_registrar_.Add(
prefs::kReportingEndpoints,
base::BindRepeating(
&ProfileNetworkContextService::UpdateEnterpriseReportingEndpoints,
base::Unretained(this)));
}
#endif // BUILDFLAG(ENABLE_REPORTING)
}
ProfileNetworkContextService::~ProfileNetworkContextService() = default;
void ProfileNetworkContextService::ConfigureNetworkContextParams(
bool in_memory,
const base::FilePath& relative_partition_path,
network::mojom::NetworkContextParams* network_context_params,
cert_verifier::mojom::CertVerifierCreationParams*
cert_verifier_creation_params) {
ConfigureNetworkContextParamsInternal(in_memory, relative_partition_path,
network_context_params,
cert_verifier_creation_params);
if ((!in_memory && !profile_->IsOffTheRecord())) {
// TODO(jam): delete this code 1 year after Network Service shipped to all
// stable users, which would be after M83 branches.
base::FilePath base_cache_path;
chrome::GetUserCacheDirectory(GetPartitionPath(relative_partition_path),
&base_cache_path);
base::FilePath media_cache_path =
base_cache_path.Append(chrome::kMediaCacheDirname);
base::ThreadPool::PostTask(
FROM_HERE,
{base::TaskPriority::BEST_EFFORT, base::MayBlock(),
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::GetDeletePathRecursivelyCallback(media_cache_path));
}
}
void ProfileNetworkContextService::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(embedder_support::kAlternateErrorPagesEnabled,
true);
registry->RegisterBooleanPref(prefs::kQuicAllowed, true);
registry->RegisterBooleanPref(prefs::kGloballyScopeHTTPAuthCacheEnabled,
false);
registry->RegisterListPref(prefs::kHSTSPolicyBypassList);
registry->RegisterListPref(prefs::kCACertificates);
registry->RegisterListPref(prefs::kCACertificatesWithConstraints);
registry->RegisterListPref(prefs::kCADistrustedCertificates);
registry->RegisterListPref(prefs::kCAHintCertificates);
#if !BUILDFLAG(IS_CHROMEOS)
// Include user added platform certs by default.
registry->RegisterBooleanPref(prefs::kCAPlatformIntegrationEnabled, true);
#endif
}
// static
void ProfileNetworkContextService::RegisterLocalStatePrefs(
PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(
prefs::kAmbientAuthenticationInPrivateModesEnabled,
static_cast<int>(net::AmbientAuthAllowedProfileTypes::kRegularOnly));
// For information about whether to reset the HTTP Cache or not, defaults
// to the empty string, which does not prompt a reset.
registry->RegisterStringPref(kHttpCacheFinchExperimentGroups, "");
}
void ProfileNetworkContextService::DisableQuicIfNotAllowed() {
if (!quic_allowed_.IsManaged())
return;
// If QUIC is allowed, do nothing (re-enabling QUIC is not supported).
if (quic_allowed_.GetValue())
return;
g_browser_process->system_network_context_manager()->DisableQuic();
}
void ProfileNetworkContextService::UpdateAcceptLanguage() {
const std::string accept_language = ComputeAcceptLanguage();
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()->SetAcceptLanguage(
accept_language);
});
}
void ProfileNetworkContextService::OnThirdPartyCookieBlockingChanged(
bool block_third_party_cookies) {
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetCookieManagerForBrowserProcess()
->BlockThirdPartyCookies(block_third_party_cookies);
});
}
void ProfileNetworkContextService::OnMitigationsEnabledFor3pcdChanged(
bool enable) {
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetCookieManagerForBrowserProcess()
->SetMitigationsEnabledFor3pcd(enable);
});
}
void ProfileNetworkContextService::OnTrackingProtectionEnabledFor3pcdChanged(
bool enable) {
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetCookieManagerForBrowserProcess()
->SetTrackingProtectionEnabledFor3pcd(enable);
});
}
std::string ProfileNetworkContextService::ComputeAcceptLanguage() const {
// TODO:(https://crbug.com/40224802) Return only single language without
// expanding the language list if the DisableReduceAcceptLanguage deprecation
// trial ends.
if (profile_->IsOffTheRecord()) {
// In incognito mode return only the first language.
return ComputeAcceptLanguageFromPref(
language::GetFirstLanguage(pref_accept_language_.GetValue()));
}
return ComputeAcceptLanguageFromPref(pref_accept_language_.GetValue());
}
void ProfileNetworkContextService::UpdateReferrersEnabled() {
const bool enable_referrers = enable_referrers_.GetValue();
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()->SetEnableReferrers(
enable_referrers);
});
}
network::mojom::CTPolicyPtr ProfileNetworkContextService::GetCTPolicy() {
auto* prefs = profile_->GetPrefs();
const base::Value::List& ct_excluded =
prefs->GetList(certificate_transparency::prefs::kCTExcludedHosts);
const base::Value::List& ct_excluded_spkis =
prefs->GetList(certificate_transparency::prefs::kCTExcludedSPKIs);
std::vector<std::string> excluded(TranslateStringArray(ct_excluded));
std::vector<std::string> excluded_spkis(
TranslateStringArray(ct_excluded_spkis));
return network::mojom::CTPolicy::New(std::move(excluded),
std::move(excluded_spkis));
}
void ProfileNetworkContextService::UpdateCTPolicyForContexts(
const std::vector<network::mojom::NetworkContext*>& contexts) {
for (auto* context : contexts) {
context->SetCTPolicy(GetCTPolicy());
}
}
void ProfileNetworkContextService::UpdateCTPolicy() {
std::vector<network::mojom::NetworkContext*> contexts;
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
contexts.push_back(storage_partition->GetNetworkContext());
});
UpdateCTPolicyForContexts(contexts);
}
void ProfileNetworkContextService::ScheduleUpdateCTPolicy() {
ct_policy_update_timer_.Start(FROM_HERE, base::Seconds(0), this,
&ProfileNetworkContextService::UpdateCTPolicy);
}
cert_verifier::mojom::AdditionalCertificatesPtr
ProfileNetworkContextService::GetCertificatePolicy(
const base::FilePath& storage_partition_path) {
auto* prefs = profile_->GetPrefs();
auto additional_certificates =
cert_verifier::mojom::AdditionalCertificates::New();
#if BUILDFLAG(IS_CHROMEOS)
const policy::PolicyCertService* policy_cert_service =
policy::PolicyCertServiceFactory::GetForProfile(profile_);
if (policy_cert_service) {
net::CertificateList all_certificates;
net::CertificateList trust_anchors;
policy_cert_service->GetPolicyCertificatesForStoragePartition(
storage_partition_path, &all_certificates, &trust_anchors);
for (const auto& cert : all_certificates) {
base::span<const uint8_t> cert_bytes =
net::x509_util::CryptoBufferAsSpan(cert->cert_buffer());
additional_certificates->all_certificates.push_back(
std::vector<uint8_t>(cert_bytes.begin(), cert_bytes.end()));
}
for (const auto& cert : trust_anchors) {
base::span<const uint8_t> cert_bytes =
net::x509_util::CryptoBufferAsSpan(cert->cert_buffer());
additional_certificates->trust_anchors.push_back(
std::vector<uint8_t>(cert_bytes.begin(), cert_bytes.end()));
}
}
#endif // BUILDFLAG(IS_CHROMEOS)
for (const base::Value& cert_b64 :
prefs->GetList(prefs::kCAHintCertificates)) {
std::optional<std::vector<uint8_t>> decoded_opt =
base::Base64Decode(cert_b64.GetString());
if (decoded_opt.has_value()) {
additional_certificates->all_certificates.push_back(
std::move(*decoded_opt));
}
}
for (const base::Value& cert_b64 : prefs->GetList(prefs::kCACertificates)) {
std::optional<std::vector<uint8_t>> decoded_opt =
base::Base64Decode(cert_b64.GetString());
if (decoded_opt.has_value()) {
additional_certificates->trust_anchors_with_enforced_constraints
.push_back(std::move(*decoded_opt));
}
}
// Add trust anchors with constraints outside the cert
for (const base::Value& cert_with_constraints :
prefs->GetList(prefs::kCACertificatesWithConstraints)) {
const base::Value::Dict* cert_with_constraints_dict =
cert_with_constraints.GetIfDict();
if (!cert_with_constraints_dict) {
continue;
}
const std::string* cert_b64 =
cert_with_constraints_dict->FindString("certificate");
const base::Value::Dict* constraints_dict =
cert_with_constraints_dict->FindDict("constraints");
if (!constraints_dict) {
continue;
}
const base::Value::List* permitted_cidrs =
constraints_dict->FindList("permitted_cidrs");
const base::Value::List* permitted_dns_names =
constraints_dict->FindList("permitted_dns_names");
// Need to have a cert, and at least one set of restrictions.
if (!cert_b64) {
continue;
}
if (!((permitted_cidrs && permitted_cidrs->size() > 0) ||
(permitted_dns_names && permitted_dns_names->size() > 0))) {
continue;
}
std::optional<std::vector<uint8_t>> decoded_cert_opt =
base::Base64Decode(*cert_b64);
if (!decoded_cert_opt.has_value()) {
// Cert isn't valid b64, continue.
continue;
}
bool invalid_constraint = false;
auto cert_with_constraints_mojo =
cert_verifier::mojom::CertWithConstraints::New();
cert_with_constraints_mojo->certificate = std::move(*decoded_cert_opt);
if (permitted_dns_names) {
for (const base::Value& dns_name : *permitted_dns_names) {
if (dns_name.is_string() && base::IsStringASCII(dns_name.GetString()) &&
dns_name.GetString().length() <= 255) {
cert_with_constraints_mojo->permitted_dns_names.push_back(
dns_name.GetString());
} else {
invalid_constraint = true;
break;
}
}
}
if (invalid_constraint) {
continue;
}
if (permitted_cidrs) {
for (const base::Value& cidr : *permitted_cidrs) {
if (!cidr.is_string()) {
invalid_constraint = true;
break;
}
net::IPAddress parsed_cidr;
net::IPAddress mask;
size_t prefix_length;
if (!net::ParseCIDRBlock(cidr.GetString(), &parsed_cidr,
&prefix_length)) {
// Don't add trust for cert if CIDR block doesn't parse.
invalid_constraint = true;
break;
}
if (parsed_cidr.IsIPv4()) {
if (!net::IPAddress::CreateIPv4Mask(&mask, prefix_length)) {
// Error in mask creation.
invalid_constraint = true;
break;
}
} else if (parsed_cidr.IsIPv6()) {
if (!net::IPAddress::CreateIPv6Mask(&mask, prefix_length)) {
// Error in mask creation.
invalid_constraint = true;
break;
}
} else {
// Somehow got an IP address that isn't ipv4 or ipv6?
invalid_constraint = true;
break;
}
cert_with_constraints_mojo->permitted_cidrs.push_back(
cert_verifier::mojom::CIDR::New(/*ip=*/parsed_cidr, /*mask=*/mask));
}
}
if (invalid_constraint) {
continue;
}
additional_certificates->trust_anchors_with_additional_constraints
.push_back(std::move(cert_with_constraints_mojo));
}
for (const base::Value& cert_b64 :
prefs->GetList(prefs::kCADistrustedCertificates)) {
std::string decoded;
if (!base::Base64Decode(cert_b64.GetString(), &decoded)) {
continue;
}
std::string_view spki_piece;
bool success = net::asn1::ExtractSPKIFromDERCert(decoded, &spki_piece);
if (success) {
additional_certificates->distrusted_spkis.push_back(
base::ToVector(base::as_byte_span(spki_piece)));
}
}
#if !BUILDFLAG(IS_CHROMEOS)
additional_certificates->include_system_trust_store =
prefs->GetBoolean(prefs::kCAPlatformIntegrationEnabled);
#endif
return additional_certificates;
}
void ProfileNetworkContextService::UpdateAdditionalCertificates() {
#if BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
if (base::FeatureList::IsEnabled(features::kEnableCertManagementUIV2Write)) {
net::ServerCertificateDatabaseService* cert_db_service =
net::ServerCertificateDatabaseServiceFactory::GetForBrowserContext(
profile_);
cert_db_service->GetAllCertificates(
base::BindOnce(&ProfileNetworkContextService::
UpdateAdditionalCertificatesWithUserAddedCerts,
base::Unretained(this)));
} else {
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetCertVerifierServiceUpdater()
->UpdateAdditionalCertificates(
GetCertificatePolicy(storage_partition->GetPath()));
});
}
#else
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetCertVerifierServiceUpdater()
->UpdateAdditionalCertificates(
GetCertificatePolicy(storage_partition->GetPath()));
});
#endif
}
#if BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
void ProfileNetworkContextService::
UpdateAdditionalCertificatesWithUserAddedCerts(
std::vector<net::ServerCertificateDatabase::CertInformation>
cert_infos) {
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
cert_verifier::mojom::AdditionalCertificatesPtr additional_certs =
GetCertificatePolicy(storage_partition->GetPath());
for (const auto& cert_info : cert_infos) {
std::optional<bssl::CertificateTrustType> trust =
net::ServerCertificateDatabase::GetUserCertificateTrust(
cert_info);
if (!trust) {
continue;
}
switch (trust.value()) {
case bssl::CertificateTrustType::UNSPECIFIED:
additional_certs->all_certificates.push_back(cert_info.der_cert);
break;
case bssl::CertificateTrustType::DISTRUSTED: {
std::string_view spki_piece;
bool success = net::asn1::ExtractSPKIFromDERCert(
base::as_string_view(cert_info.der_cert), &spki_piece);
if (success) {
additional_certs->distrusted_spkis.push_back(
base::ToVector(base::as_byte_span(spki_piece)));
}
break;
}
case bssl::CertificateTrustType::TRUSTED_ANCHOR:
// TODO(crbug.com/40928765): add additional constraints.
additional_certs->trust_anchors_with_enforced_constraints
.push_back(cert_info.der_cert);
break;
case bssl::CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF:
case bssl::CertificateTrustType::TRUSTED_LEAF:
// TODO(crbug.com/40928765): There's currently no place to pass
// this through mojo to the cert verifier; add this to the mojo
// message after this becomes possible.
continue;
}
}
storage_partition->GetCertVerifierServiceUpdater()
->UpdateAdditionalCertificates(std::move(additional_certs));
});
}
#endif // BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
void ProfileNetworkContextService::ScheduleUpdateCertificatePolicy() {
cert_policy_update_timer_.Start(
FROM_HERE, base::Seconds(0), this,
&ProfileNetworkContextService::UpdateAdditionalCertificates);
}
ProfileNetworkContextService::CertificatePoliciesForView::
CertificatePoliciesForView() = default;
ProfileNetworkContextService::CertificatePoliciesForView::
~CertificatePoliciesForView() = default;
ProfileNetworkContextService::CertificatePoliciesForView::
CertificatePoliciesForView(CertificatePoliciesForView&&) = default;
ProfileNetworkContextService::CertificatePoliciesForView&
ProfileNetworkContextService::CertificatePoliciesForView::operator=(
CertificatePoliciesForView&& other) = default;
ProfileNetworkContextService::CertificatePoliciesForView
ProfileNetworkContextService::GetCertificatePolicyForView() {
CertificatePoliciesForView policies;
policies.certificate_policies =
GetCertificatePolicy(profile_->GetDefaultStoragePartition()->GetPath());
auto* prefs = profile_->GetPrefs();
for (const base::Value& cert_b64 :
prefs->GetList(prefs::kCADistrustedCertificates)) {
std::optional<std::vector<uint8_t>> decoded_opt =
base::Base64Decode(cert_b64.GetString());
if (decoded_opt.has_value()) {
policies.full_distrusted_certs.push_back(std::move(*decoded_opt));
}
}
#if !BUILDFLAG(IS_CHROMEOS)
policies.is_include_system_trust_store_managed =
prefs->FindPreference(prefs::kCAPlatformIntegrationEnabled)->IsManaged();
#endif
return policies;
}
bool ProfileNetworkContextService::ShouldSplitAuthCacheByNetworkIsolationKey()
const {
if (profile_->GetPrefs()->GetBoolean(
prefs::kGloballyScopeHTTPAuthCacheEnabled))
return false;
return base::FeatureList::IsEnabled(
network::features::kSplitAuthCacheByNetworkIsolationKey);
}
void ProfileNetworkContextService::UpdateSplitAuthCacheByNetworkIsolationKey() {
const bool split_auth_cache_by_network_isolation_key =
ShouldSplitAuthCacheByNetworkIsolationKey();
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()
->SetSplitAuthCacheByNetworkAnonymizationKey(
split_auth_cache_by_network_isolation_key);
});
}
void ProfileNetworkContextService::
UpdateCorsNonWildcardRequestHeadersSupport() {
const bool value = profile_->GetPrefs()->GetBoolean(
prefs::kCorsNonWildcardRequestHeadersSupport);
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()
->SetCorsNonWildcardRequestHeadersSupport(value);
});
}
#if BUILDFLAG(ENABLE_REPORTING)
base::flat_map<std::string, GURL>
ProfileNetworkContextService::GetEnterpriseReportingEndpoints() const {
using FlatMap = base::flat_map<std::string, GURL>;
// Create the underlying container first to allow sorting to
// be done in a single pass.
FlatMap::container_type pairs;
const base::Value::Dict& pref_dict =
profile_->GetPrefs()->GetDict(prefs::kReportingEndpoints);
pairs.reserve(pref_dict.size());
// The iterator for base::Value::Dict returns a temporary value when
// dereferenced, so a const reference is not used below.
for (const auto [endpoint_name, endpoint_url] : pref_dict) {
GURL endpoint(endpoint_url.GetString());
if (endpoint.is_valid() && endpoint.SchemeIsCryptographic()) {
pairs.emplace_back(endpoint_name, std::move(endpoint));
}
}
return FlatMap(std::move(pairs));
}
void ProfileNetworkContextService::UpdateEnterpriseReportingEndpoints() {
base::flat_map<std::string, GURL> endpoints =
GetEnterpriseReportingEndpoints();
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()->SetEnterpriseReportingEndpoints(
endpoints);
});
}
#endif
// static
network::mojom::CookieManagerParamsPtr
ProfileNetworkContextService::CreateCookieManagerParams(
Profile* profile,
const content_settings::CookieSettings& cookie_settings) {
auto out = network::mojom::CookieManagerParams::New();
out->block_third_party_cookies =
cookie_settings.ShouldBlockThirdPartyCookies();
// This allows cookies to be sent on https requests from chrome:// pages,
// ignoring SameSite attribute rules. For example, this is needed for browser
// UI to interact with SameSite cookies on accounts.google.com, which is used
// for displaying a list of available accounts on the NTP
// (chrome://new-tab-page), etc.
out->secure_origin_cookies_allowed_schemes.push_back(
content::kChromeUIScheme);
#if BUILDFLAG(ENABLE_EXTENSIONS)
// TODO(chlily): To be consistent with the content_settings version of
// CookieSettings, we should probably also add kExtensionScheme to the list of
// matching_scheme_cookies_allowed_schemes.
out->third_party_cookies_allowed_schemes.push_back(
extensions::kExtensionScheme);
out->third_party_cookies_allowed_schemes.push_back(
content::kChromeDevToolsScheme);
#endif
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(profile);
for (auto type :
content_settings::CookieSettings::GetContentSettingsTypes()) {
if (!IsContentSettingsTypeEnabled(type)) {
continue;
}
if (type == ContentSettingsType::FEDERATED_IDENTITY_SHARING) {
if (FederatedIdentityPermissionContext* fedcm_context =
FederatedIdentityPermissionContextFactory::GetForProfile(profile);
fedcm_context) {
out->content_settings[type] =
fedcm_context->GetSharingPermissionGrantsAsContentSettings();
} else {
out->content_settings[type] = ContentSettingsForOneType();
}
} else {
out->content_settings[type] =
host_content_settings_map->GetSettingsForOneType(type);
}
}
out->cookie_access_delegate_type =
network::mojom::CookieAccessDelegateType::USE_CONTENT_SETTINGS;
out->mitigations_enabled_for_3pcd =
cookie_settings.MitigationsEnabledFor3pcd();
out->tracking_protection_enabled_for_3pcd =
TrackingProtectionSettingsFactory::GetForProfile(profile)
->IsTrackingProtection3pcdEnabled();
return out;
}
void ProfileNetworkContextService::FlushCachedClientCertIfNeeded(
const net::HostPortPair& host,
const scoped_refptr<net::X509Certificate>& certificate) {
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()->FlushCachedClientCertIfNeeded(
host, certificate);
});
}
void ProfileNetworkContextService::FlushMatchingCachedClientCert(
const scoped_refptr<net::X509Certificate>& certificate) {
profile_->ForEachLoadedStoragePartition(
[&](content::StoragePartition* storage_partition) {
storage_partition->GetNetworkContext()->FlushMatchingCachedClientCert(
certificate);
});
}
void ProfileNetworkContextService::FlushProxyConfigMonitorForTesting() {
proxy_config_monitor_.FlushForTesting();
}
void ProfileNetworkContextService::SetDiscardDomainReliabilityUploadsForTesting(
bool value) {
g_discard_domain_reliability_uploads_for_testing = new bool(value);
}
std::unique_ptr<net::ClientCertStore>
ProfileNetworkContextService::CreateClientCertStore() {
if (!client_cert_store_factory_.is_null())
return client_cert_store_factory_.Run();
#if BUILDFLAG(IS_CHROMEOS)
chromeos::CertificateProviderService* cert_provider_service =
chromeos::CertificateProviderServiceFactory::GetForBrowserContext(
profile_);
std::unique_ptr<chromeos::CertificateProvider> certificate_provider;
if (cert_provider_service) {
certificate_provider = cert_provider_service->CreateCertificateProvider();
}
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
bool use_system_key_slot = false;
// Enable client certificates for the Chrome OS sign-in frame, if this feature
// is not disabled by a flag.
// Note that while this applies to the whole sign-in profile / lock screen
// profile, client certificates will only be selected for the StoragePartition
// currently used in the sign-in frame (see SigninPartitionManager).
if (ash::switches::IsSigninFrameClientCertsEnabled() &&
(ash::ProfileHelper::IsSigninProfile(profile_) ||
ash::ProfileHelper::IsLockScreenProfile(profile_))) {
use_system_key_slot = true;
}
if (ash::features::ShouldUseKcerClientCertStore()) {
return std::make_unique<ash::ClientCertStoreKcer>(
std::move(certificate_provider),
kcer::KcerFactoryAsh::GetKcer(profile_));
} else {
std::string username_hash;
const user_manager::User* user =
ash::ProfileHelper::Get()->GetUserByProfile(profile_);
if (user && !user->username_hash().empty()) {
username_hash = user->username_hash();
// Use the device-wide system key slot only if the user is affiliated on
// the device.
if (user->IsAffiliated()) {
use_system_key_slot = true;
}
}
return std::make_unique<ash::ClientCertStoreAsh>(
std::move(certificate_provider), use_system_key_slot, username_hash,
base::BindRepeating(&CreateCryptoModuleBlockingPasswordDelegate,
kCryptoModulePasswordClientAuth));
}
#elif BUILDFLAG(USE_NSS_CERTS)
std::unique_ptr<net::ClientCertStore> store =
std::make_unique<net::ClientCertStoreNSS>(
base::BindRepeating(&CreateCryptoModuleBlockingPasswordDelegate,
kCryptoModulePasswordClientAuth));
#if BUILDFLAG(IS_CHROMEOS_LACROS)
if (!Profile::FromBrowserContext(
GetBrowserContextRedirectedInIncognito(profile_))
->IsMainProfile()) {
// TODO(crbug.com/40156976): At the moment client certs are only enabled for
// the main profile and its incognito profile (similarly to how it worked in
// Ash-Chrome). Return some cert store for secondary profiles in
// Lacros-Chrome when certs are supported there.
return nullptr;
}
CertDbInitializer* cert_db_initializer =
CertDbInitializerFactory::GetForBrowserContext(profile_);
store = std::make_unique<ClientCertStoreLacros>(
std::move(certificate_provider), cert_db_initializer, std::move(store));
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
#if BUILDFLAG(IS_LINUX)
return GetWrappedCertStore(profile_, std::move(store));
#else
return store;
#endif // BUILDFLAG(IS_LINUX)
#elif BUILDFLAG(IS_WIN)
return GetWrappedCertStore(profile_,
std::make_unique<net::ClientCertStoreWin>());
#elif BUILDFLAG(IS_MAC)
return GetWrappedCertStore(profile_,
std::make_unique<net::ClientCertStoreMac>());
#elif BUILDFLAG(IS_ANDROID)
// Android does not use the ClientCertStore infrastructure. On Android client
// cert matching is done by the OS as part of the call to show the cert
// selection dialog.
return nullptr;
#else
#error Unknown platform.
#endif
}
bool GetHttpCacheBackendResetParam(PrefService* local_state) {
// Get the field trial groups. If the server cannot be reached, then
// this corresponds to "None" for each experiment.
base::FieldTrial* field_trial = base::FeatureList::GetFieldTrial(
net::features::kSplitCacheByNetworkIsolationKey);
std::string current_field_trial_status =
(field_trial ? field_trial->group_name() : "None");
// This used to be used for keying on main frame only vs main frame +
// innermost frame, but the feature was removed, and now it's always keyed on
// both.
current_field_trial_status += " None";
// This used to be for keying on scheme + eTLD+1 vs origin, but the trial was
// removed, and now it's always keyed on eTLD+1. Still keeping a third "None"
// to avoid resetting the disk cache.
current_field_trial_status += " None ";
field_trial = base::FeatureList::GetFieldTrial(
net::features::kSplitCacheByIncludeCredentials);
current_field_trial_status +=
(field_trial ? field_trial->group_name() : "None");
// For the HTTP Cache keying experiments, if a flag indicates that the user is
// in an experiment group, modify `current_field_trial_status` to ensure that
// the cache gets cleared. If the user is not a part of the experiment, don't
// make any changes so as not to invalidate the existing cache.
if (base::FeatureList::IsEnabled(
net::features::kSplitCacheByCrossSiteMainFrameNavigationBoolean)) {
current_field_trial_status += " 20240814-CrossSiteNavBool";
} else if (base::FeatureList::IsEnabled(
net::features::kSplitCacheByMainFrameNavigationInitiator)) {
current_field_trial_status += " 20240814-MainFrameNavigationInitiator";
} else if (base::FeatureList::IsEnabled(
net::features::kSplitCacheByNavigationInitiator)) {
current_field_trial_status += " 20240814-NavigationInitiator";
} else if (base::FeatureList::IsEnabled(
net::features::kHttpCacheKeyingExperimentControlGroup2024)) {
current_field_trial_status += " 20240814-ExperimentControlGroup";
}
std::string previous_field_trial_status =
local_state->GetString(kHttpCacheFinchExperimentGroups);
local_state->SetString(kHttpCacheFinchExperimentGroups,
current_field_trial_status);
return !previous_field_trial_status.empty() &&
current_field_trial_status != previous_field_trial_status;
}
void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
bool in_memory,
const base::FilePath& relative_partition_path,
network::mojom::NetworkContextParams* network_context_params,
cert_verifier::mojom::CertVerifierCreationParams*
cert_verifier_creation_params) {
TRACE_EVENT0(
"startup",
"ProfileNetworkContextService::ConfigureNetworkContextParamsInternal");
if (profile_->IsOffTheRecord())
in_memory = true;
base::FilePath path(GetPartitionPath(relative_partition_path));
g_browser_process->system_network_context_manager()
->ConfigureDefaultNetworkContextParams(network_context_params);
network_context_params->enable_zstd =
base::FeatureList::IsEnabled(net::features::kZstdContentEncoding) &&
g_browser_process->local_state()->GetBoolean(
prefs::kZstdContentEncodingEnabled);
network_context_params->accept_language = ComputeAcceptLanguage();
network_context_params->enable_referrers = enable_referrers_.GetValue();
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(embedder_support::kShortReportingDelay)) {
network_context_params->reporting_delivery_interval =
base::Milliseconds(100);
}
// Always enable the HTTP cache.
network_context_params->http_cache_enabled = true;
network_context_params->http_auth_static_network_context_params =
network::mojom::HttpAuthStaticNetworkContextParams::New();
if (IsAmbientAuthAllowedForProfile(profile_)) {
network_context_params->http_auth_static_network_context_params
->allow_default_credentials =
net::HttpAuthPreferences::ALLOW_DEFAULT_CREDENTIALS;
} else {
network_context_params->http_auth_static_network_context_params
->allow_default_credentials =
net::HttpAuthPreferences::DISALLOW_DEFAULT_CREDENTIALS;
}
network_context_params->cookie_manager_params =
CreateCookieManagerParams(profile_, *cookie_settings_);
// Configure on-disk storage for non-OTR profiles. OTR profiles just use
// default behavior (in memory storage, default sizes).
if (!in_memory) {
PrefService* local_state = g_browser_process->local_state();
// Configure the HTTP cache path and size.
base::FilePath base_cache_path;
chrome::GetUserCacheDirectory(path, &base_cache_path);
base::FilePath disk_cache_dir =
local_state->GetFilePath(prefs::kDiskCacheDir);
if (!disk_cache_dir.empty())
base_cache_path = disk_cache_dir.Append(base_cache_path.BaseName());
const int disk_cache_size = local_state->GetInteger(prefs::kDiskCacheSize);
network_context_params->http_cache_max_size = disk_cache_size;
network_context_params->shared_dictionary_cache_max_size = disk_cache_size;
network_context_params->file_paths =
::network::mojom::NetworkContextFilePaths::New();
network_context_params->file_paths->http_cache_directory =
base_cache_path.Append(chrome::kCacheDirname);
network_context_params->file_paths->data_directory =
path.Append(chrome::kNetworkDataDirname);
network_context_params->file_paths->unsandboxed_data_path = path;
network_context_params->file_paths->trigger_migration =
base::FeatureList::IsEnabled(features::kTriggerNetworkDataMigration);
// Currently this just contains HttpServerProperties, but that will likely
// change.
network_context_params->file_paths->http_server_properties_file_name =
base::FilePath(chrome::kNetworkPersistentStateFilename);
network_context_params->file_paths->cookie_database_name =
base::FilePath(chrome::kCookieFilename);
#if BUILDFLAG(IS_WIN)
// If this feature is enabled, then the cookie database used by this profile
// will be locked for exclusive access by sqlite3 implementation in the
// network service.
network_context_params->enable_locking_cookie_database =
base::FeatureList::IsEnabled(features::kLockProfileCookieDatabase);
#endif // BUILDFLAG(IS_WIN)
g_browser_process->system_network_context_manager()
->AddCookieEncryptionManagerToNetworkContextParams(
network_context_params);
network_context_params->file_paths->trust_token_database_name =
base::FilePath(chrome::kTrustTokenFilename);
#if BUILDFLAG(ENABLE_REPORTING)
network_context_params->file_paths->reporting_and_nel_store_database_name =
base::FilePath(chrome::kReportingAndNelStoreFilename);
if (base::FeatureList::IsEnabled(
net::features::kReportingApiEnableEnterpriseCookieIssues)) {
network_context_params->enterprise_reporting_endpoints =
GetEnterpriseReportingEndpoints();
}
#endif // BUILDFLAG(ENABLE_REPORTING)
if (relative_partition_path.empty()) { // This is the main partition.
network_context_params->restore_old_session_cookies =
profile_->ShouldRestoreOldSessionCookies();
network_context_params->persist_session_cookies =
profile_->ShouldPersistSessionCookies();
} else {
// Copy behavior of ProfileImplIOData::InitializeAppRequestContext.
network_context_params->restore_old_session_cookies = false;
network_context_params->persist_session_cookies = false;
}
network_context_params->file_paths->transport_security_persister_file_name =
base::FilePath(chrome::kTransportSecurityPersisterFilename);
network_context_params->file_paths->sct_auditing_pending_reports_file_name =
base::FilePath(chrome::kSCTAuditingPendingReportsFileName);
}
const base::Value::List& hsts_policy_bypass_list =
profile_->GetPrefs()->GetList(prefs::kHSTSPolicyBypassList);
for (const auto& value : hsts_policy_bypass_list) {
const std::string* string_value = value.GetIfString();
if (!string_value)
continue;
network_context_params->hsts_policy_bypass_list.push_back(*string_value);
}
proxy_config_monitor_.AddToNetworkContextParams(network_context_params);
network_context_params->enable_certificate_reporting = true;
SCTReportingService* sct_reporting_service =
SCTReportingServiceFactory::GetForBrowserContext(profile_);
if (sct_reporting_service) {
network_context_params->sct_auditing_mode =
sct_reporting_service->GetReportingMode();
} else {
network_context_params->sct_auditing_mode =
network::mojom::SCTAuditingMode::kDisabled;
}
network_context_params->ct_policy = GetCTPolicy();
if (domain_reliability::ShouldCreateService()) {
network_context_params->enable_domain_reliability = true;
network_context_params->domain_reliability_upload_reporter =
domain_reliability::kUploadReporterString;
network_context_params->discard_domain_reliablity_uploads =
g_discard_domain_reliability_uploads_for_testing
? *g_discard_domain_reliability_uploads_for_testing
: !g_browser_process->local_state()->GetBoolean(
metrics::prefs::kMetricsReportingEnabled);
}
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// Configure cert verifier to use the same software NSS database as Chrome is
// currently using (secondary profiles don't have their own databases at the
// moment).
cert_verifier_creation_params->nss_full_path.reset();
if (profile_->IsMainProfile()) {
const crosapi::mojom::DefaultPathsPtr& default_paths =
chromeos::BrowserParamsProxy::Get()->DefaultPaths();
// `default_paths` can be nullptr in tests.
if (!default_paths) {
CHECK_IS_TEST();
}
// Populating `nss_full_path` will make cert verifier load
// and use the corresponding NSS public slot. Kiosk sessions don't have
// the UI that could result in interactions with the public slot. Kiosk
// users are also not owner users and can't have the owner key in the
// public slot. Leaving it empty will make cert verifier ignore the
// public slot. This is done mainly because Chrome sometimes fails to
// load the public slot and has to crash because of that.
if (default_paths && default_paths->user_nss_database.has_value() &&
!chromeos::IsKioskSession()) {
cert_verifier_creation_params->nss_full_path =
default_paths->user_nss_database.value();
}
}
policy::PolicyCertServiceFactory::CreateAndStartObservingForProfile(profile_);
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
bool profile_supports_policy_certs = false;
if (ash::ProfileHelper::IsSigninProfile(profile_) ||
ash::ProfileHelper::IsLockScreenProfile(profile_)) {
profile_supports_policy_certs = true;
}
user_manager::UserManager* user_manager = user_manager::UserManager::Get();
if (user_manager) {
const user_manager::User* user =
ash::ProfileHelper::Get()->GetUserByProfile(profile_);
// No need to initialize NSS for users with empty username hash:
// Getters for a user's NSS slots always return NULL slot if the user's
// username hash is empty, even when the NSS is not initialized for the
// user.
if (user && !user->username_hash().empty()) {
// Populating `username_hash` and `nss_path` will make cert verifier load
// and use the corresponding NSS public slot. Kiosk sessions don't have
// the UI that could result in interactions with the public slot. Kiosk
// users are also not owner users and can't have the owner key in the
// public slot. Leaving them empty will make cert verifier ignore the
// public slot. This is done mainly because Chrome sometimes fails to
// load the public slot and has to crash because of that.
if (!chromeos::IsKioskSession()) {
cert_verifier_creation_params->username_hash = user->username_hash();
cert_verifier_creation_params->nss_path = profile_->GetPath();
}
profile_supports_policy_certs = true;
}
}
if (profile_supports_policy_certs) {
policy::PolicyCertServiceFactory::CreateAndStartObservingForProfile(
profile_);
}
#endif
// TODO(crbug.com/40928765): check to see if IsManaged() ensures the pref
// isn't set in user profiles, or if that does something else. If that's true,
// add an isManaged() check here.
#if BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
if (base::FeatureList::IsEnabled(features::kEnableCertManagementUIV2Write)) {
cert_verifier_creation_params->wait_for_update = true;
UpdateAdditionalCertificates();
} else {
cert_verifier_creation_params->initial_additional_certificates =
GetCertificatePolicy(GetPartitionPath(relative_partition_path));
}
#else
cert_verifier_creation_params->initial_additional_certificates =
GetCertificatePolicy(GetPartitionPath(relative_partition_path));
#endif // BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
#if BUILDFLAG(IS_CHROMEOS)
// Disable idle sockets close on memory pressure if configured by finch or
// about://flags.
if (base::FeatureList::IsEnabled(
chromeos::features::kDisableIdleSocketsCloseOnMemoryPressure)) {
network_context_params->disable_idle_sockets_close_on_memory_pressure =
true;
}
#endif
network_context_params->reset_http_cache_backend =
GetHttpCacheBackendResetParam(g_browser_process->local_state());
network_context_params->split_auth_cache_by_network_anonymization_key =
ShouldSplitAuthCacheByNetworkIsolationKey();
// All consumers of the main NetworkContext must provide
// NetworkAnonymizationKeys / IsolationInfos, so storage can be isolated on a
// per-site basis.
network_context_params->require_network_anonymization_key = true;
ContentSetting anti_abuse_content_setting =
HostContentSettingsMapFactory::GetForProfile(profile_)
->GetDefaultContentSetting(ContentSettingsType::ANTI_ABUSE, nullptr);
network_context_params->block_trust_tokens =
anti_abuse_content_setting == CONTENT_SETTING_BLOCK;
network_context_params->first_party_sets_access_delegate_params =
network::mojom::FirstPartySetsAccessDelegateParams::New();
network_context_params->first_party_sets_access_delegate_params->enabled =
PrivacySandboxSettingsFactory::GetForProfile(profile_)
->AreRelatedWebsiteSetsEnabled();
mojo::Remote<network::mojom::FirstPartySetsAccessDelegate>
fps_access_delegate_remote;
network_context_params->first_party_sets_access_delegate_receiver =
fps_access_delegate_remote.BindNewPipeAndPassReceiver();
first_party_sets::FirstPartySetsPolicyService* fps_service =
first_party_sets::FirstPartySetsPolicyServiceFactory::
GetForBrowserContext(profile_);
DCHECK(fps_service);
fps_service->AddRemoteAccessDelegate(std::move(fps_access_delegate_remote));
network_context_params->acam_preflight_spec_conformant =
profile_->GetPrefs()->GetBoolean(
prefs::kAccessControlAllowMethodsInCORSPreflightSpecConformant);
IpProtectionCoreHost* ipp_core_host = IpProtectionCoreHost::Get(profile_);
if (ipp_core_host) {
ipp_core_host->AddNetworkService(
network_context_params->ip_protection_config_getter
.InitWithNewPipeAndPassReceiver(),
network_context_params->ip_protection_control
.InitWithNewPipeAndPassRemote());
network_context_params->enable_ip_protection =
ipp_core_host->IsIpProtectionEnabled();
}
network_context_params->device_bound_sessions_enabled =
base::FeatureList::IsEnabled(net::features::kDeviceBoundSessions);
}
base::FilePath ProfileNetworkContextService::GetPartitionPath(
const base::FilePath& relative_partition_path) {
base::FilePath path = profile_->GetPath();
if (!relative_partition_path.empty())
path = path.Append(relative_partition_path);
return path;
}
void ProfileNetworkContextService::OnContentSettingChanged(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
ContentSettingsType content_type) {
switch (content_type) {
case ContentSettingsType::ANTI_ABUSE:
UpdateAntiAbuseSettings(profile_);
break;
case ContentSettingsType::DEFAULT:
UpdateAntiAbuseSettings(profile_);
for (auto type :
content_settings::CookieSettings::GetContentSettingsTypes()) {
UpdateCookieSettings(profile_, type);
}
break;
default:
if (content_settings::CookieSettings::GetContentSettingsTypes().contains(
content_type)) {
UpdateCookieSettings(profile_, content_type);
return;
}
return;
}
}