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