blob: 7754310bb3f3bed102d38fd23b3e9557ca8ba1a7 [file]
// Copyright 2020 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/safe_browsing/generated_safe_browsing_pref.h"
#include <utility>
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/settings_private.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
namespace settings_api = extensions::api::settings_private;
namespace safe_browsing {
const char kGeneratedSafeBrowsingPref[] = "generated.safe_browsing";
GeneratedSafeBrowsingPref::GeneratedSafeBrowsingPref(Profile* profile)
: profile_(profile) {
user_prefs_registrar_.Init(profile->GetPrefs());
user_prefs_registrar_.AddMultiple(
{prefs::kSafeBrowsingEnabled, prefs::kSafeBrowsingEnhanced,
prefs::kSafeBrowsingScoutReportingEnabled},
base::BindRepeating(
&GeneratedSafeBrowsingPref::OnSafeBrowsingPreferencesChanged,
base::Unretained(this)));
user_prefs_registrar_.Add(
prefs::kSecuritySettingsBundle,
base::BindRepeating(&GeneratedSafeBrowsingPref::OnSettingsBundleChanged,
base::Unretained(this)));
}
extensions::settings_private::SetPrefResult GeneratedSafeBrowsingPref::SetPref(
const base::Value* value) {
if (!value->is_int()) {
return extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH;
}
auto selection = static_cast<SafeBrowsingState>(value->GetInt());
if (selection != SafeBrowsingState::NO_SAFE_BROWSING &&
selection != SafeBrowsingState::STANDARD_PROTECTION &&
selection != SafeBrowsingState::ENHANCED_PROTECTION) {
return extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH;
}
// If SBER is forcefully disabled, Enhanced cannot be selected by the user.
const PrefService::Preference* reporting_pref =
profile_->GetPrefs()->FindPreference(
prefs::kSafeBrowsingScoutReportingEnabled);
const bool reporting_on = reporting_pref->GetValue()->GetBool();
const bool reporting_enforced = !reporting_pref->IsUserModifiable();
if (reporting_enforced && !reporting_on &&
selection == SafeBrowsingState::ENHANCED_PROTECTION) {
return extensions::settings_private::SetPrefResult::PREF_NOT_MODIFIABLE;
}
// kSafeBrowsingEnabled is considered the canonical source for Safe Browsing
// management.
const PrefService::Preference* enabled_pref =
profile_->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnabled);
if (!enabled_pref->IsUserModifiable()) {
return extensions::settings_private::SetPrefResult::PREF_NOT_MODIFIABLE;
}
// Update both Safe Browsing preferences to match selection.
profile_->GetPrefs()->SetBoolean(
prefs::kSafeBrowsingEnabled,
selection != SafeBrowsingState::NO_SAFE_BROWSING);
profile_->GetPrefs()->SetBoolean(
prefs::kSafeBrowsingEnhanced,
selection == SafeBrowsingState::ENHANCED_PROTECTION);
// Set ESB not set in sync with Account ESB through TailoredSecurity.
if (selection == SafeBrowsingState::ENHANCED_PROTECTION) {
profile_->GetPrefs()->SetBoolean(
prefs::kEnhancedProtectionEnabledViaTailoredSecurity, false);
}
return extensions::settings_private::SetPrefResult::SUCCESS;
}
extensions::api::settings_private::PrefObject
GeneratedSafeBrowsingPref::GetPrefObject() const {
SafeBrowsingState safe_browsing_state =
GetSafeBrowsingState(*profile_->GetPrefs());
extensions::api::settings_private::PrefObject pref_object;
pref_object.key = kGeneratedSafeBrowsingPref;
pref_object.type = extensions::api::settings_private::PrefType::kNumber;
pref_object.value = base::Value(static_cast<int>(safe_browsing_state));
ApplySafeBrowsingManagementState(*profile_, pref_object);
return pref_object;
}
void GeneratedSafeBrowsingPref::OnSafeBrowsingPreferencesChanged() {
NotifyObservers(kGeneratedSafeBrowsingPref);
}
void GeneratedSafeBrowsingPref::OnSettingsBundleChanged() {
auto bundle = GetSecurityBundleSetting(*profile_->GetPrefs());
switch (bundle) {
case SecuritySettingsBundleSetting::STANDARD:
SetPref(std::make_unique<base::Value>(
static_cast<int>(SafeBrowsingState::STANDARD_PROTECTION))
.get());
break;
case SecuritySettingsBundleSetting::ENHANCED:
SetPref(std::make_unique<base::Value>(
static_cast<int>(SafeBrowsingState::ENHANCED_PROTECTION))
.get());
break;
default:
NOTREACHED();
}
}
/* static */
void GeneratedSafeBrowsingPref::ApplySafeBrowsingManagementState(
const Profile& profile,
settings_api::PrefObject& pref_object) {
// Computing the effective Safe Browsing managed state requires inspecting
// three different preferences. It is possible that these may be in
// temporarily conflicting managed states. The enabled preference is always
// taken as the canonical source of management.
const PrefService::Preference* enabled_pref =
profile.GetPrefs()->FindPreference(prefs::kSafeBrowsingEnabled);
const bool enabled_enforced = !enabled_pref->IsUserModifiable();
const bool enabled_recommended =
(enabled_pref && enabled_pref->GetRecommendedValue());
const bool enabled_recommended_on =
enabled_recommended && enabled_pref->GetRecommendedValue()->GetBool();
// The enhanced preference may have a recommended setting. This only takes
// effect if the enabled preference also has a recommended setting.
const PrefService::Preference* enhanced_pref =
profile.GetPrefs()->FindPreference(prefs::kSafeBrowsingEnhanced);
const bool enhanced_recommended_on =
enhanced_pref->GetRecommendedValue() &&
enhanced_pref->GetRecommendedValue()->GetBool();
// A forcefully disabled reporting preference will disallow enhanced from
// being selected and thus it must also be considered.
const PrefService::Preference* reporting_pref =
profile.GetPrefs()->FindPreference(
prefs::kSafeBrowsingScoutReportingEnabled);
const bool reporting_on = reporting_pref->GetValue()->GetBool();
const bool reporting_enforced = !reporting_pref->IsUserModifiable();
if (!enabled_enforced && !enabled_recommended && !reporting_enforced) {
// No relevant policies are applied.
return;
}
if (enabled_enforced) {
// Preference is fully controlled.
pref_object.enforcement = settings_api::Enforcement::kEnforced;
extensions::settings_private::GeneratedPref::ApplyControlledByFromPref(
&pref_object, enabled_pref);
return;
}
if (enabled_recommended) {
// Set enforcement to recommended. This may be upgraded to enforced later
// in this function.
pref_object.enforcement = settings_api::Enforcement::kRecommended;
if (enhanced_recommended_on) {
pref_object.recommended_value =
base::Value(static_cast<int>(SafeBrowsingState::ENHANCED_PROTECTION));
} else if (enabled_recommended_on) {
pref_object.recommended_value =
base::Value(static_cast<int>(SafeBrowsingState::STANDARD_PROTECTION));
} else {
pref_object.recommended_value =
base::Value(static_cast<int>(SafeBrowsingState::NO_SAFE_BROWSING));
}
}
if (reporting_enforced && !reporting_on) {
// Reporting has been forcefully disabled by policy. Enhanced protection is
// thus also implicitly disabled by the same policy.
pref_object.enforcement = settings_api::Enforcement::kEnforced;
extensions::settings_private::GeneratedPref::ApplyControlledByFromPref(
&pref_object, reporting_pref);
pref_object.user_selectable_values.emplace();
pref_object.user_selectable_values->Append(
std::to_underlying(SafeBrowsingState::STANDARD_PROTECTION));
pref_object.user_selectable_values->Append(
std::to_underlying(SafeBrowsingState::NO_SAFE_BROWSING));
}
}
} // namespace safe_browsing