blob: 10a78726d1e921464acbb047a9fec5e059506d24 [file] [log] [blame]
// Copyright 2023 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/tpcd/support/tpcd_support_service.h"
#include "base/functional/callback_helpers.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.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_pattern.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "components/origin_trials/browser/origin_trials.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace tpcd::trial {
namespace {
const char kTrialName[] = "Tpcd";
} // namespace
TpcdTrialService::TpcdTrialService(content::BrowserContext* browser_context)
: browser_context_(browser_context) {
ot_controller_ = browser_context->GetOriginTrialsControllerDelegate();
if (ot_controller_) {
ot_controller_->AddObserver(this);
}
}
TpcdTrialService::~TpcdTrialService() = default;
void TpcdTrialService::Shutdown() {
if (ot_controller_) {
ot_controller_->RemoveObserver(this);
}
ot_controller_ = nullptr;
browser_context_ = nullptr;
}
void TpcdTrialService::Update3pcdTrialSettingsForTesting(
const OriginTrialStatusChangeDetails& details) {
Update3pcdTrialSettings(details);
}
void TpcdTrialService::Update3pcdTrialSettings(
const OriginTrialStatusChangeDetails& details) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
HostContentSettingsMap* settings_map =
HostContentSettingsMapFactory::GetForProfile(browser_context_);
CHECK(settings_map);
const GURL origin_as_url = details.origin.GetURL();
const GURL partition_site_as_url = GURL(details.partition_site);
// Check for an existing `TPCD_TRIAL` setting that allows the pair.
content_settings::SettingInfo existing_setting_info;
bool setting_exists =
(settings_map->GetContentSetting(origin_as_url, partition_site_as_url,
ContentSettingsType::TPCD_TRIAL,
&existing_setting_info) ==
CONTENT_SETTING_ALLOW) &&
(existing_setting_info.primary_pattern.HasDomainWildcard() ==
details.match_subdomains) &&
!existing_setting_info.primary_pattern.MatchesAllHosts() &&
!existing_setting_info.secondary_pattern.MatchesAllHosts();
// If the trial status matches existing settings, there is no need to
// update `settings_map`.
if (details.enabled == setting_exists) {
return;
}
ContentSettingsPattern primary_setting_pattern;
ContentSettingsPattern secondary_setting_pattern =
ContentSettingsPattern::FromURLToSchemefulSitePattern(
partition_site_as_url);
if (details.match_subdomains) {
primary_setting_pattern = ContentSettingsPattern::FromURL(origin_as_url);
} else {
// In this case, the combination of `primary_setting_pattern` and
// `secondary_setting_pattern` is equivalent to
// `ContentSettingsType::TPCD_TRIAL`'s default scope
// (`REQUESTING_ORIGIN_AND_TOP_SCHEMEFUL_SITE_SCOPE`).
primary_setting_pattern =
ContentSettingsPattern::FromURLNoWildcard(origin_as_url);
}
if (details.enabled) {
settings_map->SetContentSettingCustomScope(
primary_setting_pattern, secondary_setting_pattern,
ContentSettingsType::TPCD_TRIAL, CONTENT_SETTING_ALLOW);
} else {
CHECK(setting_exists);
// Remove settings for expired/unused pairs to avoid memory bloat.
auto matches_pair =
[&](const ContentSettingPatternSource& setting) -> bool {
return (setting.primary_pattern ==
existing_setting_info.primary_pattern) &&
(setting.secondary_pattern ==
existing_setting_info.secondary_pattern);
};
settings_map->ClearSettingsForOneTypeWithPredicate(
ContentSettingsType::TPCD_TRIAL, matches_pair);
}
SyncTpcdTrialSettingsToNetworkService(settings_map);
}
void TpcdTrialService::ClearTpcdTrialSettings() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
HostContentSettingsMap* settings_map =
HostContentSettingsMapFactory::GetForProfile(browser_context_);
CHECK(settings_map);
settings_map->ClearSettingsForOneType(ContentSettingsType::TPCD_TRIAL);
SyncTpcdTrialSettingsToNetworkService(settings_map);
}
void TpcdTrialService::SyncTpcdTrialSettingsToNetworkService(
HostContentSettingsMap* settings_map) {
ContentSettingsForOneType tpcd_trial_settings =
settings_map->GetSettingsForOneType(ContentSettingsType::TPCD_TRIAL);
browser_context_->GetDefaultStoragePartition()
->GetCookieManagerForBrowserProcess()
->SetContentSettings(ContentSettingsType::TPCD_TRIAL,
std::move(tpcd_trial_settings),
base::NullCallback());
}
void TpcdTrialService::OnStatusChanged(
const OriginTrialStatusChangeDetails& details) {
Update3pcdTrialSettings(details);
}
void TpcdTrialService::OnPersistedTokensCleared() {
ClearTpcdTrialSettings();
}
std::string TpcdTrialService::trial_name() {
return kTrialName;
}
} // namespace tpcd::trial