blob: 995f54db53c5d4c04d911c7a66b4d97fa98fab48 [file] [log] [blame]
[email protected]cce15bb2014-06-17 13:43:511// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]0850e842013-01-19 03:44:312// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]cce15bb2014-06-17 13:43:515#include "chrome/browser/supervised_user/supervised_user_service.h"
[email protected]0850e842013-01-19 03:44:316
dchenge73d8520c2015-12-27 01:19:097#include <utility>
8
[email protected]a19df3e2013-05-21 00:03:039#include "base/command_line.h"
mamire9609642016-06-28 22:17:5410#include "base/feature_list.h"
treibdaece84f2014-09-05 12:58:1511#include "base/files/file_path.h"
treib2fd187392015-04-16 17:19:3812#include "base/files/file_util.h"
leon.han4ea301f2017-03-28 03:36:3113#include "base/memory/ptr_util.h"
[email protected]0850e842013-01-19 03:44:3114#include "base/memory/ref_counted.h"
bratell0a7406f2017-03-28 07:46:3715#include "base/metrics/user_metrics.h"
treibd3f8b7a2015-04-10 11:41:3316#include "base/path_service.h"
treib40d3ad92015-10-20 18:15:4217#include "base/strings/stringprintf.h"
[email protected]112158af2013-06-07 23:46:1818#include "base/strings/utf_string_conversions.h"
fdoray9afc2bc2017-04-27 15:00:0019#include "base/task_scheduler/post_task.h"
treibf832a992015-03-24 18:09:2420#include "base/version.h"
avi664c07b2015-12-26 02:18:3121#include "build/build_config.h"
[email protected]5ddfade2014-02-03 10:24:5322#include "chrome/browser/browser_process.h"
bauerb4da36132014-12-26 19:53:1323#include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
[email protected]0850e842013-01-19 03:44:3124#include "chrome/browser/profiles/profile.h"
lwchkg7f133c72016-03-01 16:48:5325#include "chrome/browser/profiles/profile_attributes_entry.h"
26#include "chrome/browser/profiles/profile_attributes_storage.h"
[email protected]5ddfade2014-02-03 10:24:5327#include "chrome/browser/profiles/profile_manager.h"
[email protected]aab946912013-11-06 22:18:5128#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
[email protected]f252df2e2013-06-06 23:47:1929#include "chrome/browser/signin/signin_manager_factory.h"
treibe2082a0e2015-04-08 10:15:3030#include "chrome/browser/supervised_user/experimental/supervised_user_filtering_switches.h"
bauerb5f8cda92015-10-07 15:36:4431#include "chrome/browser/supervised_user/permission_request_creator.h"
[email protected]cce15bb2014-06-17 13:43:5132#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5433#include "chrome/browser/supervised_user/supervised_user_features.h"
mmenkedb2637ff2017-03-30 23:59:4234#include "chrome/browser/supervised_user/supervised_user_navigation_throttle.h"
mamire9609642016-06-28 22:17:5435#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
treibab0a39e2014-09-24 14:48:2836#include "chrome/browser/supervised_user/supervised_user_service_observer.h"
[email protected]cce15bb2014-06-17 13:43:5137#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
38#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
[email protected]cce15bb2014-06-17 13:43:5139#include "chrome/browser/supervised_user/supervised_user_site_list.h"
bauerb4da36132014-12-26 19:53:1340#include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
[email protected]a19df3e2013-05-21 00:03:0341#include "chrome/browser/sync/profile_sync_service_factory.h"
[email protected]509ad1a92013-03-19 21:41:0642#include "chrome/browser/ui/browser.h"
[email protected]dfddd022013-07-10 17:29:4843#include "chrome/browser/ui/browser_list.h"
Bernhard Bauer2ea168ed2017-06-23 15:27:3644#include "chrome/common/chrome_features.h"
treibd3f8b7a2015-04-10 11:41:3345#include "chrome/common/chrome_paths.h"
[email protected]a19df3e2013-05-21 00:03:0346#include "chrome/common/chrome_switches.h"
[email protected]0850e842013-01-19 03:44:3147#include "chrome/common/pref_names.h"
[email protected]af39f002014-08-22 10:18:1848#include "chrome/grit/generated_resources.h"
maxbogue26f40222016-09-16 20:22:1849#include "components/browser_sync/profile_sync_service.h"
[email protected]f0c8c4992014-05-15 17:37:2650#include "components/pref_registry/pref_registry_syncable.h"
brettwb1fc1b82016-02-02 00:19:0851#include "components/prefs/pref_service.h"
[email protected]7274ef02014-03-24 22:43:4052#include "components/signin/core/browser/profile_oauth2_token_service.h"
[email protected]7fbd3b12014-04-01 11:19:1653#include "components/signin/core/browser/signin_manager.h"
[email protected]63c7f0c2014-03-25 21:12:5954#include "components/signin/core/browser/signin_manager_base.h"
David Rogera6c88122017-10-25 13:02:4655#include "components/signin/core/browser/signin_switches.h"
[email protected]0850e842013-01-19 03:44:3156#include "content/public/browser/browser_thread.h"
Scott Violetc8240b02018-03-08 22:03:5957#include "extensions/buildflags/buildflags.h"
rhalavati5f1caa2b2017-02-25 08:22:1658#include "net/traffic_annotation/network_traffic_annotation.h"
[email protected]0850e842013-01-19 03:44:3159#include "ui/base/l10n/l10n_util.h"
60
jam1c5a91492016-02-24 20:47:5361#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:4462#include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service.h"
63#include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service_factory.h"
64#include "chrome/browser/supervised_user/legacy/permission_request_creator_sync.h"
65#include "chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service.h"
66#include "chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service_factory.h"
thestig1b76f1a2015-09-30 22:52:3867#include "chrome/browser/supervised_user/legacy/supervised_user_registration_utility.h"
bauerb5f8cda92015-10-07 15:36:4468#include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_factory.h"
brettw9b0866f2016-12-11 02:34:0669#include "chrome/browser/themes/theme_service.h"
70#include "chrome/browser/themes/theme_service_factory.h"
thestig1b76f1a2015-09-30 22:52:3871#endif
72
[email protected]3aacc9c2013-08-08 11:19:3173#if defined(OS_CHROMEOS)
[email protected]4d390782014-08-15 09:22:5874#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
[email protected]83d82d42014-05-16 02:04:4275#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
[email protected]4d390782014-08-15 09:22:5876#include "components/user_manager/user_manager.h"
[email protected]3aacc9c2013-08-08 11:19:3177#endif
78
brettw00899e62016-11-12 02:10:1779#if BUILDFLAG(ENABLE_EXTENSIONS)
treib9e30e302015-04-15 08:12:1680#include "chrome/browser/extensions/extension_service.h"
mamir192d7882016-06-22 17:10:1681#include "chrome/browser/extensions/extension_util.h"
82#include "extensions/browser/extension_prefs.h"
mamire9609642016-06-28 22:17:5483#include "extensions/browser/extension_registry.h"
[email protected]c14a6802014-07-11 21:51:1284#include "extensions/browser/extension_system.h"
[email protected]c14a6802014-07-11 21:51:1285#endif
86
[email protected]a581ea22013-05-06 12:34:1987using base::DictionaryValue;
[email protected]2056c3b2014-04-07 18:08:5088using base::UserMetricsAction;
[email protected]0850e842013-01-19 03:44:3189using content::BrowserThread;
90
brettw00899e62016-11-12 02:10:1791#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:5492using extensions::Extension;
93using extensions::ExtensionPrefs;
94using extensions::ExtensionRegistry;
95using extensions::ExtensionSystem;
96#endif
97
brettw00899e62016-11-12 02:10:1798#if BUILDFLAG(ENABLE_EXTENSIONS)
mamir192d7882016-06-22 17:10:1699using extensions::ExtensionPrefs;
100#endif
101
treib22c3a042015-01-15 21:30:13102namespace {
103
treibd3f8b7a2015-04-10 11:41:33104// The URL from which to download a host blacklist if no local one exists yet.
105const char kBlacklistURL[] =
106 "https://www.gstatic.com/chrome/supervised_user/blacklist-20141001-1k.bin";
107// The filename under which we'll store the blacklist (in the user data dir).
108const char kBlacklistFilename[] = "su-blacklist.bin";
109
treib22c3a042015-01-15 21:30:13110const char* const kCustodianInfoPrefs[] = {
111 prefs::kSupervisedUserCustodianName,
112 prefs::kSupervisedUserCustodianEmail,
113 prefs::kSupervisedUserCustodianProfileImageURL,
114 prefs::kSupervisedUserCustodianProfileURL,
115 prefs::kSupervisedUserSecondCustodianName,
116 prefs::kSupervisedUserSecondCustodianEmail,
117 prefs::kSupervisedUserSecondCustodianProfileImageURL,
118 prefs::kSupervisedUserSecondCustodianProfileURL,
119};
120
Carlos IL6b784a62018-03-20 00:26:49121void CreateURLAccessRequest(const GURL& url,
122 PermissionRequestCreator* creator,
123 SupervisedUserService::SuccessCallback callback) {
124 creator->CreateURLAccessRequest(url, std::move(callback));
treib8ecc1eb52015-03-04 18:29:06125}
126
mamire9609642016-06-28 22:17:54127void CreateExtensionInstallRequest(
128 const std::string& id,
129 PermissionRequestCreator* creator,
Carlos IL6b784a62018-03-20 00:26:49130 SupervisedUserService::SuccessCallback callback) {
131 creator->CreateExtensionInstallRequest(id, std::move(callback));
mamire9609642016-06-28 22:17:54132}
133
treib8ecc1eb52015-03-04 18:29:06134void CreateExtensionUpdateRequest(
treibf832a992015-03-24 18:09:24135 const std::string& id,
treib8ecc1eb52015-03-04 18:29:06136 PermissionRequestCreator* creator,
Carlos IL6b784a62018-03-20 00:26:49137 SupervisedUserService::SuccessCallback callback) {
138 creator->CreateExtensionUpdateRequest(id, std::move(callback));
treib8ecc1eb52015-03-04 18:29:06139}
140
mamire9609642016-06-28 22:17:54141// Default callback for AddExtensionInstallRequest.
142void ExtensionInstallRequestSent(const std::string& id, bool success) {
143 VLOG_IF(1, !success) << "Failed sending install request for " << id;
144}
145
treib40d3ad92015-10-20 18:15:42146// Default callback for AddExtensionUpdateRequest.
147void ExtensionUpdateRequestSent(const std::string& id, bool success) {
148 VLOG_IF(1, !success) << "Failed sending update request for " << id;
149}
150
treibd3f8b7a2015-04-10 11:41:33151base::FilePath GetBlacklistPath() {
152 base::FilePath blacklist_dir;
153 PathService::Get(chrome::DIR_USER_DATA, &blacklist_dir);
154 return blacklist_dir.AppendASCII(kBlacklistFilename);
155}
156
treib22c3a042015-01-15 21:30:13157} // namespace
158
bauerb5f8cda92015-10-07 15:36:44159SupervisedUserService::~SupervisedUserService() {
160 DCHECK(!did_init_ || did_shutdown_);
mmenkedb2637ff2017-03-30 23:59:42161 url_filter_.RemoveObserver(this);
bauerb5f8cda92015-10-07 15:36:44162}
163
164// static
165void SupervisedUserService::RegisterProfilePrefs(
166 user_prefs::PrefRegistrySyncable* registry) {
mamire9609642016-06-28 22:17:54167 registry->RegisterDictionaryPref(prefs::kSupervisedUserApprovedExtensions);
bauerb5f8cda92015-10-07 15:36:44168 registry->RegisterDictionaryPref(prefs::kSupervisedUserManualHosts);
169 registry->RegisterDictionaryPref(prefs::kSupervisedUserManualURLs);
170 registry->RegisterIntegerPref(prefs::kDefaultSupervisedUserFilteringBehavior,
171 SupervisedUserURLFilter::ALLOW);
172 registry->RegisterBooleanPref(prefs::kSupervisedUserCreationAllowed, true);
173 registry->RegisterBooleanPref(prefs::kSupervisedUserSafeSites, true);
174 for (const char* pref : kCustodianInfoPrefs) {
175 registry->RegisterStringPref(pref, std::string());
176 }
177}
178
179void SupervisedUserService::Init() {
180 DCHECK(!did_init_);
181 did_init_ = true;
182 DCHECK(GetSettingsService()->IsReady());
183
184 pref_change_registrar_.Init(profile_->GetPrefs());
185 pref_change_registrar_.Add(
186 prefs::kSupervisedUserId,
187 base::Bind(&SupervisedUserService::OnSupervisedUserIdChanged,
188 base::Unretained(this)));
189 pref_change_registrar_.Add(
bauerbb519f8252016-05-13 09:16:39190 prefs::kForceSessionSync,
191 base::Bind(&SupervisedUserService::OnForceSessionSyncChanged,
bauerb5f8cda92015-10-07 15:36:44192 base::Unretained(this)));
193
maxbogue0a379452016-09-22 21:35:05194 browser_sync::ProfileSyncService* sync_service =
bauerb5f8cda92015-10-07 15:36:44195 ProfileSyncServiceFactory::GetForProfile(profile_);
196 // Can be null in tests.
197 if (sync_service)
198 sync_service->AddPreferenceProvider(this);
199
200 std::string client_id = component_updater::SupervisedUserWhitelistInstaller::
201 ClientIdForProfilePath(profile_->GetPath());
202 whitelist_service_.reset(new SupervisedUserWhitelistService(
203 profile_->GetPrefs(),
204 g_browser_process->supervised_user_whitelist_installer(), client_id));
205 whitelist_service_->AddSiteListsChangedCallback(
206 base::Bind(&SupervisedUserService::OnSiteListsChanged,
207 weak_ptr_factory_.GetWeakPtr()));
208
209 SetActive(ProfileIsSupervised());
210}
211
212void SupervisedUserService::SetDelegate(Delegate* delegate) {
213 if (delegate) {
214 // Changing delegates isn't allowed.
215 DCHECK(!delegate_);
216 } else {
217 // If the delegate is removed, deactivate first to give the old delegate a
218 // chance to clean up.
219 SetActive(false);
220 }
221 delegate_ = delegate;
222}
223
mmenkedb2637ff2017-03-30 23:59:42224SupervisedUserURLFilter* SupervisedUserService::GetURLFilter() {
225 return &url_filter_;
bauerb5f8cda92015-10-07 15:36:44226}
227
228SupervisedUserWhitelistService* SupervisedUserService::GetWhitelistService() {
229 return whitelist_service_.get();
230}
231
232bool SupervisedUserService::AccessRequestsEnabled() {
233 return FindEnabledPermissionRequestCreator(0) < permissions_creators_.size();
234}
235
Carlos IL6b784a62018-03-20 00:26:49236void SupervisedUserService::AddURLAccessRequest(const GURL& url,
237 SuccessCallback callback) {
mmenkedb2637ff2017-03-30 23:59:42238 GURL effective_url = url_filter_.GetEmbeddedURL(url);
treib17f2e382016-10-14 11:42:53239 if (!effective_url.is_valid())
240 effective_url = url;
bauerb5f8cda92015-10-07 15:36:44241 AddPermissionRequestInternal(
Carlos IL6b784a62018-03-20 00:26:49242 base::BindRepeating(CreateURLAccessRequest,
243 SupervisedUserURLFilter::Normalize(effective_url)),
244 std::move(callback), 0);
bauerb5f8cda92015-10-07 15:36:44245}
246
atanasovaac676032016-04-05 16:31:05247void SupervisedUserService::ReportURL(const GURL& url,
Carlos IL6b784a62018-03-20 00:26:49248 SuccessCallback callback) {
atanasovaac676032016-04-05 16:31:05249 if (url_reporter_)
Carlos IL6b784a62018-03-20 00:26:49250 url_reporter_->ReportUrl(url, std::move(callback));
atanasovaac676032016-04-05 16:31:05251 else
Carlos IL6b784a62018-03-20 00:26:49252 std::move(callback).Run(false);
atanasovaac676032016-04-05 16:31:05253}
254
mamire9609642016-06-28 22:17:54255void SupervisedUserService::AddExtensionInstallRequest(
256 const std::string& extension_id,
257 const base::Version& version,
Carlos IL6b784a62018-03-20 00:26:49258 SuccessCallback callback) {
mamire9609642016-06-28 22:17:54259 std::string id = GetExtensionRequestId(extension_id, version);
Carlos IL6b784a62018-03-20 00:26:49260 AddPermissionRequestInternal(
261 base::BindRepeating(CreateExtensionInstallRequest, id),
262 std::move(callback), 0);
mamire9609642016-06-28 22:17:54263}
264
265void SupervisedUserService::AddExtensionInstallRequest(
266 const std::string& extension_id,
267 const base::Version& version) {
268 std::string id = GetExtensionRequestId(extension_id, version);
Carlos IL6b784a62018-03-20 00:26:49269 AddExtensionInstallRequest(extension_id, version,
270 base::BindOnce(ExtensionInstallRequestSent, id));
mamire9609642016-06-28 22:17:54271}
272
bauerb5f8cda92015-10-07 15:36:44273void SupervisedUserService::AddExtensionUpdateRequest(
274 const std::string& extension_id,
275 const base::Version& version,
Carlos IL6b784a62018-03-20 00:26:49276 SuccessCallback callback) {
mamire9609642016-06-28 22:17:54277 std::string id = GetExtensionRequestId(extension_id, version);
bauerb5f8cda92015-10-07 15:36:44278 AddPermissionRequestInternal(
Carlos IL6b784a62018-03-20 00:26:49279 base::BindRepeating(CreateExtensionUpdateRequest, id),
280 std::move(callback), 0);
treib40d3ad92015-10-20 18:15:42281}
282
283void SupervisedUserService::AddExtensionUpdateRequest(
284 const std::string& extension_id,
285 const base::Version& version) {
mamire9609642016-06-28 22:17:54286 std::string id = GetExtensionRequestId(extension_id, version);
treib40d3ad92015-10-20 18:15:42287 AddExtensionUpdateRequest(extension_id, version,
Carlos IL6b784a62018-03-20 00:26:49288 base::BindOnce(ExtensionUpdateRequestSent, id));
treib40d3ad92015-10-20 18:15:42289}
290
291// static
mamire9609642016-06-28 22:17:54292std::string SupervisedUserService::GetExtensionRequestId(
treib40d3ad92015-10-20 18:15:42293 const std::string& extension_id,
294 const base::Version& version) {
295 return base::StringPrintf("%s:%s", extension_id.c_str(),
296 version.GetString().c_str());
bauerb5f8cda92015-10-07 15:36:44297}
298
299std::string SupervisedUserService::GetCustodianEmailAddress() const {
treib2170ea02015-10-13 14:55:12300 std::string email = profile_->GetPrefs()->GetString(
bauerb5f8cda92015-10-07 15:36:44301 prefs::kSupervisedUserCustodianEmail);
302#if defined(OS_CHROMEOS)
treib2170ea02015-10-13 14:55:12303 // |GetActiveUser()| can return null in unit tests.
304 if (email.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
305 email = chromeos::ChromeUserManager::Get()
alemate1e3ddde2016-11-04 02:17:06306 ->GetSupervisedUserManager()
307 ->GetManagerDisplayEmail(user_manager::UserManager::Get()
308 ->GetActiveUser()
309 ->GetAccountId()
310 .GetUserEmail());
bauerb5f8cda92015-10-07 15:36:44311 }
312#endif
treib2170ea02015-10-13 14:55:12313 return email;
bauerb5f8cda92015-10-07 15:36:44314}
315
316std::string SupervisedUserService::GetCustodianName() const {
317 std::string name = profile_->GetPrefs()->GetString(
318 prefs::kSupervisedUserCustodianName);
319#if defined(OS_CHROMEOS)
treib2170ea02015-10-13 14:55:12320 // |GetActiveUser()| can return null in unit tests.
321 if (name.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
alemate1e3ddde2016-11-04 02:17:06322 name = base::UTF16ToUTF8(
323 chromeos::ChromeUserManager::Get()
324 ->GetSupervisedUserManager()
325 ->GetManagerDisplayName(user_manager::UserManager::Get()
326 ->GetActiveUser()
327 ->GetAccountId()
328 .GetUserEmail()));
bauerb5f8cda92015-10-07 15:36:44329 }
330#endif
331 return name.empty() ? GetCustodianEmailAddress() : name;
332}
333
334std::string SupervisedUserService::GetSecondCustodianEmailAddress() const {
335 return profile_->GetPrefs()->GetString(
336 prefs::kSupervisedUserSecondCustodianEmail);
337}
338
339std::string SupervisedUserService::GetSecondCustodianName() const {
340 std::string name = profile_->GetPrefs()->GetString(
341 prefs::kSupervisedUserSecondCustodianName);
342 return name.empty() ? GetSecondCustodianEmailAddress() : name;
343}
344
treib2170ea02015-10-13 14:55:12345base::string16 SupervisedUserService::GetExtensionsLockedMessage() const {
346 return l10n_util::GetStringFUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER,
347 base::UTF8ToUTF16(GetCustodianName()));
348}
349
jam1c5a91492016-02-24 20:47:53350#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44351void SupervisedUserService::InitSync(const std::string& refresh_token) {
352 StartSetupSync();
353
354 ProfileOAuth2TokenService* token_service =
355 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
356 token_service->UpdateCredentials(supervised_users::kSupervisedUserPseudoEmail,
357 refresh_token);
358
359 FinishSetupSyncWhenReady();
360}
361
362void SupervisedUserService::RegisterAndInitSync(
363 SupervisedUserRegistrationUtility* registration_utility,
364 Profile* custodian_profile,
365 const std::string& supervised_user_id,
Carlos IL6b784a62018-03-20 00:26:49366 AuthErrorCallback callback) {
bauerb5f8cda92015-10-07 15:36:44367 DCHECK(ProfileIsSupervised());
368 DCHECK(!custodian_profile->IsSupervised());
369
370 base::string16 name = base::UTF8ToUTF16(
371 profile_->GetPrefs()->GetString(prefs::kProfileName));
372 int avatar_index = profile_->GetPrefs()->GetInteger(
373 prefs::kProfileAvatarIndex);
374 SupervisedUserRegistrationInfo info(name, avatar_index);
375 registration_utility->Register(
Carlos IL6b784a62018-03-20 00:26:49376 supervised_user_id, info,
377 base::BindOnce(&SupervisedUserService::OnSupervisedUserRegistered,
378 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
379 custodian_profile));
bauerb5f8cda92015-10-07 15:36:44380
381 // Fetch the custodian's profile information, to store the name.
msarda4224a222017-03-17 17:20:31382 // TODO(pamg): Take the name from the ProfileAttributesStorage instead.
bauerb5f8cda92015-10-07 15:36:44383 CustodianProfileDownloaderService* profile_downloader_service =
384 CustodianProfileDownloaderServiceFactory::GetForProfile(
385 custodian_profile);
386 profile_downloader_service->DownloadProfile(
387 base::Bind(&SupervisedUserService::OnCustodianProfileDownloaded,
388 weak_ptr_factory_.GetWeakPtr()));
389}
jam1c5a91492016-02-24 20:47:53390#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44391
392void SupervisedUserService::AddNavigationBlockedCallback(
393 const NavigationBlockedCallback& callback) {
394 navigation_blocked_callbacks_.push_back(callback);
395}
396
397void SupervisedUserService::DidBlockNavigation(
398 content::WebContents* web_contents) {
399 for (const auto& callback : navigation_blocked_callbacks_)
400 callback.Run(web_contents);
401}
402
403void SupervisedUserService::AddObserver(
404 SupervisedUserServiceObserver* observer) {
405 observer_list_.AddObserver(observer);
406}
407
408void SupervisedUserService::RemoveObserver(
409 SupervisedUserServiceObserver* observer) {
410 observer_list_.RemoveObserver(observer);
411}
412
413void SupervisedUserService::AddPermissionRequestCreator(
dchengf624e472016-04-12 08:33:17414 std::unique_ptr<PermissionRequestCreator> creator) {
leon.han4ea301f2017-03-28 03:36:31415 permissions_creators_.push_back(std::move(creator));
bauerb5f8cda92015-10-07 15:36:44416}
417
atanasovaac676032016-04-05 16:31:05418void SupervisedUserService::SetSafeSearchURLReporter(
dchengf624e472016-04-12 08:33:17419 std::unique_ptr<SafeSearchURLReporter> reporter) {
atanasovaac676032016-04-05 16:31:05420 url_reporter_ = std::move(reporter);
421}
422
bauerbb519f8252016-05-13 09:16:39423bool SupervisedUserService::IncludesSyncSessionsType() const {
424 return includes_sync_sessions_type_;
425}
426
[email protected]cce15bb2014-06-17 13:43:51427SupervisedUserService::SupervisedUserService(Profile* profile)
fhorschig1f351f02014-09-30 12:30:22428 : includes_sync_sessions_type_(true),
429 profile_(profile),
[email protected]f085fdd52014-06-11 18:09:20430 active_(false),
431 delegate_(NULL),
[email protected]a243d644c2013-06-20 18:37:55432 waiting_for_sync_initialization_(false),
[email protected]dfddd022013-07-10 17:29:48433 is_profile_active_(false),
[email protected]3a276ff2014-08-12 14:22:09434 did_init_(false),
[email protected]8052b242013-11-15 16:40:55435 did_shutdown_(false),
treib9cc1b112016-01-08 10:08:01436 blacklist_state_(BlacklistLoadState::NOT_LOADED),
brettw00899e62016-11-12 02:10:17437#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54438 registry_observer_(this),
439#endif
[email protected]8052b242013-11-15 16:40:55440 weak_ptr_factory_(this) {
mmenkedb2637ff2017-03-30 23:59:42441 url_filter_.AddObserver(this);
brettw00899e62016-11-12 02:10:17442#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54443 registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
444#endif
[email protected]a243d644c2013-06-20 18:37:55445}
[email protected]0850e842013-01-19 03:44:31446
[email protected]cce15bb2014-06-17 13:43:51447void SupervisedUserService::SetActive(bool active) {
[email protected]f085fdd52014-06-11 18:09:20448 if (active_ == active)
[email protected]0850e842013-01-19 03:44:31449 return;
[email protected]f085fdd52014-06-11 18:09:20450 active_ = active;
451
452 if (!delegate_ || !delegate_->SetActive(active_)) {
453 if (active_) {
jam1c5a91492016-02-24 20:47:53454#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20455 SupervisedUserPrefMappingServiceFactory::GetForBrowserContext(profile_)
456 ->Init();
457
avi556c05022014-12-22 23:31:43458 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
[email protected]d20d0432014-06-12 17:14:05459 if (command_line->HasSwitch(switches::kSupervisedUserSyncToken)) {
[email protected]f085fdd52014-06-11 18:09:20460 InitSync(
[email protected]d20d0432014-06-12 17:14:05461 command_line->GetSwitchValueASCII(
462 switches::kSupervisedUserSyncToken));
[email protected]f085fdd52014-06-11 18:09:20463 }
464
465 ProfileOAuth2TokenService* token_service =
466 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
[email protected]cce15bb2014-06-17 13:43:51467 token_service->LoadCredentials(
468 supervised_users::kSupervisedUserPseudoEmail);
[email protected]6e08b9a62014-07-08 00:32:48469
Bernhard Bauer2ea168ed2017-06-23 15:27:36470 if (base::FeatureList::IsEnabled(features::kSupervisedUserCreation)) {
Jeremy Romanec48d7a2018-03-01 17:35:09471 permissions_creators_.push_back(std::make_unique<
Bernhard Bauer2ea168ed2017-06-23 15:27:36472 PermissionRequestCreatorSync>(
473 GetSettingsService(),
474 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(
475 profile_),
476 ProfileSyncServiceFactory::GetForProfile(profile_),
477 GetSupervisedUserName(),
478 profile_->GetPrefs()->GetString(prefs::kSupervisedUserId)));
479 }
treib531fc7312014-12-09 12:49:20480
[email protected]6e08b9a62014-07-08 00:32:48481 SetupSync();
bauerb7f3b8542015-06-29 19:56:19482#else
483 NOTREACHED();
484#endif
[email protected]f085fdd52014-06-11 18:09:20485 }
[email protected]e861bba2013-06-17 15:20:54486 }
[email protected]0850e842013-01-19 03:44:31487
[email protected]f085fdd52014-06-11 18:09:20488 // Now activate/deactivate anything not handled by the delegate yet.
[email protected]e1480482013-09-11 11:49:58489
brettw9b0866f2016-12-11 02:34:06490#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20491 // Re-set the default theme to turn the SU theme on/off.
492 ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile_);
treib9e30e302015-04-15 08:12:16493 if (theme_service->UsingDefaultTheme() || theme_service->UsingSystemTheme())
494 theme_service->UseDefaultTheme();
[email protected]f085fdd52014-06-11 18:09:20495#endif
[email protected]a19df3e2013-05-21 00:03:03496
maxbogue0a379452016-09-22 21:35:05497 browser_sync::ProfileSyncService* sync_service =
bauerbf03588b92014-10-27 13:40:15498 ProfileSyncServiceFactory::GetForProfile(profile_);
499 sync_service->SetEncryptEverythingAllowed(!active_);
500
bauerbd3a36cc42014-10-01 13:05:49501 GetSettingsService()->SetActive(active_);
[email protected]a243d644c2013-06-20 18:37:55502
brettw00899e62016-11-12 02:10:17503#if BUILDFLAG(ENABLE_EXTENSIONS)
[email protected]c14a6802014-07-11 21:51:12504 SetExtensionsActive();
505#endif
[email protected]0850e842013-01-19 03:44:31506
[email protected]f085fdd52014-06-11 18:09:20507 if (active_) {
[email protected]f085fdd52014-06-11 18:09:20508 pref_change_registrar_.Add(
[email protected]d20d0432014-06-12 17:14:05509 prefs::kDefaultSupervisedUserFilteringBehavior,
Carlos IL6b784a62018-03-20 00:26:49510 base::BindRepeating(
511 &SupervisedUserService::OnDefaultFilteringBehaviorChanged,
[email protected]f085fdd52014-06-11 18:09:20512 base::Unretained(this)));
brettw00899e62016-11-12 02:10:17513#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54514 pref_change_registrar_.Add(
515 prefs::kSupervisedUserApprovedExtensions,
Carlos IL6b784a62018-03-20 00:26:49516 base::BindRepeating(&SupervisedUserService::UpdateApprovedExtensions,
517 base::Unretained(this)));
mamire9609642016-06-28 22:17:54518#endif
Carlos IL6b784a62018-03-20 00:26:49519 pref_change_registrar_.Add(
520 prefs::kSupervisedUserSafeSites,
521 base::BindRepeating(&SupervisedUserService::OnSafeSitesSettingChanged,
522 base::Unretained(this)));
523 pref_change_registrar_.Add(
524 prefs::kSupervisedUserManualHosts,
525 base::BindRepeating(&SupervisedUserService::UpdateManualHosts,
526 base::Unretained(this)));
527 pref_change_registrar_.Add(
528 prefs::kSupervisedUserManualURLs,
529 base::BindRepeating(&SupervisedUserService::UpdateManualURLs,
530 base::Unretained(this)));
treib22c3a042015-01-15 21:30:13531 for (const char* pref : kCustodianInfoPrefs) {
Carlos IL6b784a62018-03-20 00:26:49532 pref_change_registrar_.Add(
533 pref,
534 base::BindRepeating(&SupervisedUserService::OnCustodianInfoChanged,
535 base::Unretained(this)));
treib22c3a042015-01-15 21:30:13536 }
[email protected]f085fdd52014-06-11 18:09:20537
538 // Initialize the filter.
539 OnDefaultFilteringBehaviorChanged();
treib9cc1b112016-01-08 10:08:01540 OnSafeSitesSettingChanged();
bauerb4da36132014-12-26 19:53:13541 whitelist_service_->Init();
[email protected]f085fdd52014-06-11 18:09:20542 UpdateManualHosts();
543 UpdateManualURLs();
[email protected]0850e842013-01-19 03:44:31544
brettw00899e62016-11-12 02:10:17545#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54546 UpdateApprovedExtensions();
547#endif
548
jam1c5a91492016-02-24 20:47:53549#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20550 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
551 // http://crbug.com/313377
552 BrowserList::AddObserver(this);
[email protected]975677d2013-11-14 16:15:34553#endif
[email protected]f085fdd52014-06-11 18:09:20554 } else {
bauerbd3a36cc42014-10-01 13:05:49555 permissions_creators_.clear();
atanasovaac676032016-04-05 16:31:05556 url_reporter_.reset();
[email protected]dfddd022013-07-10 17:29:48557
[email protected]d20d0432014-06-12 17:14:05558 pref_change_registrar_.Remove(
559 prefs::kDefaultSupervisedUserFilteringBehavior);
brettw00899e62016-11-12 02:10:17560#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54561 pref_change_registrar_.Remove(prefs::kSupervisedUserApprovedExtensions);
562#endif
[email protected]d20d0432014-06-12 17:14:05563 pref_change_registrar_.Remove(prefs::kSupervisedUserManualHosts);
564 pref_change_registrar_.Remove(prefs::kSupervisedUserManualURLs);
treib22c3a042015-01-15 21:30:13565 for (const char* pref : kCustodianInfoPrefs) {
566 pref_change_registrar_.Remove(pref);
567 }
568
mmenkedb2637ff2017-03-30 23:59:42569 url_filter_.Clear();
ericwilligers8b92b052016-10-19 22:21:58570 for (SupervisedUserServiceObserver& observer : observer_list_)
571 observer.OnURLFilterChanged();
[email protected]f085fdd52014-06-11 18:09:20572
jam1c5a91492016-02-24 20:47:53573#if !defined(OS_ANDROID)
[email protected]3a276ff2014-08-12 14:22:09574 if (waiting_for_sync_initialization_)
575 ProfileSyncServiceFactory::GetForProfile(profile_)->RemoveObserver(this);
[email protected]f085fdd52014-06-11 18:09:20576
[email protected]f085fdd52014-06-11 18:09:20577 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
578 // http://crbug.com/313377
579 BrowserList::RemoveObserver(this);
580#endif
581 }
[email protected]0850e842013-01-19 03:44:31582}
583
jam1c5a91492016-02-24 20:47:53584#if !defined(OS_ANDROID)
[email protected]cce15bb2014-06-17 13:43:51585void SupervisedUserService::OnCustodianProfileDownloaded(
[email protected]0085863a2013-12-06 21:19:03586 const base::string16& full_name) {
[email protected]d20d0432014-06-12 17:14:05587 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
[email protected]6778fed2013-12-24 20:09:37588 base::UTF16ToUTF8(full_name));
[email protected]acfcfbb2013-05-13 18:01:27589}
590
[email protected]cce15bb2014-06-17 13:43:51591void SupervisedUserService::OnSupervisedUserRegistered(
Carlos IL6b784a62018-03-20 00:26:49592 AuthErrorCallback callback,
[email protected]f252df2e2013-06-06 23:47:19593 Profile* custodian_profile,
[email protected]acfcfbb2013-05-13 18:01:27594 const GoogleServiceAuthError& auth_error,
595 const std::string& token) {
[email protected]514fcf22013-08-13 06:37:24596 if (auth_error.state() == GoogleServiceAuthError::NONE) {
597 InitSync(token);
598 SigninManagerBase* signin =
599 SigninManagerFactory::GetForProfile(custodian_profile);
bzanotti1b5be2902015-08-31 12:10:05600 profile_->GetPrefs()->SetString(
601 prefs::kSupervisedUserCustodianEmail,
602 signin->GetAuthenticatedAccountInfo().email);
[email protected]5ddfade2014-02-03 10:24:53603
[email protected]cce15bb2014-06-17 13:43:51604 // The supervised user profile is now ready for use.
lwchkg7f133c72016-03-01 16:48:53605 ProfileAttributesEntry* entry = nullptr;
606 bool has_entry =
607 g_browser_process->profile_manager()->GetProfileAttributesStorage().
608 GetProfileAttributesWithPath(profile_->GetPath(), &entry);
609 DCHECK(has_entry);
610 entry->SetIsOmitted(false);
[email protected]514fcf22013-08-13 06:37:24611 } else {
[email protected]acfcfbb2013-05-13 18:01:27612 DCHECK_EQ(std::string(), token);
[email protected]acfcfbb2013-05-13 18:01:27613 }
614
Carlos IL6b784a62018-03-20 00:26:49615 std::move(callback).Run(auth_error);
[email protected]acfcfbb2013-05-13 18:01:27616}
bauerb5f8cda92015-10-07 15:36:44617void SupervisedUserService::SetupSync() {
618 StartSetupSync();
619 FinishSetupSyncWhenReady();
620}
621
622void SupervisedUserService::StartSetupSync() {
623 // Tell the sync service that setup is in progress so we don't start syncing
624 // until we've finished configuration.
tommyclif3a1551e2016-06-21 18:11:23625 sync_blocker_ = ProfileSyncServiceFactory::GetForProfile(profile_)
626 ->GetSetupInProgressHandle();
bauerb5f8cda92015-10-07 15:36:44627}
628
629void SupervisedUserService::FinishSetupSyncWhenReady() {
maxbogue6b6f9f432016-12-05 23:59:14630 // If we're already waiting for the sync engine, there's nothing to do here.
bauerb5f8cda92015-10-07 15:36:44631 if (waiting_for_sync_initialization_)
632 return;
633
maxbogue6b6f9f432016-12-05 23:59:14634 // Continue in FinishSetupSync() once the sync engine has been initialized.
maxbogue0a379452016-09-22 21:35:05635 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:44636 ProfileSyncServiceFactory::GetForProfile(profile_);
maxbogue6b6f9f432016-12-05 23:59:14637 if (service->IsEngineInitialized()) {
bauerb5f8cda92015-10-07 15:36:44638 FinishSetupSync();
639 } else {
640 service->AddObserver(this);
641 waiting_for_sync_initialization_ = true;
642 }
643}
644
645void SupervisedUserService::FinishSetupSync() {
maxbogue0a379452016-09-22 21:35:05646 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:44647 ProfileSyncServiceFactory::GetForProfile(profile_);
maxbogue6b6f9f432016-12-05 23:59:14648 DCHECK(service->IsEngineInitialized());
bauerb5f8cda92015-10-07 15:36:44649
650 // Sync nothing (except types which are set via GetPreferredDataTypes).
651 bool sync_everything = false;
652 syncer::ModelTypeSet synced_datatypes;
653 service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
654
655 // Notify ProfileSyncService that we are done with configuration.
tommyclif3a1551e2016-06-21 18:11:23656 sync_blocker_.reset();
maxboguefe00952a2016-01-19 19:02:01657 service->SetFirstSetupComplete();
bauerb5f8cda92015-10-07 15:36:44658}
659#endif
660
661bool SupervisedUserService::ProfileIsSupervised() const {
662 return profile_->IsSupervised();
663}
664
665void SupervisedUserService::OnCustodianInfoChanged() {
ericwilligers8b92b052016-10-19 22:21:58666 for (SupervisedUserServiceObserver& observer : observer_list_)
667 observer.OnCustodianInfoChanged();
bauerb5f8cda92015-10-07 15:36:44668}
669
670SupervisedUserSettingsService* SupervisedUserService::GetSettingsService() {
671 return SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
672}
673
674size_t SupervisedUserService::FindEnabledPermissionRequestCreator(
675 size_t start) {
676 for (size_t i = start; i < permissions_creators_.size(); ++i) {
677 if (permissions_creators_[i]->IsEnabled())
678 return i;
679 }
680 return permissions_creators_.size();
681}
682
683void SupervisedUserService::AddPermissionRequestInternal(
684 const CreatePermissionRequestCallback& create_request,
Carlos IL6b784a62018-03-20 00:26:49685 SuccessCallback callback,
bauerb5f8cda92015-10-07 15:36:44686 size_t index) {
687 // Find a permission request creator that is enabled.
688 size_t next_index = FindEnabledPermissionRequestCreator(index);
689 if (next_index >= permissions_creators_.size()) {
Carlos IL6b784a62018-03-20 00:26:49690 std::move(callback).Run(false);
bauerb5f8cda92015-10-07 15:36:44691 return;
692 }
693
694 create_request.Run(
leon.han4ea301f2017-03-28 03:36:31695 permissions_creators_[next_index].get(),
Carlos IL6b784a62018-03-20 00:26:49696 base::BindOnce(&SupervisedUserService::OnPermissionRequestIssued,
697 weak_ptr_factory_.GetWeakPtr(), create_request,
698 std::move(callback), next_index));
bauerb5f8cda92015-10-07 15:36:44699}
700
701void SupervisedUserService::OnPermissionRequestIssued(
702 const CreatePermissionRequestCallback& create_request,
Carlos IL6b784a62018-03-20 00:26:49703 SuccessCallback callback,
bauerb5f8cda92015-10-07 15:36:44704 size_t index,
705 bool success) {
706 if (success) {
Carlos IL6b784a62018-03-20 00:26:49707 std::move(callback).Run(true);
bauerb5f8cda92015-10-07 15:36:44708 return;
709 }
710
Carlos IL6b784a62018-03-20 00:26:49711 AddPermissionRequestInternal(create_request, std::move(callback), index + 1);
bauerb5f8cda92015-10-07 15:36:44712}
713
714void SupervisedUserService::OnSupervisedUserIdChanged() {
715 SetActive(ProfileIsSupervised());
716}
717
718void SupervisedUserService::OnDefaultFilteringBehaviorChanged() {
719 int behavior_value = profile_->GetPrefs()->GetInteger(
720 prefs::kDefaultSupervisedUserFilteringBehavior);
721 SupervisedUserURLFilter::FilteringBehavior behavior =
722 SupervisedUserURLFilter::BehaviorFromInt(behavior_value);
mmenkedb2637ff2017-03-30 23:59:42723 url_filter_.SetDefaultFilteringBehavior(behavior);
bauerb5f8cda92015-10-07 15:36:44724
ericwilligers8b92b052016-10-19 22:21:58725 for (SupervisedUserServiceObserver& observer : observer_list_)
726 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:44727}
728
treib9cc1b112016-01-08 10:08:01729void SupervisedUserService::OnSafeSitesSettingChanged() {
730 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
mmenkedb2637ff2017-03-30 23:59:42731 if (use_blacklist != url_filter_.HasBlacklist()) {
treib9cc1b112016-01-08 10:08:01732 if (use_blacklist && blacklist_state_ == BlacklistLoadState::NOT_LOADED) {
733 LoadBlacklist(GetBlacklistPath(), GURL(kBlacklistURL));
734 } else if (!use_blacklist ||
735 blacklist_state_ == BlacklistLoadState::LOADED) {
736 // Either the blacklist was turned off, or it was turned on but has
737 // already been loaded previously. Just update the setting.
738 UpdateBlacklist();
739 }
740 // Else: The blacklist was enabled, but the load is already in progress.
741 // Do nothing - we'll check the setting again when the load finishes.
742 }
743
744 bool use_online_check =
745 supervised_users::IsSafeSitesOnlineCheckEnabled(profile_);
mmenkedb2637ff2017-03-30 23:59:42746 if (use_online_check != url_filter_.HasAsyncURLChecker()) {
treib9cc1b112016-01-08 10:08:01747 if (use_online_check)
mmenkedb2637ff2017-03-30 23:59:42748 url_filter_.InitAsyncURLChecker(profile_->GetRequestContext());
treib9cc1b112016-01-08 10:08:01749 else
mmenkedb2637ff2017-03-30 23:59:42750 url_filter_.ClearAsyncURLChecker();
treib9cc1b112016-01-08 10:08:01751 }
752}
753
bauerb5f8cda92015-10-07 15:36:44754void SupervisedUserService::OnSiteListsChanged(
755 const std::vector<scoped_refptr<SupervisedUserSiteList> >& site_lists) {
atanasova9572aaf2016-02-26 18:08:26756 whitelists_ = site_lists;
mmenkedb2637ff2017-03-30 23:59:42757 url_filter_.LoadWhitelists(site_lists);
bauerb5f8cda92015-10-07 15:36:44758}
759
760void SupervisedUserService::LoadBlacklist(const base::FilePath& path,
761 const GURL& url) {
treib9cc1b112016-01-08 10:08:01762 DCHECK(blacklist_state_ == BlacklistLoadState::NOT_LOADED);
763 blacklist_state_ = BlacklistLoadState::LOAD_STARTED;
fdoray9afc2bc2017-04-27 15:00:00764 base::PostTaskWithTraitsAndReplyWithResult(
bauerb5f8cda92015-10-07 15:36:44765 FROM_HERE,
fdoray4ad14932017-05-03 21:21:11766 {base::MayBlock(), base::TaskPriority::BACKGROUND,
767 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
fdoray9afc2bc2017-04-27 15:00:00768 base::BindOnce(&base::PathExists, path),
769 base::BindOnce(&SupervisedUserService::OnBlacklistFileChecked,
770 weak_ptr_factory_.GetWeakPtr(), path, url));
bauerb5f8cda92015-10-07 15:36:44771}
772
773void SupervisedUserService::OnBlacklistFileChecked(const base::FilePath& path,
774 const GURL& url,
775 bool file_exists) {
treib9cc1b112016-01-08 10:08:01776 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
bauerb5f8cda92015-10-07 15:36:44777 if (file_exists) {
778 LoadBlacklistFromFile(path);
779 return;
780 }
781
782 DCHECK(!blacklist_downloader_);
rhalavati5f1caa2b2017-02-25 08:22:16783
784 // Create traffic annotation tag.
785 net::NetworkTrafficAnnotationTag traffic_annotation =
786 net::DefineNetworkTrafficAnnotation("supervised_users_blacklist", R"(
787 semantics {
788 sender: "Supervised Users"
789 description:
790 "Downloads a static blacklist consisting of hostname hashes of "
791 "common inappropriate websites. This is only enabled for child "
792 "accounts and only if the corresponding setting is enabled by the "
793 "parent."
794 trigger:
795 "The file is downloaded on demand if the child account profile is "
796 "created and the setting is enabled."
797 data:
798 "No additional data is sent to the server beyond the request "
799 "itself."
800 destination: GOOGLE_OWNED_SERVICE
801 }
802 policy {
Ramin Halavati3b979782017-07-21 11:40:26803 cookies_allowed: NO
rhalavati5f1caa2b2017-02-25 08:22:16804 setting:
805 "The feature can be remotely enabled or disabled by the parent. In "
806 "addition, if sign-in is restricted to accounts from a managed "
807 "domain, those accounts are not going to be child accounts."
rhalavatieaa64e92017-04-03 09:36:43808 chrome_policy {
rhalavati5f1caa2b2017-02-25 08:22:16809 RestrictSigninToPattern {
810 policy_options {mode: MANDATORY}
rhalavatieaa64e92017-04-03 09:36:43811 RestrictSigninToPattern: "*@manageddomain.com"
rhalavati5f1caa2b2017-02-25 08:22:16812 }
813 }
814 })");
815
bauerb5f8cda92015-10-07 15:36:44816 blacklist_downloader_.reset(new FileDownloader(
rhalavati5f1caa2b2017-02-25 08:22:16817 url, path, false, profile_->GetRequestContext(),
bauerb5f8cda92015-10-07 15:36:44818 base::Bind(&SupervisedUserService::OnBlacklistDownloadDone,
rhalavati5f1caa2b2017-02-25 08:22:16819 base::Unretained(this), path),
820 traffic_annotation));
bauerb5f8cda92015-10-07 15:36:44821}
822
823void SupervisedUserService::LoadBlacklistFromFile(const base::FilePath& path) {
treib9cc1b112016-01-08 10:08:01824 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
825 blacklist_.ReadFromFile(
826 path,
827 base::Bind(&SupervisedUserService::OnBlacklistLoaded,
828 base::Unretained(this)));
bauerb5f8cda92015-10-07 15:36:44829}
830
treibf38cc252016-04-07 14:44:11831void SupervisedUserService::OnBlacklistDownloadDone(
832 const base::FilePath& path,
833 FileDownloader::Result result) {
treib9cc1b112016-01-08 10:08:01834 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
treibf38cc252016-04-07 14:44:11835 if (FileDownloader::IsSuccess(result)) {
bauerb5f8cda92015-10-07 15:36:44836 LoadBlacklistFromFile(path);
837 } else {
838 LOG(WARNING) << "Blacklist download failed";
treib9cc1b112016-01-08 10:08:01839 // TODO(treib): Retry downloading after some time?
bauerb5f8cda92015-10-07 15:36:44840 }
841 blacklist_downloader_.reset();
842}
843
844void SupervisedUserService::OnBlacklistLoaded() {
treib9cc1b112016-01-08 10:08:01845 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
846 blacklist_state_ = BlacklistLoadState::LOADED;
847 UpdateBlacklist();
848}
849
850void SupervisedUserService::UpdateBlacklist() {
851 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
mmenkedb2637ff2017-03-30 23:59:42852 url_filter_.SetBlacklist(use_blacklist ? &blacklist_ : nullptr);
ericwilligers8b92b052016-10-19 22:21:58853 for (SupervisedUserServiceObserver& observer : observer_list_)
854 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:44855}
[email protected]acfcfbb2013-05-13 18:01:27856
[email protected]cce15bb2014-06-17 13:43:51857void SupervisedUserService::UpdateManualHosts() {
[email protected]cb1078de2013-12-23 20:04:22858 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05859 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualHosts);
mmenkedb2637ff2017-03-30 23:59:42860 std::map<std::string, bool> host_map;
[email protected]cb1078de2013-12-23 20:04:22861 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17862 bool allow = false;
863 bool result = it.value().GetAsBoolean(&allow);
864 DCHECK(result);
mmenkedb2637ff2017-03-30 23:59:42865 host_map[it.key()] = allow;
[email protected]5e022292013-02-06 16:42:17866 }
mmenkedb2637ff2017-03-30 23:59:42867 url_filter_.SetManualHosts(std::move(host_map));
treibab0a39e2014-09-24 14:48:28868
ericwilligers8b92b052016-10-19 22:21:58869 for (SupervisedUserServiceObserver& observer : observer_list_)
870 observer.OnURLFilterChanged();
[email protected]0850e842013-01-19 03:44:31871}
872
[email protected]cce15bb2014-06-17 13:43:51873void SupervisedUserService::UpdateManualURLs() {
[email protected]cb1078de2013-12-23 20:04:22874 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05875 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualURLs);
mmenkedb2637ff2017-03-30 23:59:42876 std::map<GURL, bool> url_map;
[email protected]cb1078de2013-12-23 20:04:22877 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17878 bool allow = false;
879 bool result = it.value().GetAsBoolean(&allow);
880 DCHECK(result);
mmenkedb2637ff2017-03-30 23:59:42881 url_map[GURL(it.key())] = allow;
[email protected]5e022292013-02-06 16:42:17882 }
mmenkedb2637ff2017-03-30 23:59:42883 url_filter_.SetManualURLs(std::move(url_map));
treibab0a39e2014-09-24 14:48:28884
ericwilligers8b92b052016-10-19 22:21:58885 for (SupervisedUserServiceObserver& observer : observer_list_)
886 observer.OnURLFilterChanged();
[email protected]0850e842013-01-19 03:44:31887}
[email protected]dfddd022013-07-10 17:29:48888
[email protected]0b4c6b22014-08-04 09:46:31889std::string SupervisedUserService::GetSupervisedUserName() const {
890#if defined(OS_CHROMEOS)
891 // The active user can be NULL in unit tests.
[email protected]4d390782014-08-15 09:22:58892 if (user_manager::UserManager::Get()->GetActiveUser()) {
Adam Riceff26dcf2017-08-14 05:01:52893 return base::UTF16ToUTF8(
894 user_manager::UserManager::Get()->GetUserDisplayName(
895 user_manager::UserManager::Get()->GetActiveUser()->GetAccountId()));
[email protected]0b4c6b22014-08-04 09:46:31896 }
897 return std::string();
898#else
899 return profile_->GetPrefs()->GetString(prefs::kProfileName);
900#endif
901}
bauerb5f8cda92015-10-07 15:36:44902
bauerbb519f8252016-05-13 09:16:39903void SupervisedUserService::OnForceSessionSyncChanged() {
904 includes_sync_sessions_type_ =
905 profile_->GetPrefs()->GetBoolean(prefs::kForceSessionSync);
bauerb5f8cda92015-10-07 15:36:44906 ProfileSyncServiceFactory::GetForProfile(profile_)
907 ->ReconfigureDatatypeManager();
908}
909
bauerb5f8cda92015-10-07 15:36:44910void SupervisedUserService::Shutdown() {
911 if (!did_init_)
912 return;
913 DCHECK(!did_shutdown_);
914 did_shutdown_ = true;
915 if (ProfileIsSupervised()) {
bratell0a7406f2017-03-28 07:46:37916 base::RecordAction(UserMetricsAction("ManagedUsers_QuitBrowser"));
bauerb5f8cda92015-10-07 15:36:44917 }
918 SetActive(false);
tommyclif3a1551e2016-06-21 18:11:23919 sync_blocker_.reset();
bauerb5f8cda92015-10-07 15:36:44920
maxbogue0a379452016-09-22 21:35:05921 browser_sync::ProfileSyncService* sync_service =
bauerb5f8cda92015-10-07 15:36:44922 ProfileSyncServiceFactory::GetForProfile(profile_);
923
924 // Can be null in tests.
925 if (sync_service)
926 sync_service->RemovePreferenceProvider(this);
927}
928
brettw00899e62016-11-12 02:10:17929#if BUILDFLAG(ENABLE_EXTENSIONS)
mamir192d7882016-06-22 17:10:16930SupervisedUserService::ExtensionState SupervisedUserService::GetExtensionState(
mamire9609642016-06-28 22:17:54931 const Extension& extension) const {
932 bool was_installed_by_default = extension.was_installed_by_default();
mamir192d7882016-06-22 17:10:16933#if defined(OS_CHROMEOS)
934 // On Chrome OS all external sources are controlled by us so it means that
935 // they are "default". Method was_installed_by_default returns false because
936 // extensions creation flags are ignored in case of default extensions with
937 // update URL(the flags aren't passed to OnExternalExtensionUpdateUrlFound).
938 // TODO(dpolukhin): remove this Chrome OS specific code as soon as creation
939 // flags are not ignored.
940 was_installed_by_default =
mamire9609642016-06-28 22:17:54941 extensions::Manifest::IsExternalLocation(extension.location());
mamir192d7882016-06-22 17:10:16942#endif
943 // Note: Component extensions are protected from modification/uninstallation
944 // anyway, so there's no need to enforce them again for supervised users.
945 // Also, leave policy-installed extensions alone - they have their own
946 // management; in particular we don't want to override the force-install list.
mamire9609642016-06-28 22:17:54947 if (extensions::Manifest::IsComponentLocation(extension.location()) ||
948 extensions::Manifest::IsPolicyLocation(extension.location()) ||
949 extension.is_theme() || extension.from_bookmark() ||
950 extension.is_shared_module() || was_installed_by_default) {
951 return ExtensionState::ALLOWED;
mamir192d7882016-06-22 17:10:16952 }
953
mamire9609642016-06-28 22:17:54954 if (extensions::util::WasInstalledByCustodian(extension.id(), profile_))
955 return ExtensionState::FORCED;
mamir192d7882016-06-22 17:10:16956
mamire9609642016-06-28 22:17:54957 if (!base::FeatureList::IsEnabled(
958 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
959 return ExtensionState::BLOCKED;
960 }
961
962 auto extension_it = approved_extensions_map_.find(extension.id());
963 // If the installed version is approved, then the extension is allowed,
964 // otherwise, it requires approval.
965 if (extension_it != approved_extensions_map_.end() &&
Devlin Cronin03bf2d22017-12-20 08:21:05966 extension_it->second == extension.version()) {
mamire9609642016-06-28 22:17:54967 return ExtensionState::ALLOWED;
968 }
969 return ExtensionState::REQUIRE_APPROVAL;
mamir192d7882016-06-22 17:10:16970}
971
bauerb5f8cda92015-10-07 15:36:44972std::string SupervisedUserService::GetDebugPolicyProviderName() const {
973 // Save the string space in official builds.
974#ifdef NDEBUG
975 NOTREACHED();
976 return std::string();
977#else
978 return "Supervised User Service";
979#endif
980}
981
mamire9609642016-06-28 22:17:54982bool SupervisedUserService::UserMayLoad(const Extension* extension,
bauerb5f8cda92015-10-07 15:36:44983 base::string16* error) const {
984 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:54985 ExtensionState result = GetExtensionState(*extension);
986 bool may_load = result != ExtensionState::BLOCKED;
bauerb5f8cda92015-10-07 15:36:44987 if (!may_load && error)
treib2170ea02015-10-13 14:55:12988 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:44989 return may_load;
990}
991
mamire9609642016-06-28 22:17:54992bool SupervisedUserService::UserMayModifySettings(const Extension* extension,
993 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:44994 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:54995 ExtensionState result = GetExtensionState(*extension);
996 // While the following check allows the supervised user to modify the settings
997 // and enable or disable the extension, MustRemainDisabled properly takes care
998 // of keeping an extension disabled when required.
999 // For custodian-installed extensions, the state is always FORCED, even if
1000 // it's waiting for an update approval.
1001 bool may_modify = result != ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:441002 if (!may_modify && error)
treib2170ea02015-10-13 14:55:121003 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441004 return may_modify;
1005}
1006
1007// Note: Having MustRemainInstalled always say "true" for custodian-installed
1008// extensions does NOT prevent remote uninstalls (which is a bit unexpected, but
1009// exactly what we want).
mamire9609642016-06-28 22:17:541010bool SupervisedUserService::MustRemainInstalled(const Extension* extension,
1011 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:441012 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:541013 ExtensionState result = GetExtensionState(*extension);
1014 bool may_not_uninstall = result == ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:441015 if (may_not_uninstall && error)
treib2170ea02015-10-13 14:55:121016 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441017 return may_not_uninstall;
1018}
1019
Minh X. Nguyen45479012017-08-18 21:35:361020bool SupervisedUserService::MustRemainDisabled(
1021 const Extension* extension,
1022 extensions::disable_reason::DisableReason* reason,
1023 base::string16* error) const {
mamire9609642016-06-28 22:17:541024 DCHECK(ProfileIsSupervised());
1025 ExtensionState state = GetExtensionState(*extension);
1026 // Only extensions that require approval should be disabled.
1027 // Blocked extensions should be not loaded at all, and are taken care of
1028 // at UserMayLoad.
1029 bool must_remain_disabled = state == ExtensionState::REQUIRE_APPROVAL;
1030
1031 if (must_remain_disabled) {
1032 if (error)
treib39ecc842016-11-17 12:07:071033 *error = GetExtensionsLockedMessage();
mamire9609642016-06-28 22:17:541034 // If the extension must remain disabled due to permission increase,
1035 // then the update request has been already sent at update time.
1036 // We do nothing and we don't add an extra disable reason.
1037 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1038 if (extension_prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361039 extension->id(),
1040 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE)) {
mamire9609642016-06-28 22:17:541041 if (reason)
Minh X. Nguyen45479012017-08-18 21:35:361042 *reason = extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE;
mamire9609642016-06-28 22:17:541043 return true;
1044 }
1045 if (reason)
Minh X. Nguyen45479012017-08-18 21:35:361046 *reason = extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED;
mamire9609642016-06-28 22:17:541047 if (base::FeatureList::IsEnabled(
1048 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
1049 // If the Extension isn't pending a custodian approval already, send
1050 // an approval request.
1051 if (!extension_prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361052 extension->id(), extensions::disable_reason::
1053 DISABLE_CUSTODIAN_APPROVAL_REQUIRED)) {
mamire9609642016-06-28 22:17:541054 // MustRemainDisabled is a const method and hence cannot call
1055 // AddExtensionInstallRequest directly.
1056 SupervisedUserService* supervised_user_service =
1057 SupervisedUserServiceFactory::GetForProfile(profile_);
1058 supervised_user_service->AddExtensionInstallRequest(
Devlin Cronin03bf2d22017-12-20 08:21:051059 extension->id(), extension->version());
mamire9609642016-06-28 22:17:541060 }
1061 }
1062 }
1063 return must_remain_disabled;
1064}
1065
1066void SupervisedUserService::OnExtensionInstalled(
1067 content::BrowserContext* browser_context,
1068 const extensions::Extension* extension,
1069 bool is_update) {
1070 // This callback method is responsible for updating extension state and
1071 // approved_extensions_map_ upon extension updates.
1072 if (!is_update)
1073 return;
1074
1075 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1076 const std::string& id = extension->id();
Devlin Cronin03bf2d22017-12-20 08:21:051077 const base::Version& version = extension->version();
mamire9609642016-06-28 22:17:541078
1079 // If an already approved extension is updated without requiring
1080 // new permissions, we update the approved_version.
1081 if (!extension_prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361082 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE) &&
mamire9609642016-06-28 22:17:541083 approved_extensions_map_.count(id) > 0 &&
1084 approved_extensions_map_[id] < version) {
1085 approved_extensions_map_[id] = version;
1086
1087 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1088 supervised_users::kApprovedExtensions, id);
1089 std::unique_ptr<base::Value> version_value(
jdoerrie122c4da2017-03-06 11:12:041090 new base::Value(version.GetString()));
mamire9609642016-06-28 22:17:541091 GetSettingsService()->UpdateSetting(key, std::move(version_value));
1092 }
1093 // Upon extension update, the approved version may (or may not) match the
1094 // installed one. Therefore, a change in extension state might be required.
1095 ChangeExtensionStateIfNecessary(id);
1096}
1097
1098void SupervisedUserService::UpdateApprovedExtensions() {
1099 const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary(
1100 prefs::kSupervisedUserApprovedExtensions);
1101 // Keep track of currently approved extensions. We may need to disable them if
1102 // they are not in the approved map anymore.
1103 std::set<std::string> extensions_to_be_checked;
1104 for (const auto& extension : approved_extensions_map_)
1105 extensions_to_be_checked.insert(extension.first);
1106
1107 approved_extensions_map_.clear();
1108
1109 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
1110 std::string version_str;
1111 bool result = it.value().GetAsString(&version_str);
1112 DCHECK(result);
1113 base::Version version(version_str);
1114 if (version.IsValid()) {
1115 approved_extensions_map_[it.key()] = version;
1116 extensions_to_be_checked.insert(it.key());
1117 } else {
1118 LOG(WARNING) << "Invalid version number " << version_str;
1119 }
1120 }
1121
1122 for (const auto& extension_id : extensions_to_be_checked) {
1123 ChangeExtensionStateIfNecessary(extension_id);
1124 }
1125}
1126
1127void SupervisedUserService::ChangeExtensionStateIfNecessary(
1128 const std::string& extension_id) {
1129 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
1130 const Extension* extension = registry->GetInstalledExtension(extension_id);
1131 // If the extension is not installed (yet), do nothing.
1132 // Things will be handled after installation.
1133 if (!extension)
1134 return;
1135
1136 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1137 ExtensionService* service =
1138 ExtensionSystem::Get(profile_)->extension_service();
1139
1140 ExtensionState state = GetExtensionState(*extension);
1141 switch (state) {
1142 // BLOCKED/FORCED extensions should be already disabled/enabled
1143 // and we don't need to change their state here.
1144 case ExtensionState::BLOCKED:
1145 case ExtensionState::FORCED:
1146 break;
1147 case ExtensionState::REQUIRE_APPROVAL:
Minh X. Nguyen45479012017-08-18 21:35:361148 service->DisableExtension(
1149 extension_id,
1150 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
mamire9609642016-06-28 22:17:541151 break;
1152 case ExtensionState::ALLOWED:
1153 extension_prefs->RemoveDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361154 extension_id,
1155 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
mamire9609642016-06-28 22:17:541156 extension_prefs->RemoveDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361157 extension_id,
1158 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE);
mamire9609642016-06-28 22:17:541159 // If not disabled for other reasons, enable it.
1160 if (extension_prefs->GetDisableReasons(extension_id) ==
Minh X. Nguyen45479012017-08-18 21:35:361161 extensions::disable_reason::DISABLE_NONE) {
mamire9609642016-06-28 22:17:541162 service->EnableExtension(extension_id);
1163 }
1164 break;
1165 }
1166}
1167
bauerb5f8cda92015-10-07 15:36:441168void SupervisedUserService::SetExtensionsActive() {
1169 extensions::ExtensionSystem* extension_system =
1170 extensions::ExtensionSystem::Get(profile_);
1171 extensions::ManagementPolicy* management_policy =
1172 extension_system->management_policy();
1173
1174 if (management_policy) {
1175 if (active_)
1176 management_policy->RegisterProvider(this);
1177 else
1178 management_policy->UnregisterProvider(this);
1179
1180 // Re-check the policy to make sure any new settings get applied.
1181 extension_system->extension_service()->CheckManagementPolicy();
1182 }
1183}
brettw00899e62016-11-12 02:10:171184#endif // BUILDFLAG(ENABLE_EXTENSIONS)
bauerb5f8cda92015-10-07 15:36:441185
1186syncer::ModelTypeSet SupervisedUserService::GetPreferredDataTypes() const {
1187 if (!ProfileIsSupervised())
1188 return syncer::ModelTypeSet();
1189
1190 syncer::ModelTypeSet result;
1191 if (IncludesSyncSessionsType())
1192 result.Put(syncer::SESSIONS);
1193 result.Put(syncer::EXTENSIONS);
1194 result.Put(syncer::EXTENSION_SETTINGS);
1195 result.Put(syncer::APPS);
1196 result.Put(syncer::APP_SETTINGS);
1197 result.Put(syncer::APP_NOTIFICATIONS);
1198 result.Put(syncer::APP_LIST);
1199 return result;
1200}
1201
jam1c5a91492016-02-24 20:47:531202#if !defined(OS_ANDROID)
holte4ef35702017-02-03 03:30:101203void SupervisedUserService::OnStateChanged(syncer::SyncService* sync) {
1204 if (waiting_for_sync_initialization_ && sync->IsEngineInitialized()) {
bauerb5f8cda92015-10-07 15:36:441205 waiting_for_sync_initialization_ = false;
holte4ef35702017-02-03 03:30:101206 sync->RemoveObserver(this);
bauerb5f8cda92015-10-07 15:36:441207 FinishSetupSync();
1208 return;
1209 }
1210
holte4ef35702017-02-03 03:30:101211 DLOG_IF(ERROR, sync->GetAuthError().state() ==
bauerb5f8cda92015-10-07 15:36:441212 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)
1213 << "Credentials rejected";
1214}
1215
1216void SupervisedUserService::OnBrowserSetLastActive(Browser* browser) {
1217 bool profile_became_active = profile_->IsSameProfile(browser->profile());
1218 if (!is_profile_active_ && profile_became_active)
bratell0a7406f2017-03-28 07:46:371219 base::RecordAction(UserMetricsAction("ManagedUsers_OpenProfile"));
bauerb5f8cda92015-10-07 15:36:441220 else if (is_profile_active_ && !profile_became_active)
bratell0a7406f2017-03-28 07:46:371221 base::RecordAction(UserMetricsAction("ManagedUsers_SwitchProfile"));
bauerb5f8cda92015-10-07 15:36:441222
1223 is_profile_active_ = profile_became_active;
1224}
jam1c5a91492016-02-24 20:47:531225#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:441226
1227void SupervisedUserService::OnSiteListUpdated() {
ericwilligers8b92b052016-10-19 22:21:581228 for (SupervisedUserServiceObserver& observer : observer_list_)
1229 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:441230}