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