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