Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / supervised_user / supervised_user_service.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/supervised_user/supervised_user_service.h"
6
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_info_cache.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/supervised_user/custodian_profile_downloader_service.h"
20 #include "chrome/browser/supervised_user/custodian_profile_downloader_service_factory.h"
21 #include "chrome/browser/supervised_user/experimental/supervised_user_blacklist_downloader.h"
22 #include "chrome/browser/supervised_user/permission_request_creator_apiary.h"
23 #include "chrome/browser/supervised_user/permission_request_creator_sync.h"
24 #include "chrome/browser/supervised_user/supervised_user_constants.h"
25 #include "chrome/browser/supervised_user/supervised_user_pref_mapping_service.h"
26 #include "chrome/browser/supervised_user/supervised_user_pref_mapping_service_factory.h"
27 #include "chrome/browser/supervised_user/supervised_user_registration_utility.h"
28 #include "chrome/browser/supervised_user/supervised_user_service_observer.h"
29 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
30 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
31 #include "chrome/browser/supervised_user/supervised_user_shared_settings_service_factory.h"
32 #include "chrome/browser/supervised_user/supervised_user_site_list.h"
33 #include "chrome/browser/supervised_user/supervised_user_sync_service.h"
34 #include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h"
35 #include "chrome/browser/sync/profile_sync_service.h"
36 #include "chrome/browser/sync/profile_sync_service_factory.h"
37 #include "chrome/browser/ui/browser.h"
38 #include "chrome/browser/ui/browser_list.h"
39 #include "chrome/common/chrome_switches.h"
40 #include "chrome/common/pref_names.h"
41 #include "chrome/grit/generated_resources.h"
42 #include "components/pref_registry/pref_registry_syncable.h"
43 #include "components/signin/core/browser/profile_oauth2_token_service.h"
44 #include "components/signin/core/browser/signin_manager.h"
45 #include "components/signin/core/browser/signin_manager_base.h"
46 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/user_metrics.h"
48 #include "ui/base/l10n/l10n_util.h"
49
50 #if defined(OS_CHROMEOS)
51 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
52 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
53 #include "components/user_manager/user_manager.h"
54 #endif
55
56 #if defined(ENABLE_EXTENSIONS)
57 #include "chrome/browser/extensions/extension_service.h"
58 #include "chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h"
59 #include "extensions/browser/extension_registry.h"
60 #include "extensions/browser/extension_system.h"
61 #include "extensions/common/extension_set.h"
62 #endif
63
64 #if defined(ENABLE_THEMES)
65 #include "chrome/browser/themes/theme_service.h"
66 #include "chrome/browser/themes/theme_service_factory.h"
67 #endif
68
69 using base::DictionaryValue;
70 using base::UserMetricsAction;
71 using content::BrowserThread;
72
73 base::FilePath SupervisedUserService::Delegate::GetBlacklistPath() const {
74   return base::FilePath();
75 }
76
77 GURL SupervisedUserService::Delegate::GetBlacklistURL() const {
78   return GURL();
79 }
80
81 std::string SupervisedUserService::Delegate::GetSafeSitesCx() const {
82   return std::string();
83 }
84
85 std::string SupervisedUserService::Delegate::GetSafeSitesApiKey() const {
86   return std::string();
87 }
88
89 SupervisedUserService::URLFilterContext::URLFilterContext()
90     : ui_url_filter_(new SupervisedUserURLFilter),
91       io_url_filter_(new SupervisedUserURLFilter) {}
92 SupervisedUserService::URLFilterContext::~URLFilterContext() {}
93
94 SupervisedUserURLFilter*
95 SupervisedUserService::URLFilterContext::ui_url_filter() const {
96   return ui_url_filter_.get();
97 }
98
99 SupervisedUserURLFilter*
100 SupervisedUserService::URLFilterContext::io_url_filter() const {
101   return io_url_filter_.get();
102 }
103
104 void SupervisedUserService::URLFilterContext::SetDefaultFilteringBehavior(
105     SupervisedUserURLFilter::FilteringBehavior behavior) {
106   ui_url_filter_->SetDefaultFilteringBehavior(behavior);
107   BrowserThread::PostTask(
108       BrowserThread::IO,
109       FROM_HERE,
110       base::Bind(&SupervisedUserURLFilter::SetDefaultFilteringBehavior,
111                  io_url_filter_.get(), behavior));
112 }
113
114 void SupervisedUserService::URLFilterContext::LoadWhitelists(
115     ScopedVector<SupervisedUserSiteList> site_lists) {
116   // SupervisedUserURLFilter::LoadWhitelists takes ownership of |site_lists|,
117   // so we make an additional copy of it.
118   // TODO(bauerb): This is kinda ugly.
119   ScopedVector<SupervisedUserSiteList> site_lists_copy;
120   for (const SupervisedUserSiteList* site_list : site_lists)
121     site_lists_copy.push_back(site_list->Clone());
122
123   ui_url_filter_->LoadWhitelists(site_lists.Pass());
124   BrowserThread::PostTask(
125       BrowserThread::IO,
126       FROM_HERE,
127       base::Bind(&SupervisedUserURLFilter::LoadWhitelists,
128                  io_url_filter_, base::Passed(&site_lists_copy)));
129 }
130
131 void SupervisedUserService::URLFilterContext::LoadBlacklist(
132     const base::FilePath& path) {
133   // For now, support loading only once. If we want to support re-load, we'll
134   // have to clear the blacklist pointer in the url filters first.
135   DCHECK_EQ(0u, blacklist_.GetEntryCount());
136   blacklist_.ReadFromFile(
137       path,
138       base::Bind(&SupervisedUserService::URLFilterContext::OnBlacklistLoaded,
139                  base::Unretained(this)));
140 }
141
142 void SupervisedUserService::URLFilterContext::SetManualHosts(
143     scoped_ptr<std::map<std::string, bool> > host_map) {
144   ui_url_filter_->SetManualHosts(host_map.get());
145   BrowserThread::PostTask(
146       BrowserThread::IO,
147       FROM_HERE,
148       base::Bind(&SupervisedUserURLFilter::SetManualHosts,
149                  io_url_filter_, base::Owned(host_map.release())));
150 }
151
152 void SupervisedUserService::URLFilterContext::SetManualURLs(
153     scoped_ptr<std::map<GURL, bool> > url_map) {
154   ui_url_filter_->SetManualURLs(url_map.get());
155   BrowserThread::PostTask(
156       BrowserThread::IO,
157       FROM_HERE,
158       base::Bind(&SupervisedUserURLFilter::SetManualURLs,
159                  io_url_filter_, base::Owned(url_map.release())));
160 }
161
162 void SupervisedUserService::URLFilterContext::OnBlacklistLoaded() {
163   ui_url_filter_->SetBlacklist(&blacklist_);
164   BrowserThread::PostTask(
165       BrowserThread::IO,
166       FROM_HERE,
167       base::Bind(&SupervisedUserURLFilter::SetBlacklist,
168                  io_url_filter_,
169                  &blacklist_));
170 }
171
172 void SupervisedUserService::URLFilterContext::InitAsyncURLChecker(
173     net::URLRequestContextGetter* context,
174     const std::string& cx,
175     const std::string& api_key) {
176   ui_url_filter_->InitAsyncURLChecker(context, cx, api_key);
177   BrowserThread::PostTask(
178       BrowserThread::IO,
179       FROM_HERE,
180       base::Bind(&SupervisedUserURLFilter::InitAsyncURLChecker,
181                  io_url_filter_, context, cx, api_key));
182 }
183
184 SupervisedUserService::SupervisedUserService(Profile* profile)
185     : includes_sync_sessions_type_(true),
186       profile_(profile),
187       active_(false),
188       delegate_(NULL),
189 #if defined(ENABLE_EXTENSIONS)
190       extension_registry_observer_(this),
191 #endif
192       waiting_for_sync_initialization_(false),
193       is_profile_active_(false),
194       elevated_for_testing_(false),
195       did_init_(false),
196       did_shutdown_(false),
197       weak_ptr_factory_(this) {
198 }
199
200 SupervisedUserService::~SupervisedUserService() {
201   DCHECK(!did_init_ || did_shutdown_);
202 }
203
204 void SupervisedUserService::Shutdown() {
205   if (!did_init_)
206     return;
207   DCHECK(!did_shutdown_);
208   did_shutdown_ = true;
209   if (ProfileIsSupervised()) {
210     content::RecordAction(UserMetricsAction("ManagedUsers_QuitBrowser"));
211   }
212   SetActive(false);
213
214   ProfileSyncService* sync_service =
215       ProfileSyncServiceFactory::GetForProfile(profile_);
216   // Can be null in tests.
217   if (sync_service)
218     sync_service->RemovePreferenceProvider(this);
219 }
220
221 bool SupervisedUserService::ProfileIsSupervised() const {
222   return profile_->IsSupervised();
223 }
224
225 void SupervisedUserService::OnCustodianInfoChanged() {
226   FOR_EACH_OBSERVER(
227       SupervisedUserServiceObserver, observer_list_, OnCustodianInfoChanged());
228 }
229
230 // static
231 void SupervisedUserService::RegisterProfilePrefs(
232     user_prefs::PrefRegistrySyncable* registry) {
233   registry->RegisterDictionaryPref(
234       prefs::kSupervisedUserManualHosts,
235       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
236   registry->RegisterDictionaryPref(
237       prefs::kSupervisedUserManualURLs,
238       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
239   registry->RegisterIntegerPref(
240       prefs::kDefaultSupervisedUserFilteringBehavior,
241       SupervisedUserURLFilter::ALLOW,
242       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
243   registry->RegisterStringPref(
244       prefs::kSupervisedUserCustodianEmail, std::string(),
245       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
246   registry->RegisterStringPref(
247       prefs::kSupervisedUserCustodianName, std::string(),
248       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
249   registry->RegisterStringPref(
250       prefs::kSupervisedUserCustodianProfileImageURL, std::string(),
251       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
252   registry->RegisterStringPref(
253       prefs::kSupervisedUserCustodianProfileURL, std::string(),
254       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
255   registry->RegisterStringPref(
256       prefs::kSupervisedUserSecondCustodianEmail, std::string(),
257       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
258   registry->RegisterStringPref(
259       prefs::kSupervisedUserSecondCustodianName, std::string(),
260       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
261   registry->RegisterStringPref(
262       prefs::kSupervisedUserSecondCustodianProfileImageURL, std::string(),
263       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
264   registry->RegisterStringPref(
265       prefs::kSupervisedUserSecondCustodianProfileURL, std::string(),
266       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
267   registry->RegisterBooleanPref(prefs::kSupervisedUserCreationAllowed, true,
268       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
269 }
270
271 void SupervisedUserService::SetDelegate(Delegate* delegate) {
272   if (delegate) {
273     // Changing delegates isn't allowed.
274     DCHECK(!delegate_);
275   } else {
276     // If the delegate is removed, deactivate first to give the old delegate a
277     // chance to clean up.
278     SetActive(false);
279   }
280   delegate_ = delegate;
281 }
282
283 scoped_refptr<const SupervisedUserURLFilter>
284 SupervisedUserService::GetURLFilterForIOThread() {
285   return url_filter_context_.io_url_filter();
286 }
287
288 SupervisedUserURLFilter* SupervisedUserService::GetURLFilterForUIThread() {
289   return url_filter_context_.ui_url_filter();
290 }
291
292 // Items not on any list must return -1 (CATEGORY_NOT_ON_LIST in history.js).
293 // Items on a list, but with no category, must return 0 (CATEGORY_OTHER).
294 #define CATEGORY_NOT_ON_LIST -1;
295 #define CATEGORY_OTHER 0;
296
297 int SupervisedUserService::GetCategory(const GURL& url) {
298   std::vector<SupervisedUserSiteList::Site*> sites;
299   GetURLFilterForUIThread()->GetSites(url, &sites);
300   if (sites.empty())
301     return CATEGORY_NOT_ON_LIST;
302
303   return (*sites.begin())->category_id;
304 }
305
306 // static
307 void SupervisedUserService::GetCategoryNames(CategoryList* list) {
308   SupervisedUserSiteList::GetCategoryNames(list);
309 }
310
311 std::string SupervisedUserService::GetCustodianEmailAddress() const {
312   std::string custodian_email = profile_->GetPrefs()->GetString(
313       prefs::kSupervisedUserCustodianEmail);
314 #if defined(OS_CHROMEOS)
315   if (custodian_email.empty()) {
316     custodian_email = chromeos::ChromeUserManager::Get()
317         ->GetSupervisedUserManager()
318         ->GetManagerDisplayEmail(
319             user_manager::UserManager::Get()->GetActiveUser()->email());
320   }
321 #endif
322   return custodian_email;
323 }
324
325 std::string SupervisedUserService::GetCustodianName() const {
326   std::string name = profile_->GetPrefs()->GetString(
327       prefs::kSupervisedUserCustodianName);
328 #if defined(OS_CHROMEOS)
329   if (name.empty()) {
330     name = base::UTF16ToUTF8(chromeos::ChromeUserManager::Get()
331         ->GetSupervisedUserManager()
332         ->GetManagerDisplayName(
333             user_manager::UserManager::Get()->GetActiveUser()->email()));
334   }
335 #endif
336   return name.empty() ? GetCustodianEmailAddress() : name;
337 }
338
339 std::string SupervisedUserService::GetSecondCustodianEmailAddress() const {
340   return profile_->GetPrefs()->GetString(
341       prefs::kSupervisedUserSecondCustodianEmail);
342 }
343
344 std::string SupervisedUserService::GetSecondCustodianName() const {
345   std::string name = profile_->GetPrefs()->GetString(
346       prefs::kSupervisedUserSecondCustodianName);
347   return name.empty() ? GetSecondCustodianEmailAddress() : name;
348 }
349
350 void SupervisedUserService::AddNavigationBlockedCallback(
351     const NavigationBlockedCallback& callback) {
352   navigation_blocked_callbacks_.push_back(callback);
353 }
354
355 void SupervisedUserService::DidBlockNavigation(
356     content::WebContents* web_contents) {
357   for (const auto& callback : navigation_blocked_callbacks_)
358     callback.Run(web_contents);
359 }
360
361 void SupervisedUserService::AddObserver(
362     SupervisedUserServiceObserver* observer) {
363   observer_list_.AddObserver(observer);
364 }
365
366 void SupervisedUserService::RemoveObserver(
367     SupervisedUserServiceObserver* observer) {
368   observer_list_.RemoveObserver(observer);
369 }
370
371 void SupervisedUserService::AddPermissionRequestCreatorForTesting(
372     PermissionRequestCreator* creator) {
373   permissions_creators_.push_back(creator);
374 }
375
376 #if defined(ENABLE_EXTENSIONS)
377 std::string SupervisedUserService::GetDebugPolicyProviderName() const {
378   // Save the string space in official builds.
379 #ifdef NDEBUG
380   NOTREACHED();
381   return std::string();
382 #else
383   return "Supervised User Service";
384 #endif
385 }
386
387 bool SupervisedUserService::UserMayLoad(const extensions::Extension* extension,
388                                         base::string16* error) const {
389   base::string16 tmp_error;
390   if (ExtensionManagementPolicyImpl(extension, &tmp_error))
391     return true;
392
393   bool was_installed_by_default = extension->was_installed_by_default();
394   bool was_installed_by_custodian = extension->was_installed_by_custodian();
395 #if defined(OS_CHROMEOS)
396   // On Chrome OS all external sources are controlled by us so it means that
397   // they are "default". Method was_installed_by_default returns false because
398   // extensions creation flags are ignored in case of default extensions with
399   // update URL(the flags aren't passed to OnExternalExtensionUpdateUrlFound).
400   // TODO(dpolukhin): remove this Chrome OS specific code as soon as creation
401   // flags are not ignored.
402   was_installed_by_default =
403       extensions::Manifest::IsExternalLocation(extension->location());
404 #endif
405   if (extensions::Manifest::IsComponentLocation(extension->location()) ||
406       was_installed_by_default ||
407       was_installed_by_custodian) {
408     return true;
409   }
410
411   if (error)
412     *error = tmp_error;
413   return false;
414 }
415
416 bool SupervisedUserService::UserMayModifySettings(
417     const extensions::Extension* extension,
418     base::string16* error) const {
419   return ExtensionManagementPolicyImpl(extension, error);
420 }
421
422 void SupervisedUserService::OnExtensionLoaded(
423     content::BrowserContext* browser_context,
424     const extensions::Extension* extension) {
425   if (!extensions::SupervisedUserInfo::GetContentPackSiteList(extension)
426            .empty()) {
427     UpdateSiteLists();
428   }
429 }
430 void SupervisedUserService::OnExtensionUnloaded(
431     content::BrowserContext* browser_context,
432     const extensions::Extension* extension,
433     extensions::UnloadedExtensionInfo::Reason reason) {
434   if (!extensions::SupervisedUserInfo::GetContentPackSiteList(extension)
435            .empty()) {
436     UpdateSiteLists();
437   }
438 }
439 #endif  // defined(ENABLE_EXTENSIONS)
440
441 syncer::ModelTypeSet SupervisedUserService::GetPreferredDataTypes() const {
442   if (!ProfileIsSupervised())
443     return syncer::ModelTypeSet();
444
445   syncer::ModelTypeSet result;
446   if (IncludesSyncSessionsType())
447     result.Put(syncer::SESSIONS);
448   result.Put(syncer::EXTENSIONS);
449   result.Put(syncer::EXTENSION_SETTINGS);
450   result.Put(syncer::APPS);
451   result.Put(syncer::APP_SETTINGS);
452   result.Put(syncer::APP_NOTIFICATIONS);
453   result.Put(syncer::APP_LIST);
454   return result;
455 }
456
457 void SupervisedUserService::OnHistoryRecordingStateChanged() {
458   includes_sync_sessions_type_ =
459       profile_->GetPrefs()->GetBoolean(prefs::kRecordHistory);
460   ProfileSyncServiceFactory::GetForProfile(profile_)
461       ->ReconfigureDatatypeManager();
462 }
463
464 bool SupervisedUserService::IncludesSyncSessionsType() const {
465   return includes_sync_sessions_type_;
466 }
467
468 void SupervisedUserService::OnStateChanged() {
469   ProfileSyncService* service =
470       ProfileSyncServiceFactory::GetForProfile(profile_);
471   if (waiting_for_sync_initialization_ && service->backend_initialized() &&
472       service->backend_mode() == ProfileSyncService::SYNC) {
473     waiting_for_sync_initialization_ = false;
474     service->RemoveObserver(this);
475     FinishSetupSync();
476     return;
477   }
478
479   DLOG_IF(ERROR, service->GetAuthError().state() ==
480                      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)
481       << "Credentials rejected";
482 }
483
484 void SupervisedUserService::SetupSync() {
485   StartSetupSync();
486   FinishSetupSyncWhenReady();
487 }
488
489 void SupervisedUserService::StartSetupSync() {
490   // Tell the sync service that setup is in progress so we don't start syncing
491   // until we've finished configuration.
492   ProfileSyncServiceFactory::GetForProfile(profile_)->SetSetupInProgress(true);
493 }
494
495 void SupervisedUserService::FinishSetupSyncWhenReady() {
496   // If we're already waiting for the Sync backend, there's nothing to do here.
497   if (waiting_for_sync_initialization_)
498     return;
499
500   // Continue in FinishSetupSync() once the Sync backend has been initialized.
501   ProfileSyncService* service =
502       ProfileSyncServiceFactory::GetForProfile(profile_);
503   if (service->backend_initialized() &&
504       service->backend_mode() == ProfileSyncService::SYNC) {
505     FinishSetupSync();
506   } else {
507     service->AddObserver(this);
508     waiting_for_sync_initialization_ = true;
509   }
510 }
511
512 void SupervisedUserService::FinishSetupSync() {
513   ProfileSyncService* service =
514       ProfileSyncServiceFactory::GetForProfile(profile_);
515   DCHECK(service->backend_initialized());
516   DCHECK(service->backend_mode() == ProfileSyncService::SYNC);
517
518   // Sync nothing (except types which are set via GetPreferredDataTypes).
519   bool sync_everything = false;
520   syncer::ModelTypeSet synced_datatypes;
521   service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
522
523   // Notify ProfileSyncService that we are done with configuration.
524   service->SetSetupInProgress(false);
525   service->SetSyncSetupCompleted();
526 }
527
528 #if defined(ENABLE_EXTENSIONS)
529 bool SupervisedUserService::ExtensionManagementPolicyImpl(
530     const extensions::Extension* extension,
531     base::string16* error) const {
532   // |extension| can be NULL in unit_tests.
533   if (!ProfileIsSupervised() || (extension && extension->is_theme()))
534     return true;
535
536   if (elevated_for_testing_)
537     return true;
538
539   if (error)
540     *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER);
541   return false;
542 }
543
544 ScopedVector<SupervisedUserSiteList>
545 SupervisedUserService::GetActiveSiteLists() {
546   ScopedVector<SupervisedUserSiteList> site_lists;
547   ExtensionService* extension_service =
548       extensions::ExtensionSystem::Get(profile_)->extension_service();
549   // Can be NULL in unit tests.
550   if (!extension_service)
551     return site_lists.Pass();
552
553   for (const scoped_refptr<const extensions::Extension>& extension :
554            *extension_service->extensions()) {
555     if (!extension_service->IsExtensionEnabled(extension->id()))
556       continue;
557
558     extensions::ExtensionResource site_list =
559         extensions::SupervisedUserInfo::GetContentPackSiteList(extension.get());
560     if (!site_list.empty()) {
561       site_lists.push_back(new SupervisedUserSiteList(site_list.GetFilePath()));
562     }
563   }
564
565   return site_lists.Pass();
566 }
567
568 void SupervisedUserService::SetExtensionsActive() {
569   extensions::ExtensionSystem* extension_system =
570       extensions::ExtensionSystem::Get(profile_);
571   extensions::ManagementPolicy* management_policy =
572       extension_system->management_policy();
573
574   if (active_) {
575     if (management_policy)
576       management_policy->RegisterProvider(this);
577
578     extension_registry_observer_.Add(
579         extensions::ExtensionRegistry::Get(profile_));
580   } else {
581     if (management_policy)
582       management_policy->UnregisterProvider(this);
583
584     extension_registry_observer_.RemoveAll();
585   }
586 }
587 #endif  // defined(ENABLE_EXTENSIONS)
588
589 SupervisedUserSettingsService* SupervisedUserService::GetSettingsService() {
590   return SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
591 }
592
593 size_t SupervisedUserService::FindEnabledPermissionRequestCreator(
594     size_t start) {
595   for (size_t i = start; i < permissions_creators_.size(); ++i) {
596     if (permissions_creators_[i]->IsEnabled())
597       return i;
598   }
599   return permissions_creators_.size();
600 }
601
602 void SupervisedUserService::AddAccessRequestInternal(
603     const GURL& url,
604     const SuccessCallback& callback,
605     size_t index) {
606   // Find a permission request creator that is enabled.
607   size_t next_index = FindEnabledPermissionRequestCreator(index);
608   if (next_index >= permissions_creators_.size()) {
609     callback.Run(false);
610     return;
611   }
612
613   permissions_creators_[next_index]->CreatePermissionRequest(
614       url,
615       base::Bind(&SupervisedUserService::OnPermissionRequestIssued,
616                  weak_ptr_factory_.GetWeakPtr(), url, callback, next_index));
617 }
618
619 void SupervisedUserService::OnPermissionRequestIssued(
620     const GURL& url,
621     const SuccessCallback& callback,
622     size_t index,
623     bool success) {
624   if (success) {
625     callback.Run(true);
626     return;
627   }
628
629   AddAccessRequestInternal(url, callback, index + 1);
630 }
631
632 void SupervisedUserService::OnSupervisedUserIdChanged() {
633   std::string supervised_user_id =
634       profile_->GetPrefs()->GetString(prefs::kSupervisedUserId);
635   SetActive(!supervised_user_id.empty());
636 }
637
638 void SupervisedUserService::OnDefaultFilteringBehaviorChanged() {
639   DCHECK(ProfileIsSupervised());
640
641   int behavior_value = profile_->GetPrefs()->GetInteger(
642       prefs::kDefaultSupervisedUserFilteringBehavior);
643   SupervisedUserURLFilter::FilteringBehavior behavior =
644       SupervisedUserURLFilter::BehaviorFromInt(behavior_value);
645   url_filter_context_.SetDefaultFilteringBehavior(behavior);
646
647   FOR_EACH_OBSERVER(
648       SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
649 }
650
651 void SupervisedUserService::UpdateSiteLists() {
652 #if defined(ENABLE_EXTENSIONS)
653   url_filter_context_.LoadWhitelists(GetActiveSiteLists());
654
655   FOR_EACH_OBSERVER(
656       SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
657 #endif
658 }
659
660 void SupervisedUserService::LoadBlacklist(const base::FilePath& path,
661                                           const GURL& url) {
662   if (!url.is_valid()) {
663     LoadBlacklistFromFile(path);
664     return;
665   }
666
667   DCHECK(!blacklist_downloader_.get());
668   blacklist_downloader_.reset(new SupervisedUserBlacklistDownloader(
669       url,
670       path,
671       profile_->GetRequestContext(),
672       base::Bind(&SupervisedUserService::OnBlacklistDownloadDone,
673                  base::Unretained(this), path)));
674 }
675
676 void SupervisedUserService::LoadBlacklistFromFile(const base::FilePath& path) {
677   url_filter_context_.LoadBlacklist(path);
678
679   FOR_EACH_OBSERVER(
680       SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
681 }
682
683 void SupervisedUserService::OnBlacklistDownloadDone(const base::FilePath& path,
684                                                     bool success) {
685   if (success) {
686     LoadBlacklistFromFile(path);
687   } else {
688     LOG(WARNING) << "Blacklist download failed";
689   }
690   blacklist_downloader_.reset();
691 }
692
693 bool SupervisedUserService::AccessRequestsEnabled() {
694   return FindEnabledPermissionRequestCreator(0) < permissions_creators_.size();
695 }
696
697 void SupervisedUserService::AddAccessRequest(const GURL& url,
698                                              const SuccessCallback& callback) {
699   AddAccessRequestInternal(SupervisedUserURLFilter::Normalize(url), callback,
700                            0);
701 }
702
703 void SupervisedUserService::InitSync(const std::string& refresh_token) {
704   StartSetupSync();
705
706   ProfileOAuth2TokenService* token_service =
707       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
708   token_service->UpdateCredentials(supervised_users::kSupervisedUserPseudoEmail,
709                                    refresh_token);
710
711   FinishSetupSyncWhenReady();
712 }
713
714 void SupervisedUserService::Init() {
715   DCHECK(!did_init_);
716   did_init_ = true;
717   DCHECK(GetSettingsService()->IsReady());
718
719   pref_change_registrar_.Init(profile_->GetPrefs());
720   pref_change_registrar_.Add(
721       prefs::kSupervisedUserId,
722       base::Bind(&SupervisedUserService::OnSupervisedUserIdChanged,
723           base::Unretained(this)));
724   pref_change_registrar_.Add(
725       prefs::kRecordHistory,
726       base::Bind(&SupervisedUserService::OnHistoryRecordingStateChanged,
727                  base::Unretained(this)));
728
729   ProfileSyncService* sync_service =
730       ProfileSyncServiceFactory::GetForProfile(profile_);
731   // Can be null in tests.
732   if (sync_service)
733     sync_service->AddPreferenceProvider(this);
734
735   SetActive(ProfileIsSupervised());
736 }
737
738 void SupervisedUserService::SetActive(bool active) {
739   if (active_ == active)
740     return;
741   active_ = active;
742
743   if (!delegate_ || !delegate_->SetActive(active_)) {
744     if (active_) {
745       SupervisedUserPrefMappingServiceFactory::GetForBrowserContext(profile_)
746           ->Init();
747
748       CommandLine* command_line = CommandLine::ForCurrentProcess();
749       if (command_line->HasSwitch(switches::kSupervisedUserSyncToken)) {
750         InitSync(
751             command_line->GetSwitchValueASCII(
752                 switches::kSupervisedUserSyncToken));
753       }
754
755       ProfileOAuth2TokenService* token_service =
756           ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
757       token_service->LoadCredentials(
758           supervised_users::kSupervisedUserPseudoEmail);
759
760       SetupSync();
761     }
762   }
763
764   // Now activate/deactivate anything not handled by the delegate yet.
765
766 #if defined(ENABLE_THEMES)
767   // Re-set the default theme to turn the SU theme on/off.
768   ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile_);
769   if (theme_service->UsingDefaultTheme() || theme_service->UsingSystemTheme()) {
770     ThemeServiceFactory::GetForProfile(profile_)->UseDefaultTheme();
771   }
772 #endif
773
774   ProfileSyncService* sync_service =
775       ProfileSyncServiceFactory::GetForProfile(profile_);
776   sync_service->SetEncryptEverythingAllowed(!active_);
777
778   GetSettingsService()->SetActive(active_);
779
780 #if defined(ENABLE_EXTENSIONS)
781   SetExtensionsActive();
782 #endif
783
784   if (active_) {
785     if (CommandLine::ForCurrentProcess()->HasSwitch(
786             switches::kPermissionRequestApiUrl)) {
787       GURL url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
788           switches::kPermissionRequestApiUrl));
789       if (url.is_valid()) {
790         scoped_ptr<PermissionRequestCreator> creator =
791             PermissionRequestCreatorApiary::CreateWithProfile(profile_, url);
792         permissions_creators_.push_back(creator.release());
793       } else {
794         LOG(WARNING) << "Got invalid URL for "
795                      << switches::kPermissionRequestApiUrl;
796       }
797     } else {
798       permissions_creators_.push_back(new PermissionRequestCreatorSync(
799           GetSettingsService(),
800           SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(
801               profile_),
802           ProfileSyncServiceFactory::GetForProfile(profile_),
803           GetSupervisedUserName(),
804           profile_->GetPrefs()->GetString(prefs::kSupervisedUserId)));
805     }
806
807     pref_change_registrar_.Add(
808         prefs::kDefaultSupervisedUserFilteringBehavior,
809         base::Bind(&SupervisedUserService::OnDefaultFilteringBehaviorChanged,
810             base::Unretained(this)));
811     pref_change_registrar_.Add(prefs::kSupervisedUserManualHosts,
812         base::Bind(&SupervisedUserService::UpdateManualHosts,
813                    base::Unretained(this)));
814     pref_change_registrar_.Add(prefs::kSupervisedUserManualURLs,
815         base::Bind(&SupervisedUserService::UpdateManualURLs,
816                    base::Unretained(this)));
817     pref_change_registrar_.Add(prefs::kSupervisedUserCustodianName,
818         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
819                    base::Unretained(this)));
820     pref_change_registrar_.Add(prefs::kSupervisedUserCustodianEmail,
821         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
822                    base::Unretained(this)));
823     pref_change_registrar_.Add(prefs::kSupervisedUserCustodianProfileImageURL,
824         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
825                    base::Unretained(this)));
826     pref_change_registrar_.Add(prefs::kSupervisedUserCustodianProfileURL,
827         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
828                    base::Unretained(this)));
829     pref_change_registrar_.Add(prefs::kSupervisedUserSecondCustodianName,
830         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
831                    base::Unretained(this)));
832     pref_change_registrar_.Add(prefs::kSupervisedUserSecondCustodianEmail,
833         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
834                    base::Unretained(this)));
835     pref_change_registrar_.Add(
836         prefs::kSupervisedUserSecondCustodianProfileImageURL,
837         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
838                    base::Unretained(this)));
839     pref_change_registrar_.Add(prefs::kSupervisedUserSecondCustodianProfileURL,
840         base::Bind(&SupervisedUserService::OnCustodianInfoChanged,
841                    base::Unretained(this)));
842
843     // Initialize the filter.
844     OnDefaultFilteringBehaviorChanged();
845     UpdateSiteLists();
846     UpdateManualHosts();
847     UpdateManualURLs();
848     bool use_blacklist =
849         CommandLine::ForCurrentProcess()->HasSwitch(
850             switches::kEnableSupervisedUserBlacklist);
851     if (delegate_ && use_blacklist) {
852       base::FilePath blacklist_path = delegate_->GetBlacklistPath();
853       if (!blacklist_path.empty())
854         LoadBlacklist(blacklist_path, delegate_->GetBlacklistURL());
855     }
856     bool use_safesites =
857         CommandLine::ForCurrentProcess()->HasSwitch(
858             switches::kEnableSupervisedUserSafeSites);
859     if (delegate_ && use_safesites) {
860       const std::string& cx = delegate_->GetSafeSitesCx();
861       if (!cx.empty()) {
862         url_filter_context_.InitAsyncURLChecker(
863             profile_->GetRequestContext(), cx, delegate_->GetSafeSitesApiKey());
864       }
865     }
866
867 #if !defined(OS_ANDROID)
868     // TODO(bauerb): Get rid of the platform-specific #ifdef here.
869     // http://crbug.com/313377
870     BrowserList::AddObserver(this);
871 #endif
872   } else {
873     permissions_creators_.clear();
874
875     pref_change_registrar_.Remove(
876         prefs::kDefaultSupervisedUserFilteringBehavior);
877     pref_change_registrar_.Remove(prefs::kSupervisedUserManualHosts);
878     pref_change_registrar_.Remove(prefs::kSupervisedUserManualURLs);
879
880     if (waiting_for_sync_initialization_)
881       ProfileSyncServiceFactory::GetForProfile(profile_)->RemoveObserver(this);
882
883 #if !defined(OS_ANDROID)
884     // TODO(bauerb): Get rid of the platform-specific #ifdef here.
885     // http://crbug.com/313377
886     BrowserList::RemoveObserver(this);
887 #endif
888   }
889 }
890
891 void SupervisedUserService::RegisterAndInitSync(
892     SupervisedUserRegistrationUtility* registration_utility,
893     Profile* custodian_profile,
894     const std::string& supervised_user_id,
895     const AuthErrorCallback& callback) {
896   DCHECK(ProfileIsSupervised());
897   DCHECK(!custodian_profile->IsSupervised());
898
899   base::string16 name = base::UTF8ToUTF16(
900       profile_->GetPrefs()->GetString(prefs::kProfileName));
901   int avatar_index = profile_->GetPrefs()->GetInteger(
902       prefs::kProfileAvatarIndex);
903   SupervisedUserRegistrationInfo info(name, avatar_index);
904   registration_utility->Register(
905       supervised_user_id,
906       info,
907       base::Bind(&SupervisedUserService::OnSupervisedUserRegistered,
908                  weak_ptr_factory_.GetWeakPtr(), callback, custodian_profile));
909
910   // Fetch the custodian's profile information, to store the name.
911   // TODO(pamg): If --google-profile-info (flag: switches::kGoogleProfileInfo)
912   // is ever enabled, take the name from the ProfileInfoCache instead.
913   CustodianProfileDownloaderService* profile_downloader_service =
914       CustodianProfileDownloaderServiceFactory::GetForProfile(
915           custodian_profile);
916   profile_downloader_service->DownloadProfile(
917       base::Bind(&SupervisedUserService::OnCustodianProfileDownloaded,
918                  weak_ptr_factory_.GetWeakPtr()));
919 }
920
921 void SupervisedUserService::OnCustodianProfileDownloaded(
922     const base::string16& full_name) {
923   profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianName,
924                                   base::UTF16ToUTF8(full_name));
925 }
926
927 void SupervisedUserService::OnSupervisedUserRegistered(
928     const AuthErrorCallback& callback,
929     Profile* custodian_profile,
930     const GoogleServiceAuthError& auth_error,
931     const std::string& token) {
932   if (auth_error.state() == GoogleServiceAuthError::NONE) {
933     InitSync(token);
934     SigninManagerBase* signin =
935         SigninManagerFactory::GetForProfile(custodian_profile);
936     profile_->GetPrefs()->SetString(prefs::kSupervisedUserCustodianEmail,
937                                     signin->GetAuthenticatedUsername());
938
939     // The supervised user profile is now ready for use.
940     ProfileManager* profile_manager = g_browser_process->profile_manager();
941     ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
942     size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
943     cache.SetIsOmittedProfileAtIndex(index, false);
944   } else {
945     DCHECK_EQ(std::string(), token);
946   }
947
948   callback.Run(auth_error);
949 }
950
951 void SupervisedUserService::UpdateManualHosts() {
952   const base::DictionaryValue* dict =
953       profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualHosts);
954   scoped_ptr<std::map<std::string, bool> > host_map(
955       new std::map<std::string, bool>());
956   for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
957     bool allow = false;
958     bool result = it.value().GetAsBoolean(&allow);
959     DCHECK(result);
960     (*host_map)[it.key()] = allow;
961   }
962   url_filter_context_.SetManualHosts(host_map.Pass());
963
964   FOR_EACH_OBSERVER(
965       SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
966 }
967
968 void SupervisedUserService::UpdateManualURLs() {
969   const base::DictionaryValue* dict =
970       profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualURLs);
971   scoped_ptr<std::map<GURL, bool> > url_map(new std::map<GURL, bool>());
972   for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
973     bool allow = false;
974     bool result = it.value().GetAsBoolean(&allow);
975     DCHECK(result);
976     (*url_map)[GURL(it.key())] = allow;
977   }
978   url_filter_context_.SetManualURLs(url_map.Pass());
979
980   FOR_EACH_OBSERVER(
981       SupervisedUserServiceObserver, observer_list_, OnURLFilterChanged());
982 }
983
984 void SupervisedUserService::OnBrowserSetLastActive(Browser* browser) {
985   bool profile_became_active = profile_->IsSameProfile(browser->profile());
986   if (!is_profile_active_ && profile_became_active)
987     content::RecordAction(UserMetricsAction("ManagedUsers_OpenProfile"));
988   else if (is_profile_active_ && !profile_became_active)
989     content::RecordAction(UserMetricsAction("ManagedUsers_SwitchProfile"));
990
991   is_profile_active_ = profile_became_active;
992 }
993
994 std::string SupervisedUserService::GetSupervisedUserName() const {
995 #if defined(OS_CHROMEOS)
996   // The active user can be NULL in unit tests.
997   if (user_manager::UserManager::Get()->GetActiveUser()) {
998     return UTF16ToUTF8(user_manager::UserManager::Get()->GetUserDisplayName(
999         user_manager::UserManager::Get()->GetActiveUser()->GetUserID()));
1000   }
1001   return std::string();
1002 #else
1003   return profile_->GetPrefs()->GetString(prefs::kProfileName);
1004 #endif
1005 }