1 // Copyright 2014 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/supervised_user/supervised_user_pref_store.h"
6 
7 #include <utility>
8 #include <vector>
9 
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/metrics/histogram_functions.h"
13 #include "base/values.h"
14 #include "build/build_config.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/prefs/incognito_mode_prefs.h"
17 #include "chrome/browser/supervised_user/supervised_user_constants.h"
18 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
19 #include "chrome/browser/supervised_user/supervised_user_url_filter.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/net/safe_search_util.h"
22 #include "chrome/common/pref_names.h"
23 #include "components/feed/core/shared_prefs/pref_names.h"
24 #include "components/prefs/pref_value_map.h"
25 #include "components/signin/public/base/signin_pref_names.h"
26 #include "extensions/buildflags/buildflags.h"
27 
28 namespace {
29 
30 struct SupervisedUserSettingsPrefMappingEntry {
31   const char* settings_name;
32   const char* pref_name;
33 };
34 
35 SupervisedUserSettingsPrefMappingEntry kSupervisedUserSettingsPrefMapping[] = {
36     {
37         supervised_users::kContentPackDefaultFilteringBehavior,
38         prefs::kDefaultSupervisedUserFilteringBehavior,
39     },
40     {
41         supervised_users::kContentPackManualBehaviorHosts,
42         prefs::kSupervisedUserManualHosts,
43     },
44     {
45         supervised_users::kContentPackManualBehaviorURLs,
46         prefs::kSupervisedUserManualURLs,
47     },
48     {
49         supervised_users::kForceSafeSearch,
50         prefs::kForceGoogleSafeSearch,
51     },
52     {
53         supervised_users::kSafeSitesEnabled,
54         prefs::kSupervisedUserSafeSites,
55     },
56     {
57         supervised_users::kSigninAllowed,
58         prefs::kSigninAllowed,
59     },
60     {
61         supervised_users::kUserName,
62         prefs::kProfileName,
63     },
64 };
65 
66 }  // namespace
67 
SupervisedUserPrefStore(SupervisedUserSettingsService * supervised_user_settings_service)68 SupervisedUserPrefStore::SupervisedUserPrefStore(
69     SupervisedUserSettingsService* supervised_user_settings_service) {
70   user_settings_subscription_ =
71       supervised_user_settings_service->SubscribeForSettingsChange(
72           base::Bind(&SupervisedUserPrefStore::OnNewSettingsAvailable,
73                      base::Unretained(this)));
74 
75   // The SupervisedUserSettingsService must be created before the PrefStore, and
76   // it will notify the PrefStore to unsubscribe both subscriptions when it is
77   // shut down.
78   shutdown_subscription_ =
79       supervised_user_settings_service->SubscribeForShutdown(
80           base::BindRepeating(
81               &SupervisedUserPrefStore::OnSettingsServiceShutdown,
82               base::Unretained(this)));
83 }
84 
GetValue(const std::string & key,const base::Value ** value) const85 bool SupervisedUserPrefStore::GetValue(const std::string& key,
86                                        const base::Value** value) const {
87   return prefs_->GetValue(key, value);
88 }
89 
GetValues() const90 std::unique_ptr<base::DictionaryValue> SupervisedUserPrefStore::GetValues()
91     const {
92   return prefs_->AsDictionaryValue();
93 }
94 
AddObserver(PrefStore::Observer * observer)95 void SupervisedUserPrefStore::AddObserver(PrefStore::Observer* observer) {
96   observers_.AddObserver(observer);
97 }
98 
RemoveObserver(PrefStore::Observer * observer)99 void SupervisedUserPrefStore::RemoveObserver(PrefStore::Observer* observer) {
100   observers_.RemoveObserver(observer);
101 }
102 
HasObservers() const103 bool SupervisedUserPrefStore::HasObservers() const {
104   return observers_.might_have_observers();
105 }
106 
IsInitializationComplete() const107 bool SupervisedUserPrefStore::IsInitializationComplete() const {
108   return !!prefs_;
109 }
110 
~SupervisedUserPrefStore()111 SupervisedUserPrefStore::~SupervisedUserPrefStore() {
112 }
113 
OnNewSettingsAvailable(const base::DictionaryValue * settings)114 void SupervisedUserPrefStore::OnNewSettingsAvailable(
115     const base::DictionaryValue* settings) {
116   std::unique_ptr<PrefValueMap> old_prefs = std::move(prefs_);
117   prefs_.reset(new PrefValueMap);
118   if (settings) {
119     // Set hardcoded prefs and defaults.
120     prefs_->SetInteger(prefs::kDefaultSupervisedUserFilteringBehavior,
121                        SupervisedUserURLFilter::ALLOW);
122     prefs_->SetBoolean(prefs::kForceGoogleSafeSearch, true);
123     prefs_->SetInteger(prefs::kForceYouTubeRestrict,
124                        safe_search_util::YOUTUBE_RESTRICT_MODERATE);
125     prefs_->SetBoolean(prefs::kHideWebStoreIcon, false);
126     prefs_->SetBoolean(prefs::kSigninAllowed, false);
127     prefs_->SetBoolean(feed::prefs::kEnableSnippets, false);
128 
129     // Copy supervised user settings to prefs.
130     for (const auto& entry : kSupervisedUserSettingsPrefMapping) {
131       const base::Value* value = NULL;
132       if (settings->GetWithoutPathExpansion(entry.settings_name, &value))
133         prefs_->SetValue(entry.pref_name, value->Clone());
134     }
135 
136     // Manually set preferences that aren't direct copies of the settings value.
137     {
138       bool record_history = true;
139       settings->GetBoolean(supervised_users::kRecordHistory, &record_history);
140       prefs_->SetBoolean(prefs::kAllowDeletingBrowserHistory, !record_history);
141       prefs_->SetInteger(prefs::kIncognitoModeAvailability,
142                          record_history ? IncognitoModePrefs::DISABLED
143                                         : IncognitoModePrefs::ENABLED);
144     }
145 
146     {
147       // Note that |prefs::kForceGoogleSafeSearch| is set automatically as part
148       // of |kSupervisedUserSettingsPrefMapping|, but this can't be done for
149       // |prefs::kForceYouTubeRestrict| because it is an int, not a bool.
150       bool force_safe_search = true;
151       settings->GetBoolean(supervised_users::kForceSafeSearch,
152                            &force_safe_search);
153       prefs_->SetInteger(
154           prefs::kForceYouTubeRestrict,
155           force_safe_search ? safe_search_util::YOUTUBE_RESTRICT_MODERATE
156                             : safe_search_util::YOUTUBE_RESTRICT_OFF);
157     }
158 
159 #if BUILDFLAG(ENABLE_EXTENSIONS)
160     {
161       // TODO(crbug/1024646): Update Kids Management server to set a new bit for
162       // extension permissions. Until then, rely on other side effects of the
163       // "Permissions for sites, apps and extensions" setting, like geolocation
164       // being disallowed.
165       bool permissions_disallowed = true;
166       settings->GetBoolean(supervised_users::kGeolocationDisabled,
167                            &permissions_disallowed);
168       prefs_->SetBoolean(prefs::kSupervisedUserExtensionsMayRequestPermissions,
169                          !permissions_disallowed);
170       base::UmaHistogramBoolean(
171           "SupervisedUsers.ExtensionsMayRequestPermissions",
172           !permissions_disallowed);
173     }
174 #endif
175   }
176 
177   if (!old_prefs) {
178     for (Observer& observer : observers_)
179       observer.OnInitializationCompleted(true);
180     return;
181   }
182 
183   std::vector<std::string> changed_prefs;
184   prefs_->GetDifferingKeys(old_prefs.get(), &changed_prefs);
185 
186   // Send out change notifications.
187   for (const std::string& pref : changed_prefs) {
188     for (Observer& observer : observers_)
189       observer.OnPrefValueChanged(pref);
190   }
191 }
192 
OnSettingsServiceShutdown()193 void SupervisedUserPrefStore::OnSettingsServiceShutdown() {
194   user_settings_subscription_.reset();
195   shutdown_subscription_.reset();
196 }
197