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