1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/safe_browsing/generated_safe_browsing_pref.h"
6
7 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/common/extensions/api/settings_private.h"
9 #include "components/prefs/pref_service.h"
10 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
11
12 namespace settings_api = extensions::api::settings_private;
13
14 namespace safe_browsing {
15
16 const char kGeneratedSafeBrowsingPref[] = "generated.safe_browsing";
17
GeneratedSafeBrowsingPref(Profile * profile)18 GeneratedSafeBrowsingPref::GeneratedSafeBrowsingPref(Profile* profile)
19 : profile_(profile) {
20 user_prefs_registrar_.Init(profile->GetPrefs());
21 user_prefs_registrar_.Add(
22 prefs::kSafeBrowsingEnabled,
23 base::BindRepeating(
24 &GeneratedSafeBrowsingPref::OnSafeBrowsingPreferencesChanged,
25 base::Unretained(this)));
26 user_prefs_registrar_.Add(
27 prefs::kSafeBrowsingEnhanced,
28 base::BindRepeating(
29 &GeneratedSafeBrowsingPref::OnSafeBrowsingPreferencesChanged,
30 base::Unretained(this)));
31 user_prefs_registrar_.Add(
32 prefs::kSafeBrowsingScoutReportingEnabled,
33 base::BindRepeating(
34 &GeneratedSafeBrowsingPref::OnSafeBrowsingPreferencesChanged,
35 base::Unretained(this)));
36 }
37
SetPref(const base::Value * value)38 extensions::settings_private::SetPrefResult GeneratedSafeBrowsingPref::SetPref(
39 const base::Value* value) {
40 if (!value->is_int())
41 return extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH;
42
43 auto selection = static_cast<SafeBrowsingSetting>(value->GetInt());
44
45 if (selection != SafeBrowsingSetting::DISABLED &&
46 selection != SafeBrowsingSetting::STANDARD &&
47 selection != SafeBrowsingSetting::ENHANCED)
48 return extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH;
49
50 // If SBER is forcefully disabled, Enhanced cannot be selected by the user.
51 const PrefService::Preference* reporting_pref =
52 profile_->GetPrefs()->FindPreference(
53 prefs::kSafeBrowsingScoutReportingEnabled);
54 const bool reporting_on = reporting_pref->GetValue()->GetBool();
55 const bool reporting_enforced = !reporting_pref->IsUserModifiable();
56
57 if (reporting_enforced && !reporting_on &&
58 selection == SafeBrowsingSetting::ENHANCED) {
59 return extensions::settings_private::SetPrefResult::PREF_NOT_MODIFIABLE;
60 }
61
62 // kSafeBrowsingEnabled is considered the canonical source for Safe Browsing
63 // management.
64 const PrefService::Preference* enabled_pref =
65 profile_->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnabled);
66 if (!enabled_pref->IsUserModifiable()) {
67 return extensions::settings_private::SetPrefResult::PREF_NOT_MODIFIABLE;
68 }
69
70 // Update both Safe Browsing preferences to match selection.
71 profile_->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled,
72 selection != SafeBrowsingSetting::DISABLED);
73 profile_->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnhanced,
74 selection == SafeBrowsingSetting::ENHANCED);
75
76 return extensions::settings_private::SetPrefResult::SUCCESS;
77 }
78
79 std::unique_ptr<extensions::api::settings_private::PrefObject>
GetPrefObject() const80 GeneratedSafeBrowsingPref::GetPrefObject() const {
81 auto pref_object =
82 std::make_unique<extensions::api::settings_private::PrefObject>();
83 pref_object->key = kGeneratedSafeBrowsingPref;
84 pref_object->type = extensions::api::settings_private::PREF_TYPE_NUMBER;
85
86 auto safe_browsing_enabled =
87 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled);
88 auto safe_browsing_enhanced_enabled =
89 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnhanced);
90
91 if (safe_browsing_enhanced_enabled && safe_browsing_enabled) {
92 pref_object->value = std::make_unique<base::Value>(
93 static_cast<int>(SafeBrowsingSetting::ENHANCED));
94 } else if (safe_browsing_enabled) {
95 pref_object->value = std::make_unique<base::Value>(
96 static_cast<int>(SafeBrowsingSetting::STANDARD));
97 } else {
98 pref_object->value = std::make_unique<base::Value>(
99 static_cast<int>(SafeBrowsingSetting::DISABLED));
100 }
101
102 ApplySafeBrowsingManagementState(profile_, pref_object.get());
103
104 return pref_object;
105 }
106
OnSafeBrowsingPreferencesChanged()107 void GeneratedSafeBrowsingPref::OnSafeBrowsingPreferencesChanged() {
108 NotifyObservers(kGeneratedSafeBrowsingPref);
109 }
110
111 /* static */
ApplySafeBrowsingManagementState(const Profile * profile,settings_api::PrefObject * pref_object)112 void GeneratedSafeBrowsingPref::ApplySafeBrowsingManagementState(
113 const Profile* profile,
114 settings_api::PrefObject* pref_object) {
115 // Computing the effective Safe Browsing managed state requires inspecting
116 // three different preferences. It is possible that these may be in
117 // temporarily conflicting managed states. The enabled preference is always
118 // taken as the canonical source of management.
119 const PrefService::Preference* enabled_pref =
120 profile->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnabled);
121 const bool enabled_enforced = !enabled_pref->IsUserModifiable();
122 const bool enabled_recommended =
123 (enabled_pref && enabled_pref->GetRecommendedValue());
124 const bool enabled_recommended_on =
125 enabled_recommended && enabled_pref->GetRecommendedValue()->GetBool();
126
127 // The enhanced preference may have a recommended setting. This only takes
128 // effect if the enabled preference also has a recommended setting.
129 const PrefService::Preference* enhanced_pref =
130 profile->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnhanced);
131 const bool enhanced_recommended_on =
132 enhanced_pref->GetRecommendedValue() &&
133 enhanced_pref->GetRecommendedValue()->GetBool();
134
135 // A forcefully disabled reporting preference will disallow enhanced from
136 // being selected and thus it must also be considered.
137 const PrefService::Preference* reporting_pref =
138 profile->GetPrefs()->FindPreference(
139 prefs::kSafeBrowsingScoutReportingEnabled);
140 const bool reporting_on = reporting_pref->GetValue()->GetBool();
141 const bool reporting_enforced = !reporting_pref->IsUserModifiable();
142
143 if (!enabled_enforced && !enabled_recommended && !reporting_enforced) {
144 // No relevant policies are applied.
145 return;
146 }
147
148 if (enabled_enforced) {
149 // Preference is fully controlled.
150 pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_ENFORCED;
151 extensions::settings_private::GeneratedPref::ApplyControlledByFromPref(
152 pref_object, enabled_pref);
153 return;
154 }
155
156 if (enabled_recommended) {
157 // Set enforcement to recommended. This may be upgraded to enforced later
158 // in this function.
159 pref_object->enforcement =
160 settings_api::Enforcement::ENFORCEMENT_RECOMMENDED;
161 if (enhanced_recommended_on) {
162 pref_object->recommended_value = std::make_unique<base::Value>(
163 static_cast<int>(SafeBrowsingSetting::ENHANCED));
164 } else if (enabled_recommended_on) {
165 pref_object->recommended_value = std::make_unique<base::Value>(
166 static_cast<int>(SafeBrowsingSetting::STANDARD));
167 } else {
168 pref_object->recommended_value = std::make_unique<base::Value>(
169 static_cast<int>(SafeBrowsingSetting::DISABLED));
170 }
171 }
172
173 if (reporting_enforced && !reporting_on) {
174 // Reporting has been forcefully disabled by policy. Enhanced protection is
175 // thus also implicitly disabled by the same policy.
176 pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_ENFORCED;
177 extensions::settings_private::GeneratedPref::ApplyControlledByFromPref(
178 pref_object, reporting_pref);
179
180 pref_object->user_selectable_values =
181 std::make_unique<std::vector<std::unique_ptr<base::Value>>>();
182 pref_object->user_selectable_values->push_back(
183 std::make_unique<base::Value>(
184 static_cast<int>(SafeBrowsingSetting::STANDARD)));
185 pref_object->user_selectable_values->push_back(
186 std::make_unique<base::Value>(
187 static_cast<int>(SafeBrowsingSetting::DISABLED)));
188 }
189 }
190
191 } // namespace safe_browsing
192