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