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