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