blob: 68d04894ce2e5bb0c327f6efe719dcb4bd8d6eac [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()
alemate1e3ddde2016-11-04 02:17:06309 ->GetSupervisedUserManager()
310 ->GetManagerDisplayEmail(user_manager::UserManager::Get()
311 ->GetActiveUser()
312 ->GetAccountId()
313 .GetUserEmail());
bauerb5f8cda92015-10-07 15:36:44314 }
315#endif
treib2170ea02015-10-13 14:55:12316 return email;
bauerb5f8cda92015-10-07 15:36:44317}
318
319std::string SupervisedUserService::GetCustodianName() const {
320 std::string name = profile_->GetPrefs()->GetString(
321 prefs::kSupervisedUserCustodianName);
322#if defined(OS_CHROMEOS)
treib2170ea02015-10-13 14:55:12323 // |GetActiveUser()| can return null in unit tests.
324 if (name.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
alemate1e3ddde2016-11-04 02:17:06325 name = base::UTF16ToUTF8(
326 chromeos::ChromeUserManager::Get()
327 ->GetSupervisedUserManager()
328 ->GetManagerDisplayName(user_manager::UserManager::Get()
329 ->GetActiveUser()
330 ->GetAccountId()
331 .GetUserEmail()));
bauerb5f8cda92015-10-07 15:36:44332 }
333#endif
334 return name.empty() ? GetCustodianEmailAddress() : name;
335}
336
337std::string SupervisedUserService::GetSecondCustodianEmailAddress() const {
338 return profile_->GetPrefs()->GetString(
339 prefs::kSupervisedUserSecondCustodianEmail);
340}
341
342std::string SupervisedUserService::GetSecondCustodianName() const {
343 std::string name = profile_->GetPrefs()->GetString(
344 prefs::kSupervisedUserSecondCustodianName);
345 return name.empty() ? GetSecondCustodianEmailAddress() : name;
346}
347
treib2170ea02015-10-13 14:55:12348base::string16 SupervisedUserService::GetExtensionsLockedMessage() const {
349 return l10n_util::GetStringFUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER,
350 base::UTF8ToUTF16(GetCustodianName()));
351}
352
jam1c5a91492016-02-24 20:47:53353#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44354void SupervisedUserService::InitSync(const std::string& refresh_token) {
355 StartSetupSync();
356
357 ProfileOAuth2TokenService* token_service =
358 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
359 token_service->UpdateCredentials(supervised_users::kSupervisedUserPseudoEmail,
360 refresh_token);
361
362 FinishSetupSyncWhenReady();
363}
364
365void SupervisedUserService::RegisterAndInitSync(
366 SupervisedUserRegistrationUtility* registration_utility,
367 Profile* custodian_profile,
368 const std::string& supervised_user_id,
369 const AuthErrorCallback& callback) {
370 DCHECK(ProfileIsSupervised());
371 DCHECK(!custodian_profile->IsSupervised());
372
373 base::string16 name = base::UTF8ToUTF16(
374 profile_->GetPrefs()->GetString(prefs::kProfileName));
375 int avatar_index = profile_->GetPrefs()->GetInteger(
376 prefs::kProfileAvatarIndex);
377 SupervisedUserRegistrationInfo info(name, avatar_index);
378 registration_utility->Register(
379 supervised_user_id,
380 info,
381 base::Bind(&SupervisedUserService::OnSupervisedUserRegistered,
382 weak_ptr_factory_.GetWeakPtr(), callback, custodian_profile));
383
384 // Fetch the custodian's profile information, to store the name.
385 // TODO(pamg): If --google-profile-info (flag: switches::kGoogleProfileInfo)
lwchkg7f133c72016-03-01 16:48:53386 // is ever enabled, take the name from the ProfileAttributesStorage instead.
bauerb5f8cda92015-10-07 15:36:44387 CustodianProfileDownloaderService* profile_downloader_service =
388 CustodianProfileDownloaderServiceFactory::GetForProfile(
389 custodian_profile);
390 profile_downloader_service->DownloadProfile(
391 base::Bind(&SupervisedUserService::OnCustodianProfileDownloaded,
392 weak_ptr_factory_.GetWeakPtr()));
393}
jam1c5a91492016-02-24 20:47:53394#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44395
396void SupervisedUserService::AddNavigationBlockedCallback(
397 const NavigationBlockedCallback& callback) {
398 navigation_blocked_callbacks_.push_back(callback);
399}
400
401void SupervisedUserService::DidBlockNavigation(
402 content::WebContents* web_contents) {
403 for (const auto& callback : navigation_blocked_callbacks_)
404 callback.Run(web_contents);
405}
406
407void SupervisedUserService::AddObserver(
408 SupervisedUserServiceObserver* observer) {
409 observer_list_.AddObserver(observer);
410}
411
412void SupervisedUserService::RemoveObserver(
413 SupervisedUserServiceObserver* observer) {
414 observer_list_.RemoveObserver(observer);
415}
416
417void SupervisedUserService::AddPermissionRequestCreator(
dchengf624e472016-04-12 08:33:17418 std::unique_ptr<PermissionRequestCreator> creator) {
bauerb5f8cda92015-10-07 15:36:44419 permissions_creators_.push_back(creator.release());
420}
421
atanasovaac676032016-04-05 16:31:05422void SupervisedUserService::SetSafeSearchURLReporter(
dchengf624e472016-04-12 08:33:17423 std::unique_ptr<SafeSearchURLReporter> reporter) {
atanasovaac676032016-04-05 16:31:05424 url_reporter_ = std::move(reporter);
425}
426
bauerbb519f8252016-05-13 09:16:39427bool SupervisedUserService::IncludesSyncSessionsType() const {
428 return includes_sync_sessions_type_;
429}
430
[email protected]cce15bb2014-06-17 13:43:51431SupervisedUserService::URLFilterContext::URLFilterContext()
432 : ui_url_filter_(new SupervisedUserURLFilter),
433 io_url_filter_(new SupervisedUserURLFilter) {}
434SupervisedUserService::URLFilterContext::~URLFilterContext() {}
[email protected]0850e842013-01-19 03:44:31435
[email protected]cce15bb2014-06-17 13:43:51436SupervisedUserURLFilter*
437SupervisedUserService::URLFilterContext::ui_url_filter() const {
[email protected]0850e842013-01-19 03:44:31438 return ui_url_filter_.get();
439}
440
[email protected]cce15bb2014-06-17 13:43:51441SupervisedUserURLFilter*
442SupervisedUserService::URLFilterContext::io_url_filter() const {
[email protected]0850e842013-01-19 03:44:31443 return io_url_filter_.get();
444}
445
[email protected]cce15bb2014-06-17 13:43:51446void SupervisedUserService::URLFilterContext::SetDefaultFilteringBehavior(
447 SupervisedUserURLFilter::FilteringBehavior behavior) {
[email protected]0850e842013-01-19 03:44:31448 ui_url_filter_->SetDefaultFilteringBehavior(behavior);
449 BrowserThread::PostTask(
450 BrowserThread::IO,
451 FROM_HERE,
[email protected]cce15bb2014-06-17 13:43:51452 base::Bind(&SupervisedUserURLFilter::SetDefaultFilteringBehavior,
tzik07cace42016-09-01 04:21:25453 io_url_filter_, behavior));
[email protected]0850e842013-01-19 03:44:31454}
455
[email protected]cce15bb2014-06-17 13:43:51456void SupervisedUserService::URLFilterContext::LoadWhitelists(
bauerb95a50682015-01-07 17:04:15457 const std::vector<scoped_refptr<SupervisedUserSiteList> >& site_lists) {
458 ui_url_filter_->LoadWhitelists(site_lists);
459 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
460 base::Bind(&SupervisedUserURLFilter::LoadWhitelists,
461 io_url_filter_, site_lists));
[email protected]0850e842013-01-19 03:44:31462}
463
treib9cc1b112016-01-08 10:08:01464void SupervisedUserService::URLFilterContext::SetBlacklist(
465 const SupervisedUserBlacklist* blacklist) {
466 ui_url_filter_->SetBlacklist(blacklist);
467 BrowserThread::PostTask(
468 BrowserThread::IO,
469 FROM_HERE,
470 base::Bind(&SupervisedUserURLFilter::SetBlacklist,
471 io_url_filter_,
472 blacklist));
473}
474
475bool SupervisedUserService::URLFilterContext::HasBlacklist() const {
476 return ui_url_filter_->HasBlacklist();
treib4edbded2014-09-05 08:43:55477}
478
[email protected]cce15bb2014-06-17 13:43:51479void SupervisedUserService::URLFilterContext::SetManualHosts(
dchengf624e472016-04-12 08:33:17480 std::unique_ptr<std::map<std::string, bool>> host_map) {
[email protected]5e022292013-02-06 16:42:17481 ui_url_filter_->SetManualHosts(host_map.get());
[email protected]0850e842013-01-19 03:44:31482 BrowserThread::PostTask(
483 BrowserThread::IO,
484 FROM_HERE,
[email protected]cce15bb2014-06-17 13:43:51485 base::Bind(&SupervisedUserURLFilter::SetManualHosts,
[email protected]5e022292013-02-06 16:42:17486 io_url_filter_, base::Owned(host_map.release())));
[email protected]0850e842013-01-19 03:44:31487}
488
[email protected]cce15bb2014-06-17 13:43:51489void SupervisedUserService::URLFilterContext::SetManualURLs(
dchengf624e472016-04-12 08:33:17490 std::unique_ptr<std::map<GURL, bool>> url_map) {
[email protected]5e022292013-02-06 16:42:17491 ui_url_filter_->SetManualURLs(url_map.get());
[email protected]0850e842013-01-19 03:44:31492 BrowserThread::PostTask(
493 BrowserThread::IO,
494 FROM_HERE,
[email protected]cce15bb2014-06-17 13:43:51495 base::Bind(&SupervisedUserURLFilter::SetManualURLs,
[email protected]5e022292013-02-06 16:42:17496 io_url_filter_, base::Owned(url_map.release())));
[email protected]0850e842013-01-19 03:44:31497}
498
treib22c3a042015-01-15 21:30:13499void SupervisedUserService::URLFilterContext::Clear() {
500 ui_url_filter_->Clear();
501 BrowserThread::PostTask(
502 BrowserThread::IO,
503 FROM_HERE,
504 base::Bind(&SupervisedUserURLFilter::Clear,
505 io_url_filter_));
506}
507
bauerb5f8cda92015-10-07 15:36:44508void SupervisedUserService::URLFilterContext::InitAsyncURLChecker(
509 const scoped_refptr<net::URLRequestContextGetter>& context) {
510 ui_url_filter_->InitAsyncURLChecker(context.get());
511 BrowserThread::PostTask(
vmpstra34d11322016-03-21 20:28:47512 BrowserThread::IO, FROM_HERE,
513 base::Bind(&SupervisedUserURLFilter::InitAsyncURLChecker, io_url_filter_,
514 base::RetainedRef(context)));
bauerb5f8cda92015-10-07 15:36:44515}
516
treib9cc1b112016-01-08 10:08:01517bool SupervisedUserService::URLFilterContext::HasAsyncURLChecker() const {
518 return ui_url_filter_->HasAsyncURLChecker();
519}
520
521void SupervisedUserService::URLFilterContext::ClearAsyncURLChecker() {
522 ui_url_filter_->ClearAsyncURLChecker();
treib4edbded2014-09-05 08:43:55523 BrowserThread::PostTask(
524 BrowserThread::IO,
525 FROM_HERE,
treib9cc1b112016-01-08 10:08:01526 base::Bind(&SupervisedUserURLFilter::ClearAsyncURLChecker,
527 io_url_filter_));
treib4edbded2014-09-05 08:43:55528}
529
[email protected]cce15bb2014-06-17 13:43:51530SupervisedUserService::SupervisedUserService(Profile* profile)
fhorschig1f351f02014-09-30 12:30:22531 : includes_sync_sessions_type_(true),
532 profile_(profile),
[email protected]f085fdd52014-06-11 18:09:20533 active_(false),
534 delegate_(NULL),
[email protected]a243d644c2013-06-20 18:37:55535 waiting_for_sync_initialization_(false),
[email protected]dfddd022013-07-10 17:29:48536 is_profile_active_(false),
[email protected]3a276ff2014-08-12 14:22:09537 did_init_(false),
[email protected]8052b242013-11-15 16:40:55538 did_shutdown_(false),
treib9cc1b112016-01-08 10:08:01539 blacklist_state_(BlacklistLoadState::NOT_LOADED),
mamire9609642016-06-28 22:17:54540#if defined(ENABLE_EXTENSIONS)
541 registry_observer_(this),
542#endif
[email protected]8052b242013-11-15 16:40:55543 weak_ptr_factory_(this) {
bauerbce9a1a82014-12-18 13:34:24544 url_filter_context_.ui_url_filter()->AddObserver(this);
mamire9609642016-06-28 22:17:54545#if defined(ENABLE_EXTENSIONS)
546 registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
547#endif
[email protected]a243d644c2013-06-20 18:37:55548}
[email protected]0850e842013-01-19 03:44:31549
[email protected]cce15bb2014-06-17 13:43:51550void SupervisedUserService::SetActive(bool active) {
[email protected]f085fdd52014-06-11 18:09:20551 if (active_ == active)
[email protected]0850e842013-01-19 03:44:31552 return;
[email protected]f085fdd52014-06-11 18:09:20553 active_ = active;
554
555 if (!delegate_ || !delegate_->SetActive(active_)) {
556 if (active_) {
jam1c5a91492016-02-24 20:47:53557#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20558 SupervisedUserPrefMappingServiceFactory::GetForBrowserContext(profile_)
559 ->Init();
560
avi556c05022014-12-22 23:31:43561 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
[email protected]d20d0432014-06-12 17:14:05562 if (command_line->HasSwitch(switches::kSupervisedUserSyncToken)) {
[email protected]f085fdd52014-06-11 18:09:20563 InitSync(
[email protected]d20d0432014-06-12 17:14:05564 command_line->GetSwitchValueASCII(
565 switches::kSupervisedUserSyncToken));
[email protected]f085fdd52014-06-11 18:09:20566 }
567
568 ProfileOAuth2TokenService* token_service =
569 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
[email protected]cce15bb2014-06-17 13:43:51570 token_service->LoadCredentials(
571 supervised_users::kSupervisedUserPseudoEmail);
[email protected]6e08b9a62014-07-08 00:32:48572
treib531fc7312014-12-09 12:49:20573 permissions_creators_.push_back(new PermissionRequestCreatorSync(
574 GetSettingsService(),
575 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(
576 profile_),
577 ProfileSyncServiceFactory::GetForProfile(profile_),
578 GetSupervisedUserName(),
579 profile_->GetPrefs()->GetString(prefs::kSupervisedUserId)));
580
[email protected]6e08b9a62014-07-08 00:32:48581 SetupSync();
bauerb7f3b8542015-06-29 19:56:19582#else
583 NOTREACHED();
584#endif
[email protected]f085fdd52014-06-11 18:09:20585 }
[email protected]e861bba2013-06-17 15:20:54586 }
[email protected]0850e842013-01-19 03:44:31587
[email protected]f085fdd52014-06-11 18:09:20588 // Now activate/deactivate anything not handled by the delegate yet.
[email protected]e1480482013-09-11 11:49:58589
[email protected]f085fdd52014-06-11 18:09:20590#if defined(ENABLE_THEMES)
591 // Re-set the default theme to turn the SU theme on/off.
592 ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile_);
treib9e30e302015-04-15 08:12:16593 if (theme_service->UsingDefaultTheme() || theme_service->UsingSystemTheme())
594 theme_service->UseDefaultTheme();
[email protected]f085fdd52014-06-11 18:09:20595#endif
[email protected]a19df3e2013-05-21 00:03:03596
maxbogue0a379452016-09-22 21:35:05597 browser_sync::ProfileSyncService* sync_service =
bauerbf03588b92014-10-27 13:40:15598 ProfileSyncServiceFactory::GetForProfile(profile_);
599 sync_service->SetEncryptEverythingAllowed(!active_);
600
bauerbd3a36cc42014-10-01 13:05:49601 GetSettingsService()->SetActive(active_);
[email protected]a243d644c2013-06-20 18:37:55602
[email protected]c14a6802014-07-11 21:51:12603#if defined(ENABLE_EXTENSIONS)
604 SetExtensionsActive();
605#endif
[email protected]0850e842013-01-19 03:44:31606
[email protected]f085fdd52014-06-11 18:09:20607 if (active_) {
[email protected]f085fdd52014-06-11 18:09:20608 pref_change_registrar_.Add(
[email protected]d20d0432014-06-12 17:14:05609 prefs::kDefaultSupervisedUserFilteringBehavior,
[email protected]cce15bb2014-06-17 13:43:51610 base::Bind(&SupervisedUserService::OnDefaultFilteringBehaviorChanged,
[email protected]f085fdd52014-06-11 18:09:20611 base::Unretained(this)));
mamire9609642016-06-28 22:17:54612#if defined(ENABLE_EXTENSIONS)
613 pref_change_registrar_.Add(
614 prefs::kSupervisedUserApprovedExtensions,
615 base::Bind(&SupervisedUserService::UpdateApprovedExtensions,
616 base::Unretained(this)));
617#endif
treib9cc1b112016-01-08 10:08:01618 pref_change_registrar_.Add(prefs::kSupervisedUserSafeSites,
619 base::Bind(&SupervisedUserService::OnSafeSitesSettingChanged,
620 base::Unretained(this)));
[email protected]d20d0432014-06-12 17:14:05621 pref_change_registrar_.Add(prefs::kSupervisedUserManualHosts,
[email protected]cce15bb2014-06-17 13:43:51622 base::Bind(&SupervisedUserService::UpdateManualHosts,
[email protected]f085fdd52014-06-11 18:09:20623 base::Unretained(this)));
[email protected]d20d0432014-06-12 17:14:05624 pref_change_registrar_.Add(prefs::kSupervisedUserManualURLs,
[email protected]cce15bb2014-06-17 13:43:51625 base::Bind(&SupervisedUserService::UpdateManualURLs,
[email protected]f085fdd52014-06-11 18:09:20626 base::Unretained(this)));
treib22c3a042015-01-15 21:30:13627 for (const char* pref : kCustodianInfoPrefs) {
628 pref_change_registrar_.Add(pref,
629 base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
630 base::Unretained(this)));
631 }
[email protected]f085fdd52014-06-11 18:09:20632
633 // Initialize the filter.
634 OnDefaultFilteringBehaviorChanged();
treib9cc1b112016-01-08 10:08:01635 OnSafeSitesSettingChanged();
bauerb4da36132014-12-26 19:53:13636 whitelist_service_->Init();
[email protected]f085fdd52014-06-11 18:09:20637 UpdateManualHosts();
638 UpdateManualURLs();
[email protected]0850e842013-01-19 03:44:31639
mamire9609642016-06-28 22:17:54640#if defined(ENABLE_EXTENSIONS)
641 UpdateApprovedExtensions();
642#endif
643
jam1c5a91492016-02-24 20:47:53644#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20645 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
646 // http://crbug.com/313377
647 BrowserList::AddObserver(this);
[email protected]975677d2013-11-14 16:15:34648#endif
[email protected]f085fdd52014-06-11 18:09:20649 } else {
bauerbd3a36cc42014-10-01 13:05:49650 permissions_creators_.clear();
atanasovaac676032016-04-05 16:31:05651 url_reporter_.reset();
[email protected]dfddd022013-07-10 17:29:48652
[email protected]d20d0432014-06-12 17:14:05653 pref_change_registrar_.Remove(
654 prefs::kDefaultSupervisedUserFilteringBehavior);
mamire9609642016-06-28 22:17:54655#if defined(ENABLE_EXTENSIONS)
656 pref_change_registrar_.Remove(prefs::kSupervisedUserApprovedExtensions);
657#endif
[email protected]d20d0432014-06-12 17:14:05658 pref_change_registrar_.Remove(prefs::kSupervisedUserManualHosts);
659 pref_change_registrar_.Remove(prefs::kSupervisedUserManualURLs);
treib22c3a042015-01-15 21:30:13660 for (const char* pref : kCustodianInfoPrefs) {
661 pref_change_registrar_.Remove(pref);
662 }
663
664 url_filter_context_.Clear();
ericwilligers8b92b052016-10-19 22:21:58665 for (SupervisedUserServiceObserver& observer : observer_list_)
666 observer.OnURLFilterChanged();
[email protected]f085fdd52014-06-11 18:09:20667
jam1c5a91492016-02-24 20:47:53668#if !defined(OS_ANDROID)
[email protected]3a276ff2014-08-12 14:22:09669 if (waiting_for_sync_initialization_)
670 ProfileSyncServiceFactory::GetForProfile(profile_)->RemoveObserver(this);
[email protected]f085fdd52014-06-11 18:09:20671
[email protected]f085fdd52014-06-11 18:09:20672 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
673 // http://crbug.com/313377
674 BrowserList::RemoveObserver(this);
675#endif
676 }
[email protected]0850e842013-01-19 03:44:31677}
678
jam1c5a91492016-02-24 20:47:53679#if !defined(OS_ANDROID)
[email protected]cce15bb2014-06-17 13:43:51680void SupervisedUserService::OnCustodianProfileDownloaded(
[email protected]0085863a2013-12-06 21:19:03681 const base::string16& full_name) {
[email protected]d20d0432014-06-12 17:14:05682 profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
[email protected]6778fed2013-12-24 20:09:37683 base::UTF16ToUTF8(full_name));
[email protected]acfcfbb2013-05-13 18:01:27684}
685
[email protected]cce15bb2014-06-17 13:43:51686void SupervisedUserService::OnSupervisedUserRegistered(
[email protected]514fcf22013-08-13 06:37:24687 const AuthErrorCallback& callback,
[email protected]f252df2e2013-06-06 23:47:19688 Profile* custodian_profile,
[email protected]acfcfbb2013-05-13 18:01:27689 const GoogleServiceAuthError& auth_error,
690 const std::string& token) {
[email protected]514fcf22013-08-13 06:37:24691 if (auth_error.state() == GoogleServiceAuthError::NONE) {
692 InitSync(token);
693 SigninManagerBase* signin =
694 SigninManagerFactory::GetForProfile(custodian_profile);
bzanotti1b5be292015-08-31 12:10:05695 profile_->GetPrefs()->SetString(
696 prefs::kSupervisedUserCustodianEmail,
697 signin->GetAuthenticatedAccountInfo().email);
[email protected]5ddfade2014-02-03 10:24:53698
[email protected]cce15bb2014-06-17 13:43:51699 // The supervised user profile is now ready for use.
lwchkg7f133c72016-03-01 16:48:53700 ProfileAttributesEntry* entry = nullptr;
701 bool has_entry =
702 g_browser_process->profile_manager()->GetProfileAttributesStorage().
703 GetProfileAttributesWithPath(profile_->GetPath(), &entry);
704 DCHECK(has_entry);
705 entry->SetIsOmitted(false);
[email protected]514fcf22013-08-13 06:37:24706 } else {
[email protected]acfcfbb2013-05-13 18:01:27707 DCHECK_EQ(std::string(), token);
[email protected]acfcfbb2013-05-13 18:01:27708 }
709
[email protected]514fcf22013-08-13 06:37:24710 callback.Run(auth_error);
[email protected]acfcfbb2013-05-13 18:01:27711}
bauerb5f8cda92015-10-07 15:36:44712void SupervisedUserService::SetupSync() {
713 StartSetupSync();
714 FinishSetupSyncWhenReady();
715}
716
717void SupervisedUserService::StartSetupSync() {
718 // Tell the sync service that setup is in progress so we don't start syncing
719 // until we've finished configuration.
tommyclif3a1551e2016-06-21 18:11:23720 sync_blocker_ = ProfileSyncServiceFactory::GetForProfile(profile_)
721 ->GetSetupInProgressHandle();
bauerb5f8cda92015-10-07 15:36:44722}
723
724void SupervisedUserService::FinishSetupSyncWhenReady() {
725 // If we're already waiting for the Sync backend, there's nothing to do here.
726 if (waiting_for_sync_initialization_)
727 return;
728
729 // Continue in FinishSetupSync() once the Sync backend has been initialized.
maxbogue0a379452016-09-22 21:35:05730 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:44731 ProfileSyncServiceFactory::GetForProfile(profile_);
zea32a7684cf2016-02-24 20:41:48732 if (service->IsBackendInitialized()) {
bauerb5f8cda92015-10-07 15:36:44733 FinishSetupSync();
734 } else {
735 service->AddObserver(this);
736 waiting_for_sync_initialization_ = true;
737 }
738}
739
740void SupervisedUserService::FinishSetupSync() {
maxbogue0a379452016-09-22 21:35:05741 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:44742 ProfileSyncServiceFactory::GetForProfile(profile_);
743 DCHECK(service->IsBackendInitialized());
bauerb5f8cda92015-10-07 15:36:44744
745 // Sync nothing (except types which are set via GetPreferredDataTypes).
746 bool sync_everything = false;
747 syncer::ModelTypeSet synced_datatypes;
748 service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
749
750 // Notify ProfileSyncService that we are done with configuration.
tommyclif3a1551e2016-06-21 18:11:23751 sync_blocker_.reset();
maxboguefe00952a2016-01-19 19:02:01752 service->SetFirstSetupComplete();
bauerb5f8cda92015-10-07 15:36:44753}
754#endif
755
756bool SupervisedUserService::ProfileIsSupervised() const {
757 return profile_->IsSupervised();
758}
759
760void SupervisedUserService::OnCustodianInfoChanged() {
ericwilligers8b92b052016-10-19 22:21:58761 for (SupervisedUserServiceObserver& observer : observer_list_)
762 observer.OnCustodianInfoChanged();
bauerb5f8cda92015-10-07 15:36:44763}
764
765SupervisedUserSettingsService* SupervisedUserService::GetSettingsService() {
766 return SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
767}
768
769size_t SupervisedUserService::FindEnabledPermissionRequestCreator(
770 size_t start) {
771 for (size_t i = start; i < permissions_creators_.size(); ++i) {
772 if (permissions_creators_[i]->IsEnabled())
773 return i;
774 }
775 return permissions_creators_.size();
776}
777
778void SupervisedUserService::AddPermissionRequestInternal(
779 const CreatePermissionRequestCallback& create_request,
780 const SuccessCallback& callback,
781 size_t index) {
782 // Find a permission request creator that is enabled.
783 size_t next_index = FindEnabledPermissionRequestCreator(index);
784 if (next_index >= permissions_creators_.size()) {
785 callback.Run(false);
786 return;
787 }
788
789 create_request.Run(
790 permissions_creators_[next_index],
791 base::Bind(&SupervisedUserService::OnPermissionRequestIssued,
792 weak_ptr_factory_.GetWeakPtr(), create_request,
793 callback, next_index));
794}
795
796void SupervisedUserService::OnPermissionRequestIssued(
797 const CreatePermissionRequestCallback& create_request,
798 const SuccessCallback& callback,
799 size_t index,
800 bool success) {
801 if (success) {
802 callback.Run(true);
803 return;
804 }
805
806 AddPermissionRequestInternal(create_request, callback, index + 1);
807}
808
809void SupervisedUserService::OnSupervisedUserIdChanged() {
810 SetActive(ProfileIsSupervised());
811}
812
813void SupervisedUserService::OnDefaultFilteringBehaviorChanged() {
814 int behavior_value = profile_->GetPrefs()->GetInteger(
815 prefs::kDefaultSupervisedUserFilteringBehavior);
816 SupervisedUserURLFilter::FilteringBehavior behavior =
817 SupervisedUserURLFilter::BehaviorFromInt(behavior_value);
818 url_filter_context_.SetDefaultFilteringBehavior(behavior);
819
ericwilligers8b92b052016-10-19 22:21:58820 for (SupervisedUserServiceObserver& observer : observer_list_)
821 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:44822}
823
treib9cc1b112016-01-08 10:08:01824void SupervisedUserService::OnSafeSitesSettingChanged() {
825 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
826 if (use_blacklist != url_filter_context_.HasBlacklist()) {
827 if (use_blacklist && blacklist_state_ == BlacklistLoadState::NOT_LOADED) {
828 LoadBlacklist(GetBlacklistPath(), GURL(kBlacklistURL));
829 } else if (!use_blacklist ||
830 blacklist_state_ == BlacklistLoadState::LOADED) {
831 // Either the blacklist was turned off, or it was turned on but has
832 // already been loaded previously. Just update the setting.
833 UpdateBlacklist();
834 }
835 // Else: The blacklist was enabled, but the load is already in progress.
836 // Do nothing - we'll check the setting again when the load finishes.
837 }
838
839 bool use_online_check =
840 supervised_users::IsSafeSitesOnlineCheckEnabled(profile_);
treibe821d6542016-01-21 01:10:19841 if (use_online_check != url_filter_context_.HasAsyncURLChecker()) {
treib9cc1b112016-01-08 10:08:01842 if (use_online_check)
843 url_filter_context_.InitAsyncURLChecker(profile_->GetRequestContext());
844 else
845 url_filter_context_.ClearAsyncURLChecker();
846 }
847}
848
bauerb5f8cda92015-10-07 15:36:44849void SupervisedUserService::OnSiteListsChanged(
850 const std::vector<scoped_refptr<SupervisedUserSiteList> >& site_lists) {
atanasova9572aaf2016-02-26 18:08:26851 whitelists_ = site_lists;
bauerb5f8cda92015-10-07 15:36:44852 url_filter_context_.LoadWhitelists(site_lists);
853}
854
855void SupervisedUserService::LoadBlacklist(const base::FilePath& path,
856 const GURL& url) {
treib9cc1b112016-01-08 10:08:01857 DCHECK(blacklist_state_ == BlacklistLoadState::NOT_LOADED);
858 blacklist_state_ = BlacklistLoadState::LOAD_STARTED;
bauerb5f8cda92015-10-07 15:36:44859 base::PostTaskAndReplyWithResult(
860 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
861 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(),
862 FROM_HERE,
863 base::Bind(&base::PathExists, path),
864 base::Bind(&SupervisedUserService::OnBlacklistFileChecked,
865 weak_ptr_factory_.GetWeakPtr(), path, url));
866}
867
868void SupervisedUserService::OnBlacklistFileChecked(const base::FilePath& path,
869 const GURL& url,
870 bool file_exists) {
treib9cc1b112016-01-08 10:08:01871 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
bauerb5f8cda92015-10-07 15:36:44872 if (file_exists) {
873 LoadBlacklistFromFile(path);
874 return;
875 }
876
877 DCHECK(!blacklist_downloader_);
878 blacklist_downloader_.reset(new FileDownloader(
879 url,
880 path,
881 false,
882 profile_->GetRequestContext(),
883 base::Bind(&SupervisedUserService::OnBlacklistDownloadDone,
884 base::Unretained(this), path)));
885}
886
887void SupervisedUserService::LoadBlacklistFromFile(const base::FilePath& path) {
treib9cc1b112016-01-08 10:08:01888 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
889 blacklist_.ReadFromFile(
890 path,
891 base::Bind(&SupervisedUserService::OnBlacklistLoaded,
892 base::Unretained(this)));
bauerb5f8cda92015-10-07 15:36:44893}
894
treibf38cc252016-04-07 14:44:11895void SupervisedUserService::OnBlacklistDownloadDone(
896 const base::FilePath& path,
897 FileDownloader::Result result) {
treib9cc1b112016-01-08 10:08:01898 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
treibf38cc252016-04-07 14:44:11899 if (FileDownloader::IsSuccess(result)) {
bauerb5f8cda92015-10-07 15:36:44900 LoadBlacklistFromFile(path);
901 } else {
902 LOG(WARNING) << "Blacklist download failed";
treib9cc1b112016-01-08 10:08:01903 // TODO(treib): Retry downloading after some time?
bauerb5f8cda92015-10-07 15:36:44904 }
905 blacklist_downloader_.reset();
906}
907
908void SupervisedUserService::OnBlacklistLoaded() {
treib9cc1b112016-01-08 10:08:01909 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
910 blacklist_state_ = BlacklistLoadState::LOADED;
911 UpdateBlacklist();
912}
913
914void SupervisedUserService::UpdateBlacklist() {
915 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
916 url_filter_context_.SetBlacklist(use_blacklist ? &blacklist_ : nullptr);
ericwilligers8b92b052016-10-19 22:21:58917 for (SupervisedUserServiceObserver& observer : observer_list_)
918 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:44919}
[email protected]acfcfbb2013-05-13 18:01:27920
[email protected]cce15bb2014-06-17 13:43:51921void SupervisedUserService::UpdateManualHosts() {
[email protected]cb1078de2013-12-23 20:04:22922 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05923 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualHosts);
dchengf624e472016-04-12 08:33:17924 std::unique_ptr<std::map<std::string, bool>> host_map(
[email protected]5e022292013-02-06 16:42:17925 new std::map<std::string, bool>());
[email protected]cb1078de2013-12-23 20:04:22926 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17927 bool allow = false;
928 bool result = it.value().GetAsBoolean(&allow);
929 DCHECK(result);
930 (*host_map)[it.key()] = allow;
931 }
dchenge73d8520c2015-12-27 01:19:09932 url_filter_context_.SetManualHosts(std::move(host_map));
treibab0a39e2014-09-24 14:48:28933
ericwilligers8b92b052016-10-19 22:21:58934 for (SupervisedUserServiceObserver& observer : observer_list_)
935 observer.OnURLFilterChanged();
[email protected]0850e842013-01-19 03:44:31936}
937
[email protected]cce15bb2014-06-17 13:43:51938void SupervisedUserService::UpdateManualURLs() {
[email protected]cb1078de2013-12-23 20:04:22939 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05940 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualURLs);
dchengf624e472016-04-12 08:33:17941 std::unique_ptr<std::map<GURL, bool>> url_map(new std::map<GURL, bool>());
[email protected]cb1078de2013-12-23 20:04:22942 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17943 bool allow = false;
944 bool result = it.value().GetAsBoolean(&allow);
945 DCHECK(result);
946 (*url_map)[GURL(it.key())] = allow;
947 }
dchenge73d8520c2015-12-27 01:19:09948 url_filter_context_.SetManualURLs(std::move(url_map));
treibab0a39e2014-09-24 14:48:28949
ericwilligers8b92b052016-10-19 22:21:58950 for (SupervisedUserServiceObserver& observer : observer_list_)
951 observer.OnURLFilterChanged();
[email protected]0850e842013-01-19 03:44:31952}
[email protected]dfddd022013-07-10 17:29:48953
[email protected]0b4c6b22014-08-04 09:46:31954std::string SupervisedUserService::GetSupervisedUserName() const {
955#if defined(OS_CHROMEOS)
956 // The active user can be NULL in unit tests.
[email protected]4d390782014-08-15 09:22:58957 if (user_manager::UserManager::Get()->GetActiveUser()) {
958 return UTF16ToUTF8(user_manager::UserManager::Get()->GetUserDisplayName(
alemate3ffbde6f2015-11-03 02:02:55959 user_manager::UserManager::Get()->GetActiveUser()->GetAccountId()));
[email protected]0b4c6b22014-08-04 09:46:31960 }
961 return std::string();
962#else
963 return profile_->GetPrefs()->GetString(prefs::kProfileName);
964#endif
965}
bauerb5f8cda92015-10-07 15:36:44966
bauerbb519f8252016-05-13 09:16:39967void SupervisedUserService::OnForceSessionSyncChanged() {
968 includes_sync_sessions_type_ =
969 profile_->GetPrefs()->GetBoolean(prefs::kForceSessionSync);
bauerb5f8cda92015-10-07 15:36:44970 ProfileSyncServiceFactory::GetForProfile(profile_)
971 ->ReconfigureDatatypeManager();
972}
973
bauerb5f8cda92015-10-07 15:36:44974void SupervisedUserService::Shutdown() {
975 if (!did_init_)
976 return;
977 DCHECK(!did_shutdown_);
978 did_shutdown_ = true;
979 if (ProfileIsSupervised()) {
980 content::RecordAction(UserMetricsAction("ManagedUsers_QuitBrowser"));
981 }
982 SetActive(false);
tommyclif3a1551e2016-06-21 18:11:23983 sync_blocker_.reset();
bauerb5f8cda92015-10-07 15:36:44984
maxbogue0a379452016-09-22 21:35:05985 browser_sync::ProfileSyncService* sync_service =
bauerb5f8cda92015-10-07 15:36:44986 ProfileSyncServiceFactory::GetForProfile(profile_);
987
988 // Can be null in tests.
989 if (sync_service)
990 sync_service->RemovePreferenceProvider(this);
991}
992
993#if defined(ENABLE_EXTENSIONS)
mamir192d7882016-06-22 17:10:16994SupervisedUserService::ExtensionState SupervisedUserService::GetExtensionState(
mamire9609642016-06-28 22:17:54995 const Extension& extension) const {
996 bool was_installed_by_default = extension.was_installed_by_default();
mamir192d7882016-06-22 17:10:16997#if defined(OS_CHROMEOS)
998 // On Chrome OS all external sources are controlled by us so it means that
999 // they are "default". Method was_installed_by_default returns false because
1000 // extensions creation flags are ignored in case of default extensions with
1001 // update URL(the flags aren't passed to OnExternalExtensionUpdateUrlFound).
1002 // TODO(dpolukhin): remove this Chrome OS specific code as soon as creation
1003 // flags are not ignored.
1004 was_installed_by_default =
mamire9609642016-06-28 22:17:541005 extensions::Manifest::IsExternalLocation(extension.location());
mamir192d7882016-06-22 17:10:161006#endif
1007 // Note: Component extensions are protected from modification/uninstallation
1008 // anyway, so there's no need to enforce them again for supervised users.
1009 // Also, leave policy-installed extensions alone - they have their own
1010 // management; in particular we don't want to override the force-install list.
mamire9609642016-06-28 22:17:541011 if (extensions::Manifest::IsComponentLocation(extension.location()) ||
1012 extensions::Manifest::IsPolicyLocation(extension.location()) ||
1013 extension.is_theme() || extension.from_bookmark() ||
1014 extension.is_shared_module() || was_installed_by_default) {
1015 return ExtensionState::ALLOWED;
mamir192d7882016-06-22 17:10:161016 }
1017
mamire9609642016-06-28 22:17:541018 if (extensions::util::WasInstalledByCustodian(extension.id(), profile_))
1019 return ExtensionState::FORCED;
mamir192d7882016-06-22 17:10:161020
mamire9609642016-06-28 22:17:541021 if (!base::FeatureList::IsEnabled(
1022 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
1023 return ExtensionState::BLOCKED;
1024 }
1025
1026 auto extension_it = approved_extensions_map_.find(extension.id());
1027 // If the installed version is approved, then the extension is allowed,
1028 // otherwise, it requires approval.
1029 if (extension_it != approved_extensions_map_.end() &&
1030 extension_it->second == *extension.version()) {
1031 return ExtensionState::ALLOWED;
1032 }
1033 return ExtensionState::REQUIRE_APPROVAL;
mamir192d7882016-06-22 17:10:161034}
1035
bauerb5f8cda92015-10-07 15:36:441036std::string SupervisedUserService::GetDebugPolicyProviderName() const {
1037 // Save the string space in official builds.
1038#ifdef NDEBUG
1039 NOTREACHED();
1040 return std::string();
1041#else
1042 return "Supervised User Service";
1043#endif
1044}
1045
mamire9609642016-06-28 22:17:541046bool SupervisedUserService::UserMayLoad(const Extension* extension,
bauerb5f8cda92015-10-07 15:36:441047 base::string16* error) const {
1048 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:541049 ExtensionState result = GetExtensionState(*extension);
1050 bool may_load = result != ExtensionState::BLOCKED;
bauerb5f8cda92015-10-07 15:36:441051 if (!may_load && error)
treib2170ea02015-10-13 14:55:121052 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441053 return may_load;
1054}
1055
mamire9609642016-06-28 22:17:541056bool SupervisedUserService::UserMayModifySettings(const Extension* extension,
1057 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:441058 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:541059 ExtensionState result = GetExtensionState(*extension);
1060 // While the following check allows the supervised user to modify the settings
1061 // and enable or disable the extension, MustRemainDisabled properly takes care
1062 // of keeping an extension disabled when required.
1063 // For custodian-installed extensions, the state is always FORCED, even if
1064 // it's waiting for an update approval.
1065 bool may_modify = result != ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:441066 if (!may_modify && error)
treib2170ea02015-10-13 14:55:121067 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441068 return may_modify;
1069}
1070
1071// Note: Having MustRemainInstalled always say "true" for custodian-installed
1072// extensions does NOT prevent remote uninstalls (which is a bit unexpected, but
1073// exactly what we want).
mamire9609642016-06-28 22:17:541074bool SupervisedUserService::MustRemainInstalled(const Extension* extension,
1075 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:441076 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:541077 ExtensionState result = GetExtensionState(*extension);
1078 bool may_not_uninstall = result == ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:441079 if (may_not_uninstall && error)
treib2170ea02015-10-13 14:55:121080 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:441081 return may_not_uninstall;
1082}
1083
mamire9609642016-06-28 22:17:541084bool SupervisedUserService::MustRemainDisabled(const Extension* extension,
1085 Extension::DisableReason* reason,
1086 base::string16* error) const {
1087 DCHECK(ProfileIsSupervised());
1088 ExtensionState state = GetExtensionState(*extension);
1089 // Only extensions that require approval should be disabled.
1090 // Blocked extensions should be not loaded at all, and are taken care of
1091 // at UserMayLoad.
1092 bool must_remain_disabled = state == ExtensionState::REQUIRE_APPROVAL;
1093
1094 if (must_remain_disabled) {
1095 if (error)
1096 *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER);
1097 // If the extension must remain disabled due to permission increase,
1098 // then the update request has been already sent at update time.
1099 // We do nothing and we don't add an extra disable reason.
1100 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1101 if (extension_prefs->HasDisableReason(
1102 extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE)) {
1103 if (reason)
1104 *reason = Extension::DISABLE_PERMISSIONS_INCREASE;
1105 return true;
1106 }
1107 if (reason)
1108 *reason = Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED;
1109 if (base::FeatureList::IsEnabled(
1110 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
1111 // If the Extension isn't pending a custodian approval already, send
1112 // an approval request.
1113 if (!extension_prefs->HasDisableReason(
1114 extension->id(),
1115 Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED)) {
1116 // MustRemainDisabled is a const method and hence cannot call
1117 // AddExtensionInstallRequest directly.
1118 SupervisedUserService* supervised_user_service =
1119 SupervisedUserServiceFactory::GetForProfile(profile_);
1120 supervised_user_service->AddExtensionInstallRequest(
1121 extension->id(), *extension->version());
1122 }
1123 }
1124 }
1125 return must_remain_disabled;
1126}
1127
1128void SupervisedUserService::OnExtensionInstalled(
1129 content::BrowserContext* browser_context,
1130 const extensions::Extension* extension,
1131 bool is_update) {
1132 // This callback method is responsible for updating extension state and
1133 // approved_extensions_map_ upon extension updates.
1134 if (!is_update)
1135 return;
1136
1137 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1138 const std::string& id = extension->id();
1139 const base::Version& version = *extension->version();
1140
1141 // If an already approved extension is updated without requiring
1142 // new permissions, we update the approved_version.
1143 if (!extension_prefs->HasDisableReason(
1144 id, Extension::DISABLE_PERMISSIONS_INCREASE) &&
1145 approved_extensions_map_.count(id) > 0 &&
1146 approved_extensions_map_[id] < version) {
1147 approved_extensions_map_[id] = version;
1148
1149 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1150 supervised_users::kApprovedExtensions, id);
1151 std::unique_ptr<base::Value> version_value(
1152 new base::StringValue(version.GetString()));
1153 GetSettingsService()->UpdateSetting(key, std::move(version_value));
1154 }
1155 // Upon extension update, the approved version may (or may not) match the
1156 // installed one. Therefore, a change in extension state might be required.
1157 ChangeExtensionStateIfNecessary(id);
1158}
1159
1160void SupervisedUserService::UpdateApprovedExtensions() {
1161 const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary(
1162 prefs::kSupervisedUserApprovedExtensions);
1163 // Keep track of currently approved extensions. We may need to disable them if
1164 // they are not in the approved map anymore.
1165 std::set<std::string> extensions_to_be_checked;
1166 for (const auto& extension : approved_extensions_map_)
1167 extensions_to_be_checked.insert(extension.first);
1168
1169 approved_extensions_map_.clear();
1170
1171 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
1172 std::string version_str;
1173 bool result = it.value().GetAsString(&version_str);
1174 DCHECK(result);
1175 base::Version version(version_str);
1176 if (version.IsValid()) {
1177 approved_extensions_map_[it.key()] = version;
1178 extensions_to_be_checked.insert(it.key());
1179 } else {
1180 LOG(WARNING) << "Invalid version number " << version_str;
1181 }
1182 }
1183
1184 for (const auto& extension_id : extensions_to_be_checked) {
1185 ChangeExtensionStateIfNecessary(extension_id);
1186 }
1187}
1188
1189void SupervisedUserService::ChangeExtensionStateIfNecessary(
1190 const std::string& extension_id) {
1191 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
1192 const Extension* extension = registry->GetInstalledExtension(extension_id);
1193 // If the extension is not installed (yet), do nothing.
1194 // Things will be handled after installation.
1195 if (!extension)
1196 return;
1197
1198 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
1199 ExtensionService* service =
1200 ExtensionSystem::Get(profile_)->extension_service();
1201
1202 ExtensionState state = GetExtensionState(*extension);
1203 switch (state) {
1204 // BLOCKED/FORCED extensions should be already disabled/enabled
1205 // and we don't need to change their state here.
1206 case ExtensionState::BLOCKED:
1207 case ExtensionState::FORCED:
1208 break;
1209 case ExtensionState::REQUIRE_APPROVAL:
1210 service->DisableExtension(extension_id,
1211 Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
1212 break;
1213 case ExtensionState::ALLOWED:
1214 extension_prefs->RemoveDisableReason(
1215 extension_id, Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
1216 extension_prefs->RemoveDisableReason(
1217 extension_id, Extension::DISABLE_PERMISSIONS_INCREASE);
1218 // If not disabled for other reasons, enable it.
1219 if (extension_prefs->GetDisableReasons(extension_id) ==
1220 Extension::DISABLE_NONE) {
1221 service->EnableExtension(extension_id);
1222 }
1223 break;
1224 }
1225}
1226
bauerb5f8cda92015-10-07 15:36:441227void SupervisedUserService::SetExtensionsActive() {
1228 extensions::ExtensionSystem* extension_system =
1229 extensions::ExtensionSystem::Get(profile_);
1230 extensions::ManagementPolicy* management_policy =
1231 extension_system->management_policy();
1232
1233 if (management_policy) {
1234 if (active_)
1235 management_policy->RegisterProvider(this);
1236 else
1237 management_policy->UnregisterProvider(this);
1238
1239 // Re-check the policy to make sure any new settings get applied.
1240 extension_system->extension_service()->CheckManagementPolicy();
1241 }
1242}
1243#endif // defined(ENABLE_EXTENSIONS)
1244
1245syncer::ModelTypeSet SupervisedUserService::GetPreferredDataTypes() const {
1246 if (!ProfileIsSupervised())
1247 return syncer::ModelTypeSet();
1248
1249 syncer::ModelTypeSet result;
1250 if (IncludesSyncSessionsType())
1251 result.Put(syncer::SESSIONS);
1252 result.Put(syncer::EXTENSIONS);
1253 result.Put(syncer::EXTENSION_SETTINGS);
1254 result.Put(syncer::APPS);
1255 result.Put(syncer::APP_SETTINGS);
1256 result.Put(syncer::APP_NOTIFICATIONS);
1257 result.Put(syncer::APP_LIST);
1258 return result;
1259}
1260
jam1c5a91492016-02-24 20:47:531261#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:441262void SupervisedUserService::OnStateChanged() {
maxbogue0a379452016-09-22 21:35:051263 browser_sync::ProfileSyncService* service =
bauerb5f8cda92015-10-07 15:36:441264 ProfileSyncServiceFactory::GetForProfile(profile_);
zea32a7684cf2016-02-24 20:41:481265 if (waiting_for_sync_initialization_ && service->IsBackendInitialized()) {
bauerb5f8cda92015-10-07 15:36:441266 waiting_for_sync_initialization_ = false;
1267 service->RemoveObserver(this);
1268 FinishSetupSync();
1269 return;
1270 }
1271
1272 DLOG_IF(ERROR, service->GetAuthError().state() ==
1273 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)
1274 << "Credentials rejected";
1275}
1276
1277void SupervisedUserService::OnBrowserSetLastActive(Browser* browser) {
1278 bool profile_became_active = profile_->IsSameProfile(browser->profile());
1279 if (!is_profile_active_ && profile_became_active)
1280 content::RecordAction(UserMetricsAction("ManagedUsers_OpenProfile"));
1281 else if (is_profile_active_ && !profile_became_active)
1282 content::RecordAction(UserMetricsAction("ManagedUsers_SwitchProfile"));
1283
1284 is_profile_active_ = profile_became_active;
1285}
jam1c5a91492016-02-24 20:47:531286#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:441287
1288void SupervisedUserService::OnSiteListUpdated() {
ericwilligers8b92b052016-10-19 22:21:581289 for (SupervisedUserServiceObserver& observer : observer_list_)
1290 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:441291}