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