Home | History | Annotate | Download | only in managed_mode
      1 // Copyright (c) 2013 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/managed_mode/managed_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/chrome_notification_types.h"
     13 #include "chrome/browser/extensions/extension_service.h"
     14 #include "chrome/browser/extensions/extension_system.h"
     15 #include "chrome/browser/managed_mode/custodian_profile_downloader_service.h"
     16 #include "chrome/browser/managed_mode/custodian_profile_downloader_service_factory.h"
     17 #include "chrome/browser/managed_mode/managed_mode_site_list.h"
     18 #include "chrome/browser/managed_mode/managed_user_constants.h"
     19 #include "chrome/browser/managed_mode/managed_user_registration_utility.h"
     20 #include "chrome/browser/managed_mode/managed_user_settings_service.h"
     21 #include "chrome/browser/managed_mode/managed_user_settings_service_factory.h"
     22 #include "chrome/browser/managed_mode/managed_user_sync_service.h"
     23 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
     24 #include "chrome/browser/profiles/profile.h"
     25 #include "chrome/browser/signin/profile_oauth2_token_service.h"
     26 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
     27 #include "chrome/browser/signin/signin_manager.h"
     28 #include "chrome/browser/signin/signin_manager_base.h"
     29 #include "chrome/browser/signin/signin_manager_factory.h"
     30 #include "chrome/browser/sync/profile_sync_service.h"
     31 #include "chrome/browser/sync/profile_sync_service_factory.h"
     32 #include "chrome/browser/ui/browser.h"
     33 #include "chrome/browser/ui/browser_list.h"
     34 #include "chrome/common/chrome_switches.h"
     35 #include "chrome/common/extensions/api/managed_mode_private/managed_mode_handler.h"
     36 #include "chrome/common/extensions/extension_set.h"
     37 #include "chrome/common/pref_names.h"
     38 #include "components/user_prefs/pref_registry_syncable.h"
     39 #include "content/public/browser/browser_thread.h"
     40 #include "content/public/browser/notification_details.h"
     41 #include "content/public/browser/notification_source.h"
     42 #include "google_apis/gaia/google_service_auth_error.h"
     43 #include "grit/generated_resources.h"
     44 #include "net/base/escape.h"
     45 #include "ui/base/l10n/l10n_util.h"
     46 
     47 #if defined(OS_CHROMEOS)
     48 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
     49 #include "chrome/browser/chromeos/login/user_manager.h"
     50 #endif
     51 
     52 using base::DictionaryValue;
     53 using content::BrowserThread;
     54 
     55 const char kManagedUserAccessRequestKeyPrefix[] =
     56     "X-ManagedUser-AccessRequests";
     57 const char kManagedUserAccessRequestTime[] = "timestamp";
     58 const char kManagedUserName[] = "name";
     59 const char kOpenManagedProfileKeyPrefix[] = "X-ManagedUser-Events-OpenProfile";
     60 const char kQuitBrowserKeyPrefix[] = "X-ManagedUser-Events-QuitBrowser";
     61 const char kSwitchFromManagedProfileKeyPrefix[] =
     62     "X-ManagedUser-Events-SwitchProfile";
     63 const char kEventTimestamp[] = "timestamp";
     64 
     65 ManagedUserService::URLFilterContext::URLFilterContext()
     66     : ui_url_filter_(new ManagedModeURLFilter),
     67       io_url_filter_(new ManagedModeURLFilter) {}
     68 ManagedUserService::URLFilterContext::~URLFilterContext() {}
     69 
     70 ManagedModeURLFilter*
     71 ManagedUserService::URLFilterContext::ui_url_filter() const {
     72   return ui_url_filter_.get();
     73 }
     74 
     75 ManagedModeURLFilter*
     76 ManagedUserService::URLFilterContext::io_url_filter() const {
     77   return io_url_filter_.get();
     78 }
     79 
     80 void ManagedUserService::URLFilterContext::SetDefaultFilteringBehavior(
     81     ManagedModeURLFilter::FilteringBehavior behavior) {
     82   ui_url_filter_->SetDefaultFilteringBehavior(behavior);
     83   BrowserThread::PostTask(
     84       BrowserThread::IO,
     85       FROM_HERE,
     86       base::Bind(&ManagedModeURLFilter::SetDefaultFilteringBehavior,
     87                  io_url_filter_.get(), behavior));
     88 }
     89 
     90 void ManagedUserService::URLFilterContext::LoadWhitelists(
     91     ScopedVector<ManagedModeSiteList> site_lists) {
     92   // ManagedModeURLFilter::LoadWhitelists takes ownership of |site_lists|,
     93   // so we make an additional copy of it.
     94   /// TODO(bauerb): This is kinda ugly.
     95   ScopedVector<ManagedModeSiteList> site_lists_copy;
     96   for (ScopedVector<ManagedModeSiteList>::iterator it = site_lists.begin();
     97        it != site_lists.end(); ++it) {
     98     site_lists_copy.push_back((*it)->Clone());
     99   }
    100   ui_url_filter_->LoadWhitelists(site_lists.Pass());
    101   BrowserThread::PostTask(
    102       BrowserThread::IO,
    103       FROM_HERE,
    104       base::Bind(&ManagedModeURLFilter::LoadWhitelists,
    105                  io_url_filter_, base::Passed(&site_lists_copy)));
    106 }
    107 
    108 void ManagedUserService::URLFilterContext::SetManualHosts(
    109     scoped_ptr<std::map<std::string, bool> > host_map) {
    110   ui_url_filter_->SetManualHosts(host_map.get());
    111   BrowserThread::PostTask(
    112       BrowserThread::IO,
    113       FROM_HERE,
    114       base::Bind(&ManagedModeURLFilter::SetManualHosts,
    115                  io_url_filter_, base::Owned(host_map.release())));
    116 }
    117 
    118 void ManagedUserService::URLFilterContext::SetManualURLs(
    119     scoped_ptr<std::map<GURL, bool> > url_map) {
    120   ui_url_filter_->SetManualURLs(url_map.get());
    121   BrowserThread::PostTask(
    122       BrowserThread::IO,
    123       FROM_HERE,
    124       base::Bind(&ManagedModeURLFilter::SetManualURLs,
    125                  io_url_filter_, base::Owned(url_map.release())));
    126 }
    127 
    128 ManagedUserService::ManagedUserService(Profile* profile)
    129     : profile_(profile),
    130       waiting_for_sync_initialization_(false),
    131       is_profile_active_(false),
    132       elevated_for_testing_(false),
    133       did_shutdown_(false),
    134       weak_ptr_factory_(this) {
    135 }
    136 
    137 ManagedUserService::~ManagedUserService() {
    138   DCHECK(did_shutdown_);
    139 }
    140 
    141 void ManagedUserService::Shutdown() {
    142   did_shutdown_ = true;
    143   if (ProfileIsManaged()) {
    144     RecordProfileAndBrowserEventsHelper(kQuitBrowserKeyPrefix);
    145 #if !defined(OS_ANDROID)
    146     // TODO(bauerb): Get rid of the platform-specific #ifdef here.
    147     // http://crbug.com/313377
    148     BrowserList::RemoveObserver(this);
    149 #endif
    150   }
    151 
    152   if (!waiting_for_sync_initialization_)
    153     return;
    154 
    155   ProfileSyncService* sync_service =
    156         ProfileSyncServiceFactory::GetForProfile(profile_);
    157   sync_service->RemoveObserver(this);
    158 }
    159 
    160 bool ManagedUserService::ProfileIsManaged() const {
    161   return profile_->IsManaged();
    162 }
    163 
    164 // static
    165 void ManagedUserService::RegisterProfilePrefs(
    166     user_prefs::PrefRegistrySyncable* registry) {
    167   registry->RegisterDictionaryPref(
    168       prefs::kManagedModeManualHosts,
    169       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    170   registry->RegisterDictionaryPref(
    171       prefs::kManagedModeManualURLs,
    172       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    173   registry->RegisterIntegerPref(
    174       prefs::kDefaultManagedModeFilteringBehavior, ManagedModeURLFilter::ALLOW,
    175       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    176   registry->RegisterStringPref(
    177       prefs::kManagedUserCustodianEmail, std::string(),
    178       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    179   registry->RegisterStringPref(
    180       prefs::kManagedUserCustodianName, std::string(),
    181       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    182   registry->RegisterBooleanPref(prefs::kManagedUserCreationAllowed, true,
    183       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    184 }
    185 
    186 // static
    187 void ManagedUserService::MigrateUserPrefs(PrefService* prefs) {
    188   if (!prefs->HasPrefPath(prefs::kProfileIsManaged))
    189     return;
    190 
    191   bool is_managed = prefs->GetBoolean(prefs::kProfileIsManaged);
    192   prefs->ClearPref(prefs::kProfileIsManaged);
    193 
    194   if (!is_managed)
    195     return;
    196 
    197   std::string managed_user_id = prefs->GetString(prefs::kManagedUserId);
    198   if (!managed_user_id.empty())
    199     return;
    200 
    201   prefs->SetString(prefs::kManagedUserId, "Dummy ID");
    202 }
    203 
    204 scoped_refptr<const ManagedModeURLFilter>
    205 ManagedUserService::GetURLFilterForIOThread() {
    206   return url_filter_context_.io_url_filter();
    207 }
    208 
    209 ManagedModeURLFilter* ManagedUserService::GetURLFilterForUIThread() {
    210   return url_filter_context_.ui_url_filter();
    211 }
    212 
    213 // Items not on any list must return -1 (CATEGORY_NOT_ON_LIST in history.js).
    214 // Items on a list, but with no category, must return 0 (CATEGORY_OTHER).
    215 #define CATEGORY_NOT_ON_LIST -1;
    216 #define CATEGORY_OTHER 0;
    217 
    218 int ManagedUserService::GetCategory(const GURL& url) {
    219   std::vector<ManagedModeSiteList::Site*> sites;
    220   GetURLFilterForUIThread()->GetSites(url, &sites);
    221   if (sites.empty())
    222     return CATEGORY_NOT_ON_LIST;
    223 
    224   return (*sites.begin())->category_id;
    225 }
    226 
    227 // static
    228 void ManagedUserService::GetCategoryNames(CategoryList* list) {
    229   ManagedModeSiteList::GetCategoryNames(list);
    230 }
    231 
    232 std::string ManagedUserService::GetCustodianEmailAddress() const {
    233 #if defined(OS_CHROMEOS)
    234   return chromeos::UserManager::Get()->GetSupervisedUserManager()->
    235       GetManagerDisplayEmail(
    236           chromeos::UserManager::Get()->GetActiveUser()->email());
    237 #else
    238   return profile_->GetPrefs()->GetString(prefs::kManagedUserCustodianEmail);
    239 #endif
    240 }
    241 
    242 std::string ManagedUserService::GetCustodianName() const {
    243 #if defined(OS_CHROMEOS)
    244   return UTF16ToUTF8(chromeos::UserManager::Get()->GetSupervisedUserManager()->
    245       GetManagerDisplayName(
    246           chromeos::UserManager::Get()->GetActiveUser()->email()));
    247 #else
    248   std::string name = profile_->GetPrefs()->GetString(
    249       prefs::kManagedUserCustodianName);
    250   return name.empty() ? GetCustodianEmailAddress() : name;
    251 #endif
    252 }
    253 
    254 void ManagedUserService::AddNavigationBlockedCallback(
    255     const NavigationBlockedCallback& callback) {
    256   navigation_blocked_callbacks_.push_back(callback);
    257 }
    258 
    259 void ManagedUserService::DidBlockNavigation(
    260     content::WebContents* web_contents) {
    261   for (std::vector<NavigationBlockedCallback>::iterator it =
    262            navigation_blocked_callbacks_.begin();
    263        it != navigation_blocked_callbacks_.end(); ++it) {
    264     it->Run(web_contents);
    265   }
    266 }
    267 
    268 std::string ManagedUserService::GetDebugPolicyProviderName() const {
    269   // Save the string space in official builds.
    270 #ifdef NDEBUG
    271   NOTREACHED();
    272   return std::string();
    273 #else
    274   return "Managed User Service";
    275 #endif
    276 }
    277 
    278 bool ManagedUserService::UserMayLoad(const extensions::Extension* extension,
    279                                      base::string16* error) const {
    280   base::string16 tmp_error;
    281   if (ExtensionManagementPolicyImpl(extension, &tmp_error))
    282     return true;
    283 
    284   // If the extension is already loaded, we allow it, otherwise we'd unload
    285   // all existing extensions.
    286   ExtensionService* extension_service =
    287       extensions::ExtensionSystem::Get(profile_)->extension_service();
    288 
    289   // |extension_service| can be NULL in a unit test.
    290   if (extension_service &&
    291       extension_service->GetInstalledExtension(extension->id()))
    292     return true;
    293 
    294   bool was_installed_by_default = extension->was_installed_by_default();
    295 #if defined(OS_CHROMEOS)
    296   // On Chrome OS all external sources are controlled by us so it means that
    297   // they are "default". Method was_installed_by_default returns false because
    298   // extensions creation flags are ignored in case of default extensions with
    299   // update URL(the flags aren't passed to OnExternalExtensionUpdateUrlFound).
    300   // TODO(dpolukhin): remove this Chrome OS specific code as soon as creation
    301   // flags are not ignored.
    302   was_installed_by_default =
    303       extensions::Manifest::IsExternalLocation(extension->location());
    304 #endif
    305   if (extension->location() == extensions::Manifest::COMPONENT ||
    306       was_installed_by_default) {
    307     return true;
    308   }
    309 
    310   if (error)
    311     *error = tmp_error;
    312   return false;
    313 }
    314 
    315 bool ManagedUserService::UserMayModifySettings(
    316     const extensions::Extension* extension,
    317     base::string16* error) const {
    318   return ExtensionManagementPolicyImpl(extension, error);
    319 }
    320 
    321 void ManagedUserService::OnStateChanged() {
    322   ProfileSyncService* service =
    323       ProfileSyncServiceFactory::GetForProfile(profile_);
    324   if (waiting_for_sync_initialization_ && service->sync_initialized()) {
    325     waiting_for_sync_initialization_ = false;
    326     service->RemoveObserver(this);
    327     SetupSync();
    328     return;
    329   }
    330 
    331   DLOG_IF(ERROR, service->GetAuthError().state() ==
    332                      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)
    333       << "Credentials rejected";
    334 }
    335 
    336 void ManagedUserService::Observe(int type,
    337                           const content::NotificationSource& source,
    338                           const content::NotificationDetails& details) {
    339   switch (type) {
    340     case chrome::NOTIFICATION_EXTENSION_LOADED: {
    341       const extensions::Extension* extension =
    342           content::Details<extensions::Extension>(details).ptr();
    343       if (!extensions::ManagedModeInfo::GetContentPackSiteList(
    344               extension).empty()) {
    345         UpdateSiteLists();
    346       }
    347       break;
    348     }
    349     case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
    350       const extensions::UnloadedExtensionInfo* extension_info =
    351           content::Details<extensions::UnloadedExtensionInfo>(details).ptr();
    352       if (!extensions::ManagedModeInfo::GetContentPackSiteList(
    353               extension_info->extension).empty()) {
    354         UpdateSiteLists();
    355       }
    356       break;
    357     }
    358     default:
    359       NOTREACHED();
    360   }
    361 }
    362 
    363 void ManagedUserService::SetupSync() {
    364   ProfileSyncService* service =
    365       ProfileSyncServiceFactory::GetForProfile(profile_);
    366   DCHECK(service->sync_initialized());
    367 
    368   bool sync_everything = false;
    369   syncer::ModelTypeSet synced_datatypes;
    370   synced_datatypes.Put(syncer::MANAGED_USER_SETTINGS);
    371   service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
    372 
    373   // Notify ProfileSyncService that we are done with configuration.
    374   service->SetSetupInProgress(false);
    375   service->SetSyncSetupCompleted();
    376 }
    377 
    378 bool ManagedUserService::ExtensionManagementPolicyImpl(
    379     const extensions::Extension* extension,
    380     base::string16* error) const {
    381   // |extension| can be NULL in unit_tests.
    382   if (!ProfileIsManaged() || (extension && extension->is_theme()))
    383     return true;
    384 
    385   if (elevated_for_testing_)
    386     return true;
    387 
    388   if (error)
    389     *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_USER);
    390   return false;
    391 }
    392 
    393 ScopedVector<ManagedModeSiteList> ManagedUserService::GetActiveSiteLists() {
    394   ScopedVector<ManagedModeSiteList> site_lists;
    395   ExtensionService* extension_service =
    396       extensions::ExtensionSystem::Get(profile_)->extension_service();
    397   // Can be NULL in unit tests.
    398   if (!extension_service)
    399     return site_lists.Pass();
    400 
    401   const ExtensionSet* extensions = extension_service->extensions();
    402   for (ExtensionSet::const_iterator it = extensions->begin();
    403        it != extensions->end(); ++it) {
    404     const extensions::Extension* extension = it->get();
    405     if (!extension_service->IsExtensionEnabled(extension->id()))
    406       continue;
    407 
    408     extensions::ExtensionResource site_list =
    409         extensions::ManagedModeInfo::GetContentPackSiteList(extension);
    410     if (!site_list.empty()) {
    411       site_lists.push_back(new ManagedModeSiteList(extension->id(),
    412                                                    site_list.GetFilePath()));
    413     }
    414   }
    415 
    416   return site_lists.Pass();
    417 }
    418 
    419 ManagedUserSettingsService* ManagedUserService::GetSettingsService() {
    420   return ManagedUserSettingsServiceFactory::GetForProfile(profile_);
    421 }
    422 
    423 void ManagedUserService::OnDefaultFilteringBehaviorChanged() {
    424   DCHECK(ProfileIsManaged());
    425 
    426   int behavior_value = profile_->GetPrefs()->GetInteger(
    427       prefs::kDefaultManagedModeFilteringBehavior);
    428   ManagedModeURLFilter::FilteringBehavior behavior =
    429       ManagedModeURLFilter::BehaviorFromInt(behavior_value);
    430   url_filter_context_.SetDefaultFilteringBehavior(behavior);
    431 }
    432 
    433 void ManagedUserService::UpdateSiteLists() {
    434   url_filter_context_.LoadWhitelists(GetActiveSiteLists());
    435 }
    436 
    437 bool ManagedUserService::AccessRequestsEnabled() {
    438   ProfileSyncService* service =
    439       ProfileSyncServiceFactory::GetForProfile(profile_);
    440   GoogleServiceAuthError::State state = service->GetAuthError().state();
    441   // We allow requesting access if Sync is working or has a transient error.
    442   return (state == GoogleServiceAuthError::NONE ||
    443           state == GoogleServiceAuthError::CONNECTION_FAILED ||
    444           state == GoogleServiceAuthError::SERVICE_UNAVAILABLE);
    445 }
    446 
    447 void ManagedUserService::AddAccessRequest(const GURL& url) {
    448   // Normalize the URL.
    449   GURL normalized_url = ManagedModeURLFilter::Normalize(url);
    450 
    451   // Escape the URL.
    452   std::string output(net::EscapeQueryParamValue(normalized_url.spec(), true));
    453 
    454   // Add the prefix.
    455   std::string key = ManagedUserSettingsService::MakeSplitSettingKey(
    456       kManagedUserAccessRequestKeyPrefix, output);
    457 
    458   scoped_ptr<DictionaryValue> dict(new DictionaryValue);
    459 
    460   // TODO(sergiu): Use sane time here when it's ready.
    461   dict->SetDouble(kManagedUserAccessRequestTime, base::Time::Now().ToJsTime());
    462 
    463   dict->SetString(kManagedUserName, profile_->GetProfileName());
    464 
    465   GetSettingsService()->UploadItem(key, dict.PassAs<Value>());
    466 }
    467 
    468 ManagedUserService::ManualBehavior ManagedUserService::GetManualBehaviorForHost(
    469     const std::string& hostname) {
    470   const DictionaryValue* dict =
    471       profile_->GetPrefs()->GetDictionary(prefs::kManagedModeManualHosts);
    472   bool allow = false;
    473   if (!dict->GetBooleanWithoutPathExpansion(hostname, &allow))
    474     return MANUAL_NONE;
    475 
    476   return allow ? MANUAL_ALLOW : MANUAL_BLOCK;
    477 }
    478 
    479 ManagedUserService::ManualBehavior ManagedUserService::GetManualBehaviorForURL(
    480     const GURL& url) {
    481   const DictionaryValue* dict =
    482       profile_->GetPrefs()->GetDictionary(prefs::kManagedModeManualURLs);
    483   GURL normalized_url = ManagedModeURLFilter::Normalize(url);
    484   bool allow = false;
    485   if (!dict->GetBooleanWithoutPathExpansion(normalized_url.spec(), &allow))
    486     return MANUAL_NONE;
    487 
    488   return allow ? MANUAL_ALLOW : MANUAL_BLOCK;
    489 }
    490 
    491 void ManagedUserService::GetManualExceptionsForHost(const std::string& host,
    492                                                     std::vector<GURL>* urls) {
    493   const DictionaryValue* dict =
    494       profile_->GetPrefs()->GetDictionary(prefs::kManagedModeManualURLs);
    495   for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
    496     GURL url(it.key());
    497     if (url.host() == host)
    498       urls->push_back(url);
    499   }
    500 }
    501 
    502 void ManagedUserService::InitSync(const std::string& refresh_token) {
    503   ProfileSyncService* service =
    504       ProfileSyncServiceFactory::GetForProfile(profile_);
    505   // Tell the sync service that setup is in progress so we don't start syncing
    506   // until we've finished configuration.
    507   service->SetSetupInProgress(true);
    508 
    509   ProfileOAuth2TokenService* token_service =
    510       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
    511   token_service->UpdateCredentials(managed_users::kManagedUserPseudoEmail,
    512                                    refresh_token);
    513 
    514   // Continue in SetupSync() once the Sync backend has been initialized.
    515   if (service->sync_initialized()) {
    516     SetupSync();
    517   } else {
    518     ProfileSyncServiceFactory::GetForProfile(profile_)->AddObserver(this);
    519     waiting_for_sync_initialization_ = true;
    520   }
    521 }
    522 
    523 void ManagedUserService::Init() {
    524   ManagedUserSettingsService* settings_service = GetSettingsService();
    525   DCHECK(settings_service->IsReady());
    526   if (!ProfileIsManaged()) {
    527     settings_service->Clear();
    528     return;
    529   }
    530 
    531   settings_service->Activate();
    532 
    533   CommandLine* command_line = CommandLine::ForCurrentProcess();
    534   if (command_line->HasSwitch(switches::kManagedUserSyncToken)) {
    535     InitSync(
    536         command_line->GetSwitchValueASCII(switches::kManagedUserSyncToken));
    537   }
    538 
    539   // TODO(rogerta): Remove this once PO2TS has replaced TokenService.
    540   ProfileOAuth2TokenService* token_service =
    541       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
    542   token_service->LoadCredentials();
    543 
    544   extensions::ExtensionSystem* extension_system =
    545       extensions::ExtensionSystem::Get(profile_);
    546   extensions::ManagementPolicy* management_policy =
    547       extension_system->management_policy();
    548   if (management_policy)
    549     extension_system->management_policy()->RegisterProvider(this);
    550 
    551   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
    552                  content::Source<Profile>(profile_));
    553   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
    554                  content::Source<Profile>(profile_));
    555 
    556   pref_change_registrar_.Init(profile_->GetPrefs());
    557   pref_change_registrar_.Add(
    558       prefs::kDefaultManagedModeFilteringBehavior,
    559       base::Bind(&ManagedUserService::OnDefaultFilteringBehaviorChanged,
    560           base::Unretained(this)));
    561   pref_change_registrar_.Add(prefs::kManagedModeManualHosts,
    562       base::Bind(&ManagedUserService::UpdateManualHosts,
    563                  base::Unretained(this)));
    564   pref_change_registrar_.Add(prefs::kManagedModeManualURLs,
    565       base::Bind(&ManagedUserService::UpdateManualURLs,
    566                  base::Unretained(this)));
    567 
    568 #if !defined(OS_ANDROID)
    569   // TODO(bauerb): Get rid of the platform-specific #ifdef here.
    570   // http://crbug.com/313377
    571   BrowserList::AddObserver(this);
    572 #endif
    573 
    574   // Initialize the filter.
    575   OnDefaultFilteringBehaviorChanged();
    576   UpdateSiteLists();
    577   UpdateManualHosts();
    578   UpdateManualURLs();
    579 }
    580 
    581 void ManagedUserService::RegisterAndInitSync(
    582     ManagedUserRegistrationUtility* registration_utility,
    583     Profile* custodian_profile,
    584     const std::string& managed_user_id,
    585     const AuthErrorCallback& callback) {
    586   DCHECK(ProfileIsManaged());
    587   DCHECK(!custodian_profile->IsManaged());
    588 
    589   base::string16 name = UTF8ToUTF16(
    590       profile_->GetPrefs()->GetString(prefs::kProfileName));
    591   int avatar_index = profile_->GetPrefs()->GetInteger(
    592       prefs::kProfileAvatarIndex);
    593   ManagedUserRegistrationInfo info(name, avatar_index);
    594   registration_utility->Register(
    595       managed_user_id,
    596       info,
    597       base::Bind(&ManagedUserService::OnManagedUserRegistered,
    598                  weak_ptr_factory_.GetWeakPtr(), callback, custodian_profile));
    599 
    600   // Fetch the custodian's profile information, to store the name.
    601   // TODO(pamg): If --google-profile-info (flag: switches::kGoogleProfileInfo)
    602   // is ever enabled, take the name from the ProfileInfoCache instead.
    603   CustodianProfileDownloaderService* profile_downloader_service =
    604       CustodianProfileDownloaderServiceFactory::GetForProfile(
    605           custodian_profile);
    606   profile_downloader_service->DownloadProfile(
    607       base::Bind(&ManagedUserService::OnCustodianProfileDownloaded,
    608                  weak_ptr_factory_.GetWeakPtr()));
    609 }
    610 
    611 void ManagedUserService::OnCustodianProfileDownloaded(
    612     const base::string16& full_name) {
    613   profile_->GetPrefs()->SetString(prefs::kManagedUserCustodianName,
    614                                   UTF16ToUTF8(full_name));
    615 }
    616 
    617 void ManagedUserService::OnManagedUserRegistered(
    618     const AuthErrorCallback& callback,
    619     Profile* custodian_profile,
    620     const GoogleServiceAuthError& auth_error,
    621     const std::string& token) {
    622   if (auth_error.state() == GoogleServiceAuthError::NONE) {
    623     InitSync(token);
    624     SigninManagerBase* signin =
    625         SigninManagerFactory::GetForProfile(custodian_profile);
    626     profile_->GetPrefs()->SetString(prefs::kManagedUserCustodianEmail,
    627                                     signin->GetAuthenticatedUsername());
    628   } else {
    629     DCHECK_EQ(std::string(), token);
    630   }
    631 
    632   callback.Run(auth_error);
    633 }
    634 
    635 void ManagedUserService::UpdateManualHosts() {
    636   const DictionaryValue* dict =
    637       profile_->GetPrefs()->GetDictionary(prefs::kManagedModeManualHosts);
    638   scoped_ptr<std::map<std::string, bool> > host_map(
    639       new std::map<std::string, bool>());
    640   for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
    641     bool allow = false;
    642     bool result = it.value().GetAsBoolean(&allow);
    643     DCHECK(result);
    644     (*host_map)[it.key()] = allow;
    645   }
    646   url_filter_context_.SetManualHosts(host_map.Pass());
    647 }
    648 
    649 void ManagedUserService::UpdateManualURLs() {
    650   const DictionaryValue* dict =
    651       profile_->GetPrefs()->GetDictionary(prefs::kManagedModeManualURLs);
    652   scoped_ptr<std::map<GURL, bool> > url_map(new std::map<GURL, bool>());
    653   for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
    654     bool allow = false;
    655     bool result = it.value().GetAsBoolean(&allow);
    656     DCHECK(result);
    657     (*url_map)[GURL(it.key())] = allow;
    658   }
    659   url_filter_context_.SetManualURLs(url_map.Pass());
    660 }
    661 
    662 void ManagedUserService::OnBrowserSetLastActive(Browser* browser) {
    663   bool profile_became_active = profile_->IsSameProfile(browser->profile());
    664   if (!is_profile_active_ && profile_became_active)
    665     RecordProfileAndBrowserEventsHelper(kOpenManagedProfileKeyPrefix);
    666   else if (is_profile_active_ && !profile_became_active)
    667     RecordProfileAndBrowserEventsHelper(kSwitchFromManagedProfileKeyPrefix);
    668 
    669   is_profile_active_ = profile_became_active;
    670 }
    671 
    672 void ManagedUserService::RecordProfileAndBrowserEventsHelper(
    673     const char* key_prefix) {
    674   std::string key = ManagedUserSettingsService::MakeSplitSettingKey(
    675       key_prefix,
    676       base::Int64ToString(base::TimeTicks::Now().ToInternalValue()));
    677 
    678   scoped_ptr<DictionaryValue> dict(new DictionaryValue);
    679 
    680   // TODO(bauerb): Use sane time when ready.
    681   dict->SetDouble(kEventTimestamp, base::Time::Now().ToJsTime());
    682 
    683   GetSettingsService()->UploadItem(key, dict.PassAs<Value>());
    684 }
    685