blob: 4ac24a67ef7de9552073ef9ae5fc93176ac04c3b [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"
[email protected]0850e842013-01-19 03:44:3113#include "base/memory/ref_counted.h"
treibd3f8b7a2015-04-10 11:41:3314#include "base/path_service.h"
treib40d3ad92015-10-20 18:15:4215#include "base/strings/stringprintf.h"
[email protected]112158af2013-06-07 23:46:1816#include "base/strings/utf_string_conversions.h"
treib2fd187392015-04-16 17:19:3817#include "base/task_runner_util.h"
treibf832a992015-03-24 18:09:2418#include "base/version.h"
avi664c07b2015-12-26 02:18:3119#include "build/build_config.h"
[email protected]5ddfade2014-02-03 10:24:5320#include "chrome/browser/browser_process.h"
bauerb4da36132014-12-26 19:53:1321#include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
[email protected]0850e842013-01-19 03:44:3122#include "chrome/browser/profiles/profile.h"
lwchkg7f133c72016-03-01 16:48:5323#include "chrome/browser/profiles/profile_attributes_entry.h"
24#include "chrome/browser/profiles/profile_attributes_storage.h"
[email protected]5ddfade2014-02-03 10:24:5325#include "chrome/browser/profiles/profile_manager.h"
[email protected]aab946912013-11-06 22:18:5126#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
[email protected]f252df2e2013-06-06 23:47:1927#include "chrome/browser/signin/signin_manager_factory.h"
treibe2082a0e2015-04-08 10:15:3028#include "chrome/browser/supervised_user/experimental/supervised_user_filtering_switches.h"
bauerb5f8cda92015-10-07 15:36:4429#include "chrome/browser/supervised_user/permission_request_creator.h"
[email protected]cce15bb2014-06-17 13:43:5130#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5431#include "chrome/browser/supervised_user/supervised_user_features.h"
32#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
treibab0a39e2014-09-24 14:48:2833#include "chrome/browser/supervised_user/supervised_user_service_observer.h"
[email protected]cce15bb2014-06-17 13:43:5134#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
35#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
[email protected]cce15bb2014-06-17 13:43:5136#include "chrome/browser/supervised_user/supervised_user_site_list.h"
bauerb4da36132014-12-26 19:53:1337#include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
[email protected]a19df3e2013-05-21 00:03:0338#include "chrome/browser/sync/profile_sync_service_factory.h"
[email protected]509ad1a92013-03-19 21:41:0639#include "chrome/browser/ui/browser.h"
[email protected]dfddd022013-07-10 17:29:4840#include "chrome/browser/ui/browser_list.h"
treibd3f8b7a2015-04-10 11:41:3341#include "chrome/common/chrome_paths.h"
[email protected]a19df3e2013-05-21 00:03:0342#include "chrome/common/chrome_switches.h"
[email protected]0850e842013-01-19 03:44:3143#include "chrome/common/pref_names.h"
[email protected]af39f002014-08-22 10:18:1844#include "chrome/grit/generated_resources.h"
maxbogue26f40222016-09-16 20:22:1845#include "components/browser_sync/profile_sync_service.h"
[email protected]f0c8c4992014-05-15 17:37:2646#include "components/pref_registry/pref_registry_syncable.h"
brettwb1fc1b82016-02-02 00:19:0847#include "components/prefs/pref_service.h"
[email protected]7274ef02014-03-24 22:43:4048#include "components/signin/core/browser/profile_oauth2_token_service.h"
[email protected]7fbd3b12014-04-01 11:19:1649#include "components/signin/core/browser/signin_manager.h"
[email protected]63c7f0c2014-03-25 21:12:5950#include "components/signin/core/browser/signin_manager_base.h"
brettwf1958912015-10-07 19:43:1251#include "components/signin/core/common/signin_switches.h"
[email protected]0850e842013-01-19 03:44:3152#include "content/public/browser/browser_thread.h"
[email protected]2056c3b2014-04-07 18:08:5053#include "content/public/browser/user_metrics.h"
[email protected]0850e842013-01-19 03:44:3154#include "ui/base/l10n/l10n_util.h"
55
jam1c5a91492016-02-24 20:47:5356#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:4457#include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service.h"
58#include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service_factory.h"
59#include "chrome/browser/supervised_user/legacy/permission_request_creator_sync.h"
60#include "chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service.h"
61#include "chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service_factory.h"
thestig1b76f1a2015-09-30 22:52:3862#include "chrome/browser/supervised_user/legacy/supervised_user_registration_utility.h"
bauerb5f8cda92015-10-07 15:36:4463#include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_factory.h"
thestig1b76f1a2015-09-30 22:52:3864#endif
65
[email protected]3aacc9c2013-08-08 11:19:3166#if defined(OS_CHROMEOS)
[email protected]4d390782014-08-15 09:22:5867#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
[email protected]83d82d42014-05-16 02:04:4268#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
[email protected]4d390782014-08-15 09:22:5869#include "components/user_manager/user_manager.h"
[email protected]3aacc9c2013-08-08 11:19:3170#endif
71
[email protected]c14a6802014-07-11 21:51:1272#if defined(ENABLE_EXTENSIONS)
treib9e30e302015-04-15 08:12:1673#include "chrome/browser/extensions/extension_service.h"
mamir192d7882016-06-22 17:10:1674#include "chrome/browser/extensions/extension_util.h"
75#include "extensions/browser/extension_prefs.h"
mamire9609642016-06-28 22:17:5476#include "extensions/browser/extension_registry.h"
[email protected]c14a6802014-07-11 21:51:1277#include "extensions/browser/extension_system.h"
[email protected]c14a6802014-07-11 21:51:1278#endif
79
[email protected]f085fdd52014-06-11 18:09:2080#if defined(ENABLE_THEMES)
81#include "chrome/browser/themes/theme_service.h"
82#include "chrome/browser/themes/theme_service_factory.h"
83#endif
84
[email protected]a581ea22013-05-06 12:34:1985using base::DictionaryValue;
[email protected]2056c3b2014-04-07 18:08:5086using base::UserMetricsAction;
[email protected]0850e842013-01-19 03:44:3187using content::BrowserThread;
88
mamir192d7882016-06-22 17:10:1689#if defined(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:5490using extensions::Extension;
91using extensions::ExtensionPrefs;
92using extensions::ExtensionRegistry;
93using extensions::ExtensionSystem;
94#endif
95
96#if defined(ENABLE_EXTENSIONS)
mamir192d7882016-06-22 17:10:1697using extensions::ExtensionPrefs;
98#endif
99
treib22c3a042015-01-15 21:30:13100namespace {
101
treibd3f8b7a2015-04-10 11:41:33102// The URL from which to download a host blacklist if no local one exists yet.
103const char kBlacklistURL[] =
104 "https://www.gstatic.com/chrome/supervised_user/blacklist-20141001-1k.bin";
105// The filename under which we'll store the blacklist (in the user data dir).
106const char kBlacklistFilename[] = "su-blacklist.bin";
107
treib22c3a042015-01-15 21:30:13108const char* const kCustodianInfoPrefs[] = {
109 prefs::kSupervisedUserCustodianName,
110 prefs::kSupervisedUserCustodianEmail,
111 prefs::kSupervisedUserCustodianProfileImageURL,
112 prefs::kSupervisedUserCustodianProfileURL,
113 prefs::kSupervisedUserSecondCustodianName,
114 prefs::kSupervisedUserSecondCustodianEmail,
115 prefs::kSupervisedUserSecondCustodianProfileImageURL,
116 prefs::kSupervisedUserSecondCustodianProfileURL,
117};
118
treib8ecc1eb52015-03-04 18:29:06119void CreateURLAccessRequest(
120 const GURL& url,
121 PermissionRequestCreator* creator,
122 const SupervisedUserService::SuccessCallback& callback) {
123 creator->CreateURLAccessRequest(url, callback);
124}
125
mamire9609642016-06-28 22:17:54126void CreateExtensionInstallRequest(
127 const std::string& id,
128 PermissionRequestCreator* creator,
129 const SupervisedUserService::SuccessCallback& callback) {
130 creator->CreateExtensionInstallRequest(id, callback);
131}
132
treib8ecc1eb52015-03-04 18:29:06133void CreateExtensionUpdateRequest(
treibf832a992015-03-24 18:09:24134 const std::string& id,
treib8ecc1eb52015-03-04 18:29:06135 PermissionRequestCreator* creator,
136 const SupervisedUserService::SuccessCallback& callback) {
treibf832a992015-03-24 18:09:24137 creator->CreateExtensionUpdateRequest(id, callback);
treib8ecc1eb52015-03-04 18:29:06138}
139
mamire9609642016-06-28 22:17:54140// Default callback for AddExtensionInstallRequest.
141void ExtensionInstallRequestSent(const std::string& id, bool success) {
142 VLOG_IF(1, !success) << "Failed sending install request for " << id;
143}
144
treib40d3ad92015-10-20 18:15:42145// Default callback for AddExtensionUpdateRequest.
146void ExtensionUpdateRequestSent(const std::string& id, bool success) {
147 VLOG_IF(1, !success) << "Failed sending update request for " << id;
148}
149
treibd3f8b7a2015-04-10 11:41:33150base::FilePath GetBlacklistPath() {
151 base::FilePath blacklist_dir;
152 PathService::Get(chrome::DIR_USER_DATA, &blacklist_dir);
153 return blacklist_dir.AppendASCII(kBlacklistFilename);
154}
155
treib22c3a042015-01-15 21:30:13156} // namespace
157
bauerb5f8cda92015-10-07 15:36:44158SupervisedUserService::~SupervisedUserService() {
159 DCHECK(!did_init_ || did_shutdown_);
160 url_filter_context_.ui_url_filter()->RemoveObserver(this);
161}
162
163// static
164void SupervisedUserService::RegisterProfilePrefs(
165 user_prefs::PrefRegistrySyncable* registry) {
mamire9609642016-06-28 22:17:54166 registry->RegisterDictionaryPref(prefs::kSupervisedUserApprovedExtensions);
bauerb5f8cda92015-10-07 15:36:44167 registry->RegisterDictionaryPref(prefs::kSupervisedUserManualHosts);
168 registry->RegisterDictionaryPref(prefs::kSupervisedUserManualURLs);
169 registry->RegisterIntegerPref(prefs::kDefaultSupervisedUserFilteringBehavior,
170 SupervisedUserURLFilter::ALLOW);
171 registry->RegisterBooleanPref(prefs::kSupervisedUserCreationAllowed, true);
172 registry->RegisterBooleanPref(prefs::kSupervisedUserSafeSites, true);
173 for (const char* pref : kCustodianInfoPrefs) {
174 registry->RegisterStringPref(pref, std::string());
175 }
176}
177
178void SupervisedUserService::Init() {
179 DCHECK(!did_init_);
180 did_init_ = true;
181 DCHECK(GetSettingsService()->IsReady());
182
183 pref_change_registrar_.Init(profile_->GetPrefs());
184 pref_change_registrar_.Add(
185 prefs::kSupervisedUserId,
186 base::Bind(&SupervisedUserService::OnSupervisedUserIdChanged,
187 base::Unretained(this)));
188 pref_change_registrar_.Add(
bauerbb519f8252016-05-13 09:16:39189 prefs::kForceSessionSync,
190 base::Bind(&SupervisedUserService::OnForceSessionSyncChanged,
bauerb5f8cda92015-10-07 15:36:44191 base::Unretained(this)));
192
maxbogue0a379452016-09-22 21:35:05193 browser_sync::ProfileSyncService* sync_service =
bauerb5f8cda92015-10-07 15:36:44194 ProfileSyncServiceFactory::GetForProfile(profile_);
195 // Can be null in tests.
196 if (sync_service)
197 sync_service->AddPreferenceProvider(this);
198
199 std::string client_id = component_updater::SupervisedUserWhitelistInstaller::
200 ClientIdForProfilePath(profile_->GetPath());
201 whitelist_service_.reset(new SupervisedUserWhitelistService(
202 profile_->GetPrefs(),
203 g_browser_process->supervised_user_whitelist_installer(), client_id));
204 whitelist_service_->AddSiteListsChangedCallback(
205 base::Bind(&SupervisedUserService::OnSiteListsChanged,
206 weak_ptr_factory_.GetWeakPtr()));
207
208 SetActive(ProfileIsSupervised());
209}
210
211void SupervisedUserService::SetDelegate(Delegate* delegate) {
212 if (delegate) {
213 // Changing delegates isn't allowed.
214 DCHECK(!delegate_);
215 } else {
216 // If the delegate is removed, deactivate first to give the old delegate a
217 // chance to clean up.
218 SetActive(false);
219 }
220 delegate_ = delegate;
221}
222
223scoped_refptr<const SupervisedUserURLFilter>
224SupervisedUserService::GetURLFilterForIOThread() {
225 return url_filter_context_.io_url_filter();
226}
227
228SupervisedUserURLFilter* SupervisedUserService::GetURLFilterForUIThread() {
229 return url_filter_context_.ui_url_filter();
230}
231
232SupervisedUserWhitelistService* SupervisedUserService::GetWhitelistService() {
233 return whitelist_service_.get();
234}
235
236bool SupervisedUserService::AccessRequestsEnabled() {
237 return FindEnabledPermissionRequestCreator(0) < permissions_creators_.size();
238}
239
240void SupervisedUserService::AddURLAccessRequest(
241 const GURL& url,
242 const SuccessCallback& callback) {
treib17f2e382016-10-14 11:42:53243 GURL effective_url = GetURLFilterForUIThread()->GetEmbeddedURL(url);
244 if (!effective_url.is_valid())
245 effective_url = url;
bauerb5f8cda92015-10-07 15:36:44246 AddPermissionRequestInternal(
247 base::Bind(CreateURLAccessRequest,
treib17f2e382016-10-14 11:42:53248 SupervisedUserURLFilter::Normalize(effective_url)),
bauerb5f8cda92015-10-07 15:36:44249 callback, 0);
250}
251
atanasovaac676032016-04-05 16:31:05252void SupervisedUserService::ReportURL(const GURL& url,
253 const SuccessCallback& callback) {
254 if (url_reporter_)
255 url_reporter_->ReportUrl(url, callback);
256 else
257 callback.Run(false);
258}
259
mamire9609642016-06-28 22:17:54260void SupervisedUserService::AddExtensionInstallRequest(
261 const std::string& extension_id,
262 const base::Version& version,
263 const SuccessCallback& callback) {
264 std::string id = GetExtensionRequestId(extension_id, version);
265 AddPermissionRequestInternal(base::Bind(CreateExtensionInstallRequest, id),
266 callback, 0);
267}
268
269void SupervisedUserService::AddExtensionInstallRequest(
270 const std::string& extension_id,
271 const base::Version& version) {
272 std::string id = GetExtensionRequestId(extension_id, version);
273 AddPermissionRequestInternal(base::Bind(CreateExtensionInstallRequest, id),
274 base::Bind(ExtensionInstallRequestSent, id), 0);
275}
276
bauerb5f8cda92015-10-07 15:36:44277void SupervisedUserService::AddExtensionUpdateRequest(
278 const std::string& extension_id,
279 const base::Version& version,
280 const SuccessCallback& callback) {
mamire9609642016-06-28 22:17:54281 std::string id = GetExtensionRequestId(extension_id, version);
bauerb5f8cda92015-10-07 15:36:44282 AddPermissionRequestInternal(
treib40d3ad92015-10-20 18:15:42283 base::Bind(CreateExtensionUpdateRequest, id), callback, 0);
284}
285
286void SupervisedUserService::AddExtensionUpdateRequest(
287 const std::string& extension_id,
288 const base::Version& version) {
mamire9609642016-06-28 22:17:54289 std::string id = GetExtensionRequestId(extension_id, version);
treib40d3ad92015-10-20 18:15:42290 AddExtensionUpdateRequest(extension_id, version,
291 base::Bind(ExtensionUpdateRequestSent, id));
292}
293
294// static
mamire9609642016-06-28 22:17:54295std::string SupervisedUserService::GetExtensionRequestId(
treib40d3ad92015-10-20 18:15:42296 const std::string& extension_id,
297 const base::Version& version) {
298 return base::StringPrintf("%s:%s", extension_id.c_str(),
299 version.GetString().c_str());
bauerb5f8cda92015-10-07 15:36:44300}
301
302std::string SupervisedUserService::GetCustodianEmailAddress() const {
treib2170ea02015-10-13 14:55:12303 std::string email = profile_->GetPrefs()->GetString(
bauerb5f8cda92015-10-07 15:36:44304 prefs::kSupervisedUserCustodianEmail);
305#if defined(OS_CHROMEOS)
treib2170ea02015-10-13 14:55:12306 // |GetActiveUser()| can return null in unit tests.
307 if (email.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
308 email = chromeos::ChromeUserManager::Get()
bauerb5f8cda92015-10-07 15:36:44309 ->GetSupervisedUserManager()
310 ->GetManagerDisplayEmail(
311 user_manager::UserManager::Get()->GetActiveUser()->email());
312 }
313#endif
treib2170ea02015-10-13 14:55:12314 return email;
bauerb5f8cda92015-10-07 15:36:44315}
316
317std::string SupervisedUserService::GetCustodianName() const {
318 std::string name = profile_->GetPrefs()->GetString(
319 prefs::kSupervisedUserCustodianName);
320#if defined(OS_CHROMEOS)
treib2170ea02015-10-13 14:55:12321 // |GetActiveUser()| can return null in unit tests.
322 if (name.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
bauerb5f8cda92015-10-07 15:36:44323 name = base::UTF16ToUTF8(chromeos::ChromeUserManager::Get()
324 ->GetSupervisedUserManager()
325 ->GetManagerDisplayName(
326 user_manager::UserManager::Get()->GetActiveUser()->email()));
327 }
328#endif
329 return name.empty() ? GetCustodianEmailAddress() : name;
330}
331
332std::string SupervisedUserService::GetSecondCustodianEmailAddress() const {
333 return profile_->GetPrefs()->GetString(
334 prefs::kSupervisedUserSecondCustodianEmail);
335}
336
337std::string SupervisedUserService::GetSecondCustodianName() const {
338 std::string name = profile_->GetPrefs()->GetString(
339 prefs::kSupervisedUserSecondCustodianName);
340 return name.empty() ? GetSecondCustodianEmailAddress() : name;
341}
342
treib2170ea02015-10-13 14:55:12343base::string16 SupervisedUserService::GetExtensionsLockedMessage() const {
344 return l10n_util::GetStringFUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER,
345 base::UTF8ToUTF16(GetCustodianName()));
346}
347
jam1c5a91492016-02-24 20:47:53348#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44349void SupervisedUserService::InitSync(const std::string& refresh_token) {
350 StartSetupSync();
351
352 ProfileOAuth2TokenService* token_service =
353 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
354 token_service->UpdateCredentials(supervised_users::kSupervisedUserPseudoEmail,
355 refresh_token);
356
357 FinishSetupSyncWhenReady();
358}
359
360void SupervisedUserService::RegisterAndInitSync(
361 SupervisedUserRegistrationUtility* registration_utility,
362 Profile* custodian_profile,
363 const std::string& supervised_user_id,
364 const AuthErrorCallback& callback) {
365 DCHECK(ProfileIsSupervised());
366 DCHECK(!custodian_profile->IsSupervised());
367
368 base::string16 name = base::UTF8ToUTF16(
369 profile_->GetPrefs()->GetString(prefs::kProfileName));
370 int avatar_index = profile_->GetPrefs()->GetInteger(
371 prefs::kProfileAvatarIndex);
372 SupervisedUserRegistrationInfo info(name, avatar_index);
373 registration_utility->Register(
374 supervised_user_id,
375 info,
376 base::Bind(&SupervisedUserService::OnSupervisedUserRegistered,
377 weak_ptr_factory_.GetWeakPtr(), callback, custodian_profile));
378
379 // Fetch the custodian's profile information, to store the name.
380 // TODO(pamg): If --google-profile-info (flag: switches::kGoogleProfileInfo)
lwchkg7f133c72016-03-01 16:48:53381 // is ever enabled, take the name from the ProfileAttributesStorage instead.
bauerb5f8cda92015-10-07 15:36:44382 CustodianProfileDownloaderService* profile_downloader_service =
383 CustodianProfileDownloaderServiceFactory::GetForProfile(
384 custodian_profile);
385 profile_downloader_service->DownloadProfile(
386 base::Bind(&SupervisedUserService::OnCustodianProfileDownloaded,
387 weak_ptr_factory_.GetWeakPtr()));
388}
jam1c5a91492016-02-24 20:47:53389#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44390
391void SupervisedUserService::AddNavigationBlockedCallback(
392 const NavigationBlockedCallback& callback) {
393 navigation_blocked_callbacks_.push_back(callback);
394}
395
396void SupervisedUserService::DidBlockNavigation(
397 content::WebContents* web_contents) {
398 for (const auto& callback : navigation_blocked_callbacks_)
399 callback.Run(web_contents);
400}
401
402void SupervisedUserService::AddObserver(
403 SupervisedUserServiceObserver* observer) {
404 observer_list_.AddObserver(observer);
405}
406
407void SupervisedUserService::RemoveObserver(
408 SupervisedUserServiceObserver* observer) {
409 observer_list_.RemoveObserver(observer);
410}
411
412void SupervisedUserService::AddPermissionRequestCreator(
dchengf624e472016-04-12 08:33:17413 std::unique_ptr<PermissionRequestCreator> creator) {
bauerb5f8cda92015-10-07 15:36:44414 permissions_creators_.push_back(creator.release());
415}
416
atanasovaac676032016-04-05 16:31:05417void SupervisedUserService::SetSafeSearchURLReporter(
dchengf624e472016-04-12 08:33:17418 std::unique_ptr<SafeSearchURLReporter> reporter) {
atanasovaac676032016-04-05 16:31:05419 url_reporter_ = std::move(reporter);
420}
421
bauerbb519f8252016-05-13 09:16:39422bool SupervisedUserService::IncludesSyncSessionsType() const {
423 return includes_sync_sessions_type_;
424}
425
[email protected]cce15bb2014-06-17 13:43:51426SupervisedUserService::URLFilterContext::URLFilterContext()
427 : ui_url_filter_(new SupervisedUserURLFilter),
428 io_url_filter_(new SupervisedUserURLFilter) {}
429SupervisedUserService::URLFilterContext::~URLFilterContext() {}
[email protected]0850e842013-01-19 03:44:31430
[email protected]cce15bb2014-06-17 13:43:51431SupervisedUserURLFilter*
432SupervisedUserService::URLFilterContext::ui_url_filter() const {
[email protected]0850e842013-01-19 03:44:31433 return ui_url_filter_.get();
434}
435
[email protected]cce15bb2014-06-17 13:43:51436SupervisedUserURLFilter*
437SupervisedUserService::URLFilterContext::io_url_filter() const {
[email protected]0850e842013-01-19 03:44:31438 return io_url_filter_.get();
439}
440
[email protected]cce15bb2014-06-17 13:43:51441void SupervisedUserService::URLFilterContext::SetDefaultFilteringBehavior(
442 SupervisedUserURLFilter::FilteringBehavior behavior) {
[email protected]0850e842013-01-19 03:44:31443 ui_url_filter_->SetDefaultFilteringBehavior(behavior);
444 BrowserThread::PostTask(
445 BrowserThread::IO,
446 FROM_HERE,
[email protected]cce15bb2014-06-17 13:43:51447 base::Bind(&SupervisedUserURLFilter::SetDefaultFilteringBehavior,
tzik07cace42016-09-01 04:21:25448 io_url_filter_, behavior));
[email protected]0850e842013-01-19 03:44:31449}
450
[email protected]cce15bb2014-06-17 13:43:51451void SupervisedUserService::URLFilterContext::LoadWhitelists(
bauerb95a50682015-01-07 17:04:15452 const std::vector<scoped_refptr<SupervisedUserSiteList> >& site_lists) {
453 ui_url_filter_->LoadWhitelists(site_lists);
454 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
455 base::Bind(&SupervisedUserURLFilter::LoadWhitelists,
456 io_url_filter_, site_lists));
[email protected]0850e842013-01-19 03:44:31457}
458
treib9cc1b112016-01-08 10:08:01459void SupervisedUserService::URLFilterContext::SetBlacklist(
460 const SupervisedUserBlacklist* blacklist) {
461 ui_url_filter_->SetBlacklist(blacklist);
462 BrowserThread::PostTask(
463 BrowserThread::IO,
464 FROM_HERE,
465 base::Bind(&SupervisedUserURLFilter::SetBlacklist,
466 io_url_filter_,
467 blacklist));
468}
469
470bool SupervisedUserService::URLFilterContext::HasBlacklist() const {
471 return ui_url_filter_->HasBlacklist();
treib4edbded2014-09-05 08:43:55472}
473
[email protected]cce15bb2014-06-17 13:43:51474void SupervisedUserService::URLFilterContext::SetManualHosts(
dchengf624e472016-04-12 08:33:17475 std::unique_ptr<std::map<std::string, bool>> host_map) {
[email protected]5e022292013-02-06 16:42:17476 ui_url_filter_->SetManualHosts(host_map.get());
[email protected]0850e842013-01-19 03:44:31477 BrowserThread::PostTask(
478 BrowserThread::IO,
479 FROM_HERE,
[email protected]cce15bb2014-06-17 13:43:51480 base::Bind(&SupervisedUserURLFilter::SetManualHosts,
[email protected]5e022292013-02-06 16:42:17481 io_url_filter_, base::Owned(host_map.release())));
[email protected]0850e842013-01-19 03:44:31482}
483
[email protected]cce15bb2014-06-17 13:43:51484void SupervisedUserService::URLFilterContext::SetManualURLs(
dchengf624e472016-04-12 08:33:17485 std::unique_ptr<std::map<GURL, bool>> url_map) {
[email protected]5e022292013-02-06 16:42:17486 ui_url_filter_->SetManualURLs(url_map.get());
[email protected]0850e842013-01-19 03:44:31487 BrowserThread::PostTask(
488 BrowserThread::IO,
489 FROM_HERE,
[email protected]cce15bb2014-06-17 13:43:51490 base::Bind(&SupervisedUserURLFilter::SetManualURLs,
[email protected]5e022292013-02-06 16:42:17491 io_url_filter_, base::Owned(url_map.release())));
[email protected]0850e842013-01-19 03:44:31492}
493
treib22c3a042015-01-15 21:30:13494void SupervisedUserService::URLFilterContext::Clear() {
495 ui_url_filter_->Clear();
496 BrowserThread::PostTask(
497 BrowserThread::IO,
498 FROM_HERE,
499 base::Bind(&SupervisedUserURLFilter::Clear,
500 io_url_filter_));
501}
502
bauerb5f8cda92015-10-07 15:36:44503void SupervisedUserService::URLFilterContext::InitAsyncURLChecker(
504 const scoped_refptr<net::URLRequestContextGetter>& context) {
505 ui_url_filter_->InitAsyncURLChecker(context.get());
506 BrowserThread::PostTask(
vmpstra34d11322016-03-21 20:28:47507 BrowserThread::IO, FROM_HERE,
508 base::Bind(&SupervisedUserURLFilter::InitAsyncURLChecker, io_url_filter_,
509 base::RetainedRef(context)));
bauerb5f8cda92015-10-07 15:36:44510}
511
treib9cc1b112016-01-08 10:08:01512bool SupervisedUserService::URLFilterContext::HasAsyncURLChecker() const {
513 return ui_url_filter_->HasAsyncURLChecker();
514}
515
516void SupervisedUserService::URLFilterContext::ClearAsyncURLChecker() {
517 ui_url_filter_->ClearAsyncURLChecker();
treib4edbded2014-09-05 08:43:55518 BrowserThread::PostTask(
519 BrowserThread::IO,
520 FROM_HERE,
treib9cc1b112016-01-08 10:08:01521 base::Bind(&SupervisedUserURLFilter::ClearAsyncURLChecker,
522 io_url_filter_));
treib4edbded2014-09-05 08:43:55523}
524
[email protected]cce15bb2014-06-17 13:43:51525SupervisedUserService::SupervisedUserService(Profile* profile)
fhorschig1f351f02014-09-30 12:30:22526 : includes_sync_sessions_type_(true),
527 profile_(profile),
[email protected]f085fdd52014-06-11 18:09:20528 active_(false),
529 delegate_(NULL),
[email protected]a243d644c2013-06-20 18:37:55530 waiting_for_sync_initialization_(false),
[email protected]dfddd022013-07-10 17:29:48531 is_profile_active_(false),
[email protected]3a276ff2014-08-12 14:22:09532 did_init_(false),
[email protected]8052b242013-11-15 16:40:55533 did_shutdown_(false),
treib9cc1b112016-01-08 10:08:01534 blacklist_state_(BlacklistLoadState::NOT_LOADED),
mamire9609642016-06-28 22:17:54535#if defined(ENABLE_EXTENSIONS)
536 registry_observer_(this),
537#endif
[email protected]8052b242013-11-15 16:40:55538 weak_ptr_factory_(this) {
bauerbce9a1a82014-12-18 13:34:24539 url_filter_context_.ui_url_filter()->AddObserver(this);
mamire9609642016-06-28 22:17:54540#if defined(ENABLE_EXTENSIONS)
541 registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
542#endif
[email protected]a243d644c2013-06-20 18:37:55543}
[email protected]0850e842013-01-19 03:44:31544
[email protected]cce15bb2014-06-17 13:43:51545void SupervisedUserService::SetActive(bool active) {
[email protected]f085fdd52014-06-11 18:09:20546 if (active_ == active)
[email protected]0850e842013-01-19 03:44:31547 return;
[email protected]f085fdd52014-06-11 18:09:20548 active_ = active;
549
550 if (!delegate_ || !delegate_->SetActive(active_)) {
551 if (active_) {
jam1c5a91492016-02-24 20:47:53552#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20553 SupervisedUserPrefMappingServiceFactory::GetForBrowserContext(profile_)
554 ->Init();
555
avi556c05022014-12-22 23:31:43556 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
[email protected]d20d0432014-06-12 17:14:05557 if (command_line->HasSwitch(switches::kSupervisedUserSyncToken)) {
[email protected]f085fdd52014-06-11 18:09:20558 InitSync(
[email protected]d20d0432014-06-12 17:14:05559 command_line->GetSwitchValueASCII(
560 switches::kSupervisedUserSyncToken));
[email protected]f085fdd52014-06-11 18:09:20561 }
562
563 ProfileOAuth2TokenService* token_service =
564 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
[email protected]cce15bb2014-06-17 13:43:51565 token_service->LoadCredentials(
566 supervised_users::kSupervisedUserPseudoEmail);
[email protected]6e08b9a62014-07-08 00:32:48567
treib531fc7312014-12-09 12:49:20568 permissions_creators_.push_back(new PermissionRequestCreatorSync(
569 GetSettingsService(),
570 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(
571 profile_),
572 ProfileSyncServiceFactory::GetForProfile(profile_),
573 GetSupervisedUserName(),
574 profile_->GetPrefs()->GetString(prefs::kSupervisedUserId)));
575
[email protected]6e08b9a62014-07-08 00:32:48576 SetupSync();
bauerb7f3b8542015-06-29 19:56:19577#else
578 NOTREACHED();
579#endif
[email protected]f085fdd52014-06-11 18:09:20580 }
[email protected]e861bba2013-06-17 15:20:54581 }
[email protected]0850e842013-01-19 03:44:31582
[email protected]f085fdd52014-06-11 18:09:20583 // Now activate/deactivate anything not handled by the delegate yet.
[email protected]e1480482013-09-11 11:49:58584
[email protected]f085fdd52014-06-11 18:09:20585#if defined(ENABLE_THEMES)
586 // Re-set the default theme to turn the SU theme on/off.
587 ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile_);
treib9e30e302015-04-15 08:12:16588 if (theme_service->UsingDefaultTheme() || theme_service->UsingSystemTheme())
589 theme_service->UseDefaultTheme();
[email protected]f085fdd52014-06-11 18:09:20590#endif
[email protected]a19df3e2013-05-21 00:03:03591
maxbogue0a379452016-09-22 21:35:05592 browser_sync::ProfileSyncService* sync_service =
bauerbf03588b92014-10-27 13:40:15593 ProfileSyncServiceFactory::GetForProfile(profile_);
594 sync_service->SetEncryptEverythingAllowed(!active_);
595
bauerbd3a36cc42014-10-01 13:05:49596 GetSettingsService()->SetActive(active_);
[email protected]a243d644c2013-06-20 18:37:55597
[email protected]c14a6802014-07-11 21:51:12598#if defined(ENABLE_EXTENSIONS)
599 SetExtensionsActive();
600#endif
[email protected]0850e842013-01-19 03:44:31601
[email protected]f085fdd52014-06-11 18:09:20602 if (active_) {
[email protected]f085fdd52014-06-11 18:09:20603 pref_change_registrar_.Add(
[email protected]d20d0432014-06-12 17:14:05604 prefs::kDefaultSupervisedUserFilteringBehavior,
[email protected]cce15bb2014-06-17 13:43:51605 base::Bind(&SupervisedUserService::OnDefaultFilteringBehaviorChanged,
[email protected]f085fdd52014-06-11 18:09:20606 base::Unretained(this)));
mamire9609642016-06-28 22:17:54607#if defined(ENABLE_EXTENSIONS)
608 pref_change_registrar_.Add(
609 prefs::kSupervisedUserApprovedExtensions,
610 base::Bind(&SupervisedUserService::UpdateApprovedExtensions,
611 base::Unretained(this)));
612#endif
treib9cc1b112016-01-08 10:08:01613 pref_change_registrar_.Add(prefs::kSupervisedUserSafeSites,
614 base::Bind(&SupervisedUserService::OnSafeSitesSettingChanged,
615 base::Unretained(this)));
[email protected]d20d0432014-06-12 17:14:05616 pref_change_registrar_.Add(prefs::kSupervisedUserManualHosts,
[email protected]cce15bb2014-06-17 13:43:51617 base::Bind(&SupervisedUserService::UpdateManualHosts,
[email protected]f085fdd52014-06-11 18:09:20618 base::Unretained(this)));
[email protected]d20d0432014-06-12 17:14:05619 pref_change_registrar_.Add(prefs::kSupervisedUserManualURLs,
[email protected]cce15bb2014-06-17 13:43:51620 base::Bind(&SupervisedUserService::UpdateManualURLs,
[email protected]f085fdd52014-06-11 18:09:20621 base::Unretained(this)));
treib22c3a042015-01-15 21:30:13622 for (const char* pref : kCustodianInfoPrefs) {
623 pref_change_registrar_.Add(pref,
624 base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
625 base::Unretained(this)));
626 }
[email protected]f085fdd52014-06-11 18:09:20627
628 // Initialize the filter.
629 OnDefaultFilteringBehaviorChanged();
treib9cc1b112016-01-08 10:08:01630 OnSafeSitesSettingChanged();
bauerb4da36132014-12-26 19:53:13631 whitelist_service_->Init();
[email protected]f085fdd52014-06-11 18:09:20632 UpdateManualHosts();
633 UpdateManualURLs();
[email protected]0850e842013-01-19 03:44:31634
mamire9609642016-06-28 22:17:54635#if defined(ENABLE_EXTENSIONS)
636 UpdateApprovedExtensions();
637#endif
638
jam1c5a91492016-02-24 20:47:53639#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20640 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
641 // http://crbug.com/313377
642 BrowserList::AddObserver(this);
[email protected]975677d2013-11-14 16:15:34643#endif
[email protected]f085fdd52014-06-11 18:09:20644 } else {
bauerbd3a36cc42014-10-01 13:05:49645 permissions_creators_.clear();
atanasovaac676032016-04-05 16:31:05646 url_reporter_.reset();
[email protected]dfddd022013-07-10 17:29:48647
[email protected]d20d0432014-06-12 17:14:05648 pref_change_registrar_.Remove(
649 prefs::kDefaultSupervisedUserFilteringBehavior);
mamire9609642016-06-28 22:17:54650#if defined(ENABLE_EXTENSIONS)
651 pref_change_registrar_.Remove(prefs::kSupervisedUserApprovedExtensions);
652#endif
[email protected]d20d0432014-06-12 17:14:05653 pref_change_registrar_.Remove(prefs::kSupervisedUserManualHosts);
654 pref_change_registrar_.Remove(prefs::kSupervisedUserManualURLs);
treib22c3a042015-01-15 21:30:13655 for (const char* pref : kCustodianInfoPrefs) {
656 pref_change_registrar_.Remove(pref);
657 }
658
659 url_filter_context_.Clear();
660 FOR_EACH_OBSERVER(
661 SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
[email protected]f085fdd52014-06-11 18:09:20662
jam1c5a91492016-02-24 20:47:53663#if !defined(OS_ANDROID)
[email protected]3a276ff2014-08-12 14:22:09664 if (waiting_for_sync_initialization_)
665 ProfileSyncServiceFactory::GetForProfile(profile_)->RemoveObserver(this);
[email protected]f085fdd52014-06-11 18:09:20666
[email protected]f085fdd52014-06-11 18:09:20667 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
668 // http://crbug.com/313377
669 BrowserList::RemoveObserver(this);
670#endif
671 }
[email protected]0850e842013-01-19 03:44:31672}
673
jam1c5a91492016-02-24 20:47:53674#if !defined(OS_ANDROID)
[email protected]cce15bb2014-06-17 13:43:51675void SupervisedUserService::OnCustodianProfileDownloaded(
[email protected]0085863a2013-12-06 21:19:03676 const base::string16& full_name) {
[email protected]d20d0432014-06-12 17:14:05677 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
[email protected]6778fed2013-12-24 20:09:37678 base::UTF16ToUTF8(full_name));
[email protected]acfcfbb2013-05-13 18:01:27679}
680
[email protected]cce15bb2014-06-17 13:43:51681void SupervisedUserService::OnSupervisedUserRegistered(
[email protected]514fcf22013-08-13 06:37:24682 const AuthErrorCallback& callback,
[email protected]f252df2e2013-06-06 23:47:19683 Profile* custodian_profile,
[email protected]acfcfbb2013-05-13 18:01:27684 const GoogleServiceAuthError& auth_error,
685 const std::string& token) {
[email protected]514fcf22013-08-13 06:37:24686 if (auth_error.state() == GoogleServiceAuthError::NONE) {
687 InitSync(token);
688 SigninManagerBase* signin =
689 SigninManagerFactory::GetForProfile(custodian_profile);
bzanotti1b5be292015-08-31 12:10:05690 profile_->GetPrefs()->SetString(
691 prefs::kSupervisedUserCustodianEmail,
692 signin->GetAuthenticatedAccountInfo().email);
[email protected]5ddfade2014-02-03 10:24:53693
[email protected]cce15bb2014-06-17 13:43:51694 // The supervised user profile is now ready for use.
lwchkg7f133c72016-03-01 16:48:53695 ProfileAttributesEntry* entry = nullptr;
696 bool has_entry =
697 g_browser_process->profile_manager()->GetProfileAttributesStorage().
698 GetProfileAttributesWithPath(profile_->GetPath(), &entry);
699 DCHECK(has_entry);
700 entry->SetIsOmitted(false);
[email protected]514fcf22013-08-13 06:37:24701 } else {
[email protected]acfcfbb2013-05-13 18:01:27702 DCHECK_EQ(std::string(), token);
[email protected]acfcfbb2013-05-13 18:01:27703 }
704
[email protected]514fcf22013-08-13 06:37:24705 callback.Run(auth_error);
[email protected]acfcfbb2013-05-13 18:01:27706}
bauerb5f8cda92015-10-07 15:36:44707void SupervisedUserService::SetupSync() {
708 StartSetupSync();
709 FinishSetupSyncWhenReady();
710}
711
712void SupervisedUserService::StartSetupSync() {
713 // Tell the sync service that setup is in progress so we don't start syncing
714 // until we've finished configuration.
tommyclif3a1551e2016-06-21 18:11:23715 sync_blocker_ = ProfileSyncServiceFactory::GetForProfile(profile_)
716 ->GetSetupInProgressHandle();
bauerb5f8cda92015-10-07 15:36:44717}
718
719void SupervisedUserService::FinishSetupSyncWhenReady() {
720 // If we're already waiting for the Sync backend, there's nothing to do here.
721 if (waiting_for_sync_initialization_)
722 return;
723
724 // Continue in FinishSetupSync() once the Sync backend has been initialized.
maxbogue0a379452016-09-22 21:35:05725 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:44726 ProfileSyncServiceFactory::GetForProfile(profile_);
zea32a7684cf2016-02-24 20:41:48727 if (service->IsBackendInitialized()) {
bauerb5f8cda92015-10-07 15:36:44728 FinishSetupSync();
729 } else {
730 service->AddObserver(this);
731 waiting_for_sync_initialization_ = true;
732 }
733}
734
735void SupervisedUserService::FinishSetupSync() {
maxbogue0a379452016-09-22 21:35:05736 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:44737 ProfileSyncServiceFactory::GetForProfile(profile_);
738 DCHECK(service->IsBackendInitialized());
bauerb5f8cda92015-10-07 15:36:44739
740 // Sync nothing (except types which are set via GetPreferredDataTypes).
741 bool sync_everything = false;
742 syncer::ModelTypeSet synced_datatypes;
743 service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
744
745 // Notify ProfileSyncService that we are done with configuration.
tommyclif3a1551e2016-06-21 18:11:23746 sync_blocker_.reset();
maxboguefe00952a2016-01-19 19:02:01747 service->SetFirstSetupComplete();
bauerb5f8cda92015-10-07 15:36:44748}
749#endif
750
751bool SupervisedUserService::ProfileIsSupervised() const {
752 return profile_->IsSupervised();
753}
754
755void SupervisedUserService::OnCustodianInfoChanged() {
756 FOR_EACH_OBSERVER(
757 SupervisedUserServiceObserver, observer_list_, OnCustodianInfoChanged());
758}
759
760SupervisedUserSettingsService* SupervisedUserService::GetSettingsService() {
761 return SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
762}
763
764size_t SupervisedUserService::FindEnabledPermissionRequestCreator(
765 size_t start) {
766 for (size_t i = start; i < permissions_creators_.size(); ++i) {
767 if (permissions_creators_[i]->IsEnabled())
768 return i;
769 }
770 return permissions_creators_.size();
771}
772
773void SupervisedUserService::AddPermissionRequestInternal(
774 const CreatePermissionRequestCallback& create_request,
775 const SuccessCallback& callback,
776 size_t index) {
777 // Find a permission request creator that is enabled.
778 size_t next_index = FindEnabledPermissionRequestCreator(index);
779 if (next_index >= permissions_creators_.size()) {
780 callback.Run(false);
781 return;
782 }
783
784 create_request.Run(
785 permissions_creators_[next_index],
786 base::Bind(&SupervisedUserService::OnPermissionRequestIssued,
787 weak_ptr_factory_.GetWeakPtr(), create_request,
788 callback, next_index));
789}
790
791void SupervisedUserService::OnPermissionRequestIssued(
792 const CreatePermissionRequestCallback& create_request,
793 const SuccessCallback& callback,
794 size_t index,
795 bool success) {
796 if (success) {
797 callback.Run(true);
798 return;
799 }
800
801 AddPermissionRequestInternal(create_request, callback, index + 1);
802}
803
804void SupervisedUserService::OnSupervisedUserIdChanged() {
805 SetActive(ProfileIsSupervised());
806}
807
808void SupervisedUserService::OnDefaultFilteringBehaviorChanged() {
809 int behavior_value = profile_->GetPrefs()->GetInteger(
810 prefs::kDefaultSupervisedUserFilteringBehavior);
811 SupervisedUserURLFilter::FilteringBehavior behavior =
812 SupervisedUserURLFilter::BehaviorFromInt(behavior_value);
813 url_filter_context_.SetDefaultFilteringBehavior(behavior);
814
815 FOR_EACH_OBSERVER(
816 SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
817}
818
treib9cc1b112016-01-08 10:08:01819void SupervisedUserService::OnSafeSitesSettingChanged() {
820 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
821 if (use_blacklist != url_filter_context_.HasBlacklist()) {
822 if (use_blacklist && blacklist_state_ == BlacklistLoadState::NOT_LOADED) {
823 LoadBlacklist(GetBlacklistPath(), GURL(kBlacklistURL));
824 } else if (!use_blacklist ||
825 blacklist_state_ == BlacklistLoadState::LOADED) {
826 // Either the blacklist was turned off, or it was turned on but has
827 // already been loaded previously. Just update the setting.
828 UpdateBlacklist();
829 }
830 // Else: The blacklist was enabled, but the load is already in progress.
831 // Do nothing - we'll check the setting again when the load finishes.
832 }
833
834 bool use_online_check =
835 supervised_users::IsSafeSitesOnlineCheckEnabled(profile_);
treibe821d6542016-01-21 01:10:19836 if (use_online_check != url_filter_context_.HasAsyncURLChecker()) {
treib9cc1b112016-01-08 10:08:01837 if (use_online_check)
838 url_filter_context_.InitAsyncURLChecker(profile_->GetRequestContext());
839 else
840 url_filter_context_.ClearAsyncURLChecker();
841 }
842}
843
bauerb5f8cda92015-10-07 15:36:44844void SupervisedUserService::OnSiteListsChanged(
845 const std::vector<scoped_refptr<SupervisedUserSiteList> >& site_lists) {
atanasova9572aaf2016-02-26 18:08:26846 whitelists_ = site_lists;
bauerb5f8cda92015-10-07 15:36:44847 url_filter_context_.LoadWhitelists(site_lists);
848}
849
850void SupervisedUserService::LoadBlacklist(const base::FilePath& path,
851 const GURL& url) {
treib9cc1b112016-01-08 10:08:01852 DCHECK(blacklist_state_ == BlacklistLoadState::NOT_LOADED);
853 blacklist_state_ = BlacklistLoadState::LOAD_STARTED;
bauerb5f8cda92015-10-07 15:36:44854 base::PostTaskAndReplyWithResult(
855 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
856 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(),
857 FROM_HERE,
858 base::Bind(&base::PathExists, path),
859 base::Bind(&SupervisedUserService::OnBlacklistFileChecked,
860 weak_ptr_factory_.GetWeakPtr(), path, url));
861}
862
863void SupervisedUserService::OnBlacklistFileChecked(const base::FilePath& path,
864 const GURL& url,
865 bool file_exists) {
treib9cc1b112016-01-08 10:08:01866 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
bauerb5f8cda92015-10-07 15:36:44867 if (file_exists) {
868 LoadBlacklistFromFile(path);
869 return;
870 }
871
872 DCHECK(!blacklist_downloader_);
873 blacklist_downloader_.reset(new FileDownloader(
874 url,
875 path,
876 false,
877 profile_->GetRequestContext(),
878 base::Bind(&SupervisedUserService::OnBlacklistDownloadDone,
879 base::Unretained(this), path)));
880}
881
882void SupervisedUserService::LoadBlacklistFromFile(const base::FilePath& path) {
treib9cc1b112016-01-08 10:08:01883 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
884 blacklist_.ReadFromFile(
885 path,
886 base::Bind(&SupervisedUserService::OnBlacklistLoaded,
887 base::Unretained(this)));
bauerb5f8cda92015-10-07 15:36:44888}
889
treibf38cc252016-04-07 14:44:11890void SupervisedUserService::OnBlacklistDownloadDone(
891 const base::FilePath& path,
892 FileDownloader::Result result) {
treib9cc1b112016-01-08 10:08:01893 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
treibf38cc252016-04-07 14:44:11894 if (FileDownloader::IsSuccess(result)) {
bauerb5f8cda92015-10-07 15:36:44895 LoadBlacklistFromFile(path);
896 } else {
897 LOG(WARNING) << "Blacklist download failed";
treib9cc1b112016-01-08 10:08:01898 // TODO(treib): Retry downloading after some time?
bauerb5f8cda92015-10-07 15:36:44899 }
900 blacklist_downloader_.reset();
901}
902
903void SupervisedUserService::OnBlacklistLoaded() {
treib9cc1b112016-01-08 10:08:01904 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
905 blacklist_state_ = BlacklistLoadState::LOADED;
906 UpdateBlacklist();
907}
908
909void SupervisedUserService::UpdateBlacklist() {
910 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
911 url_filter_context_.SetBlacklist(use_blacklist ? &blacklist_ : nullptr);
bauerb5f8cda92015-10-07 15:36:44912 FOR_EACH_OBSERVER(
913 SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
914}
[email protected]acfcfbb2013-05-13 18:01:27915
[email protected]cce15bb2014-06-17 13:43:51916void SupervisedUserService::UpdateManualHosts() {
[email protected]cb1078de2013-12-23 20:04:22917 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05918 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualHosts);
dchengf624e472016-04-12 08:33:17919 std::unique_ptr<std::map<std::string, bool>> host_map(
[email protected]5e022292013-02-06 16:42:17920 new std::map<std::string, bool>());
[email protected]cb1078de2013-12-23 20:04:22921 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17922 bool allow = false;
923 bool result = it.value().GetAsBoolean(&allow);
924 DCHECK(result);
925 (*host_map)[it.key()] = allow;
926 }
dchenge73d8520c2015-12-27 01:19:09927 url_filter_context_.SetManualHosts(std::move(host_map));
treibab0a39e2014-09-24 14:48:28928
929 FOR_EACH_OBSERVER(
930 SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
[email protected]0850e842013-01-19 03:44:31931}
932
[email protected]cce15bb2014-06-17 13:43:51933void SupervisedUserService::UpdateManualURLs() {
[email protected]cb1078de2013-12-23 20:04:22934 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05935 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualURLs);
dchengf624e472016-04-12 08:33:17936 std::unique_ptr<std::map<GURL, bool>> url_map(new std::map<GURL, bool>());
[email protected]cb1078de2013-12-23 20:04:22937 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17938 bool allow = false;
939 bool result = it.value().GetAsBoolean(&allow);
940 DCHECK(result);
941 (*url_map)[GURL(it.key())] = allow;
942 }
dchenge73d8520c2015-12-27 01:19:09943 url_filter_context_.SetManualURLs(std::move(url_map));
treibab0a39e2014-09-24 14:48:28944
945 FOR_EACH_OBSERVER(
946 SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
[email protected]0850e842013-01-19 03:44:31947}
[email protected]dfddd022013-07-10 17:29:48948
[email protected]0b4c6b22014-08-04 09:46:31949std::string SupervisedUserService::GetSupervisedUserName() const {
950#if defined(OS_CHROMEOS)
951 // The active user can be NULL in unit tests.
[email protected]4d390782014-08-15 09:22:58952 if (user_manager::UserManager::Get()->GetActiveUser()) {
953 return UTF16ToUTF8(user_manager::UserManager::Get()->GetUserDisplayName(
alemate3ffbde6f2015-11-03 02:02:55954 user_manager::UserManager::Get()->GetActiveUser()->GetAccountId()));
[email protected]0b4c6b22014-08-04 09:46:31955 }
956 return std::string();
957#else
958 return profile_->GetPrefs()->GetString(prefs::kProfileName);
959#endif
960}
bauerb5f8cda92015-10-07 15:36:44961
bauerbb519f8252016-05-13 09:16:39962void SupervisedUserService::OnForceSessionSyncChanged() {
963 includes_sync_sessions_type_ =
964 profile_->GetPrefs()->GetBoolean(prefs::kForceSessionSync);
bauerb5f8cda92015-10-07 15:36:44965 ProfileSyncServiceFactory::GetForProfile(profile_)
966 ->ReconfigureDatatypeManager();
967}
968
bauerb5f8cda92015-10-07 15:36:44969void SupervisedUserService::Shutdown() {
970 if (!did_init_)
971 return;
972 DCHECK(!did_shutdown_);
973 did_shutdown_ = true;
974 if (ProfileIsSupervised()) {
975 content::RecordAction(UserMetricsAction("ManagedUsers_QuitBrowser"));
976 }
977 SetActive(false);
tommyclif3a1551e2016-06-21 18:11:23978 sync_blocker_.reset();
bauerb5f8cda92015-10-07 15:36:44979
maxbogue0a379452016-09-22 21:35:05980 browser_sync::ProfileSyncService* sync_service =
bauerb5f8cda92015-10-07 15:36:44981 ProfileSyncServiceFactory::GetForProfile(profile_);
982
983 // Can be null in tests.
984 if (sync_service)
985 sync_service->RemovePreferenceProvider(this);
986}
987
988#if defined(ENABLE_EXTENSIONS)
mamir192d7882016-06-22 17:10:16989SupervisedUserService::ExtensionState SupervisedUserService::GetExtensionState(
mamire9609642016-06-28 22:17:54990 const Extension& extension) const {
991 bool was_installed_by_default = extension.was_installed_by_default();
mamir192d7882016-06-22 17:10:16992#if defined(OS_CHROMEOS)
993 // On Chrome OS all external sources are controlled by us so it means that
994 // they are "default". Method was_installed_by_default returns false because
995 // extensions creation flags are ignored in case of default extensions with
996 // update URL(the flags aren't passed to OnExternalExtensionUpdateUrlFound).
997 // TODO(dpolukhin): remove this Chrome OS specific code as soon as creation
998 // flags are not ignored.
999 was_installed_by_default =
mamire9609642016-06-28 22:17:541000 extensions::Manifest::IsExternalLocation(extension.location());
mamir192d7882016-06-22 17:10:161001#endif
1002 // Note: Component extensions are protected from modification/uninstallation
1003 // anyway, so there's no need to enforce them again for supervised users.
1004 // Also, leave policy-installed extensions alone - they have their own
1005 // management; in particular we don't want to override the force-install list.
mamire9609642016-06-28 22:17:541006 if (extensions::Manifest::IsComponentLocation(extension.location()) ||
1007 extensions::Manifest::IsPolicyLocation(extension.location()) ||
1008 extension.is_theme() || extension.from_bookmark() ||
1009 extension.is_shared_module() || was_installed_by_default) {
1010 return ExtensionState::ALLOWED;
mamir192d7882016-06-22 17:10:161011 }
1012
mamire9609642016-06-28 22:17:541013 if (extensions::util::WasInstalledByCustodian(extension.id(), profile_))
1014 return ExtensionState::FORCED;
mamir192d7882016-06-22 17:10:161015
mamire9609642016-06-28 22:17:541016 if (!base::FeatureList::IsEnabled(
1017 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
1018 return ExtensionState::BLOCKED;
1019 }
1020
1021 auto extension_it = approved_extensions_map_.find(extension.id());
1022 // If the installed version is approved, then the extension is allowed,
1023 // otherwise, it requires approval.
1024 if (extension_it != approved_extensions_map_.end() &&
1025 extension_it->second == *extension.version()) {
1026 return ExtensionState::ALLOWED;
1027 }
1028 return ExtensionState::REQUIRE_APPROVAL;
mamir192d7882016-06-22 17:10:161029}
1030
bauerb5f8cda92015-10-07 15:36:441031std::string SupervisedUserService::GetDebugPolicyProviderName() const {
1032 // Save the string space in official builds.
1033#ifdef NDEBUG
1034 NOTREACHED();
1035 return std::string();
1036#else
1037 return "Supervised User Service";
1038#endif
1039}
1040
mamire9609642016-06-28 22:17:541041bool SupervisedUserService::UserMayLoad(const Extension* extension,
bauerb5f8cda92015-10-07 15:36:441042 base::string16* error) const {
1043 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:541044 ExtensionState result = GetExtensionState(*extension);
1045 bool may_load = result != ExtensionState::BLOCKED;
bauerb5f8cda92015-10-07 15:36:441046 if (!may_load && error)
treib2170ea02015-10-13 14:55:121047 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441048 return may_load;
1049}
1050
mamire9609642016-06-28 22:17:541051bool SupervisedUserService::UserMayModifySettings(const Extension* extension,
1052 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:441053 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:541054 ExtensionState result = GetExtensionState(*extension);
1055 // While the following check allows the supervised user to modify the settings
1056 // and enable or disable the extension, MustRemainDisabled properly takes care
1057 // of keeping an extension disabled when required.
1058 // For custodian-installed extensions, the state is always FORCED, even if
1059 // it's waiting for an update approval.
1060 bool may_modify = result != ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:441061 if (!may_modify && error)
treib2170ea02015-10-13 14:55:121062 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441063 return may_modify;
1064}
1065
1066// Note: Having MustRemainInstalled always say "true" for custodian-installed
1067// extensions does NOT prevent remote uninstalls (which is a bit unexpected, but
1068// exactly what we want).
mamire9609642016-06-28 22:17:541069bool SupervisedUserService::MustRemainInstalled(const Extension* extension,
1070 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:441071 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:541072 ExtensionState result = GetExtensionState(*extension);
1073 bool may_not_uninstall = result == ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:441074 if (may_not_uninstall && error)
treib2170ea02015-10-13 14:55:121075 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441076 return may_not_uninstall;
1077}
1078
mamire9609642016-06-28 22:17:541079bool SupervisedUserService::MustRemainDisabled(const Extension* extension,
1080 Extension::DisableReason* reason,
1081 base::string16* error) const {
1082 DCHECK(ProfileIsSupervised());
1083 ExtensionState state = GetExtensionState(*extension);
1084 // Only extensions that require approval should be disabled.
1085 // Blocked extensions should be not loaded at all, and are taken care of
1086 // at UserMayLoad.
1087 bool must_remain_disabled = state == ExtensionState::REQUIRE_APPROVAL;
1088
1089 if (must_remain_disabled) {
1090 if (error)
1091 *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER);
1092 // If the extension must remain disabled due to permission increase,
1093 // then the update request has been already sent at update time.
1094 // We do nothing and we don't add an extra disable reason.
1095 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1096 if (extension_prefs->HasDisableReason(
1097 extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE)) {
1098 if (reason)
1099 *reason = Extension::DISABLE_PERMISSIONS_INCREASE;
1100 return true;
1101 }
1102 if (reason)
1103 *reason = Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED;
1104 if (base::FeatureList::IsEnabled(
1105 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
1106 // If the Extension isn't pending a custodian approval already, send
1107 // an approval request.
1108 if (!extension_prefs->HasDisableReason(
1109 extension->id(),
1110 Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED)) {
1111 // MustRemainDisabled is a const method and hence cannot call
1112 // AddExtensionInstallRequest directly.
1113 SupervisedUserService* supervised_user_service =
1114 SupervisedUserServiceFactory::GetForProfile(profile_);
1115 supervised_user_service->AddExtensionInstallRequest(
1116 extension->id(), *extension->version());
1117 }
1118 }
1119 }
1120 return must_remain_disabled;
1121}
1122
1123void SupervisedUserService::OnExtensionInstalled(
1124 content::BrowserContext* browser_context,
1125 const extensions::Extension* extension,
1126 bool is_update) {
1127 // This callback method is responsible for updating extension state and
1128 // approved_extensions_map_ upon extension updates.
1129 if (!is_update)
1130 return;
1131
1132 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1133 const std::string& id = extension->id();
1134 const base::Version& version = *extension->version();
1135
1136 // If an already approved extension is updated without requiring
1137 // new permissions, we update the approved_version.
1138 if (!extension_prefs->HasDisableReason(
1139 id, Extension::DISABLE_PERMISSIONS_INCREASE) &&
1140 approved_extensions_map_.count(id) > 0 &&
1141 approved_extensions_map_[id] < version) {
1142 approved_extensions_map_[id] = version;
1143
1144 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1145 supervised_users::kApprovedExtensions, id);
1146 std::unique_ptr<base::Value> version_value(
1147 new base::StringValue(version.GetString()));
1148 GetSettingsService()->UpdateSetting(key, std::move(version_value));
1149 }
1150 // Upon extension update, the approved version may (or may not) match the
1151 // installed one. Therefore, a change in extension state might be required.
1152 ChangeExtensionStateIfNecessary(id);
1153}
1154
1155void SupervisedUserService::UpdateApprovedExtensions() {
1156 const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary(
1157 prefs::kSupervisedUserApprovedExtensions);
1158 // Keep track of currently approved extensions. We may need to disable them if
1159 // they are not in the approved map anymore.
1160 std::set<std::string> extensions_to_be_checked;
1161 for (const auto& extension : approved_extensions_map_)
1162 extensions_to_be_checked.insert(extension.first);
1163
1164 approved_extensions_map_.clear();
1165
1166 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
1167 std::string version_str;
1168 bool result = it.value().GetAsString(&version_str);
1169 DCHECK(result);
1170 base::Version version(version_str);
1171 if (version.IsValid()) {
1172 approved_extensions_map_[it.key()] = version;
1173 extensions_to_be_checked.insert(it.key());
1174 } else {
1175 LOG(WARNING) << "Invalid version number " << version_str;
1176 }
1177 }
1178
1179 for (const auto& extension_id : extensions_to_be_checked) {
1180 ChangeExtensionStateIfNecessary(extension_id);
1181 }
1182}
1183
1184void SupervisedUserService::ChangeExtensionStateIfNecessary(
1185 const std::string& extension_id) {
1186 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
1187 const Extension* extension = registry->GetInstalledExtension(extension_id);
1188 // If the extension is not installed (yet), do nothing.
1189 // Things will be handled after installation.
1190 if (!extension)
1191 return;
1192
1193 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1194 ExtensionService* service =
1195 ExtensionSystem::Get(profile_)->extension_service();
1196
1197 ExtensionState state = GetExtensionState(*extension);
1198 switch (state) {
1199 // BLOCKED/FORCED extensions should be already disabled/enabled
1200 // and we don't need to change their state here.
1201 case ExtensionState::BLOCKED:
1202 case ExtensionState::FORCED:
1203 break;
1204 case ExtensionState::REQUIRE_APPROVAL:
1205 service->DisableExtension(extension_id,
1206 Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
1207 break;
1208 case ExtensionState::ALLOWED:
1209 extension_prefs->RemoveDisableReason(
1210 extension_id, Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
1211 extension_prefs->RemoveDisableReason(
1212 extension_id, Extension::DISABLE_PERMISSIONS_INCREASE);
1213 // If not disabled for other reasons, enable it.
1214 if (extension_prefs->GetDisableReasons(extension_id) ==
1215 Extension::DISABLE_NONE) {
1216 service->EnableExtension(extension_id);
1217 }
1218 break;
1219 }
1220}
1221
bauerb5f8cda92015-10-07 15:36:441222void SupervisedUserService::SetExtensionsActive() {
1223 extensions::ExtensionSystem* extension_system =
1224 extensions::ExtensionSystem::Get(profile_);
1225 extensions::ManagementPolicy* management_policy =
1226 extension_system->management_policy();
1227
1228 if (management_policy) {
1229 if (active_)
1230 management_policy->RegisterProvider(this);
1231 else
1232 management_policy->UnregisterProvider(this);
1233
1234 // Re-check the policy to make sure any new settings get applied.
1235 extension_system->extension_service()->CheckManagementPolicy();
1236 }
1237}
1238#endif // defined(ENABLE_EXTENSIONS)
1239
1240syncer::ModelTypeSet SupervisedUserService::GetPreferredDataTypes() const {
1241 if (!ProfileIsSupervised())
1242 return syncer::ModelTypeSet();
1243
1244 syncer::ModelTypeSet result;
1245 if (IncludesSyncSessionsType())
1246 result.Put(syncer::SESSIONS);
1247 result.Put(syncer::EXTENSIONS);
1248 result.Put(syncer::EXTENSION_SETTINGS);
1249 result.Put(syncer::APPS);
1250 result.Put(syncer::APP_SETTINGS);
1251 result.Put(syncer::APP_NOTIFICATIONS);
1252 result.Put(syncer::APP_LIST);
1253 return result;
1254}
1255
jam1c5a91492016-02-24 20:47:531256#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:441257void SupervisedUserService::OnStateChanged() {
maxbogue0a379452016-09-22 21:35:051258 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:441259 ProfileSyncServiceFactory::GetForProfile(profile_);
zea32a7684cf2016-02-24 20:41:481260 if (waiting_for_sync_initialization_ && service->IsBackendInitialized()) {
bauerb5f8cda92015-10-07 15:36:441261 waiting_for_sync_initialization_ = false;
1262 service->RemoveObserver(this);
1263 FinishSetupSync();
1264 return;
1265 }
1266
1267 DLOG_IF(ERROR, service->GetAuthError().state() ==
1268 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)
1269 << "Credentials rejected";
1270}
1271
1272void SupervisedUserService::OnBrowserSetLastActive(Browser* browser) {
1273 bool profile_became_active = profile_->IsSameProfile(browser->profile());
1274 if (!is_profile_active_ && profile_became_active)
1275 content::RecordAction(UserMetricsAction("ManagedUsers_OpenProfile"));
1276 else if (is_profile_active_ && !profile_became_active)
1277 content::RecordAction(UserMetricsAction("ManagedUsers_SwitchProfile"));
1278
1279 is_profile_active_ = profile_became_active;
1280}
jam1c5a91492016-02-24 20:47:531281#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:441282
1283void SupervisedUserService::OnSiteListUpdated() {
1284 FOR_EACH_OBSERVER(
1285 SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
1286}