supervised_user_registration_utility.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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_registration_utility.h" 6 7#include "base/base64.h" 8#include "base/bind.h" 9#include "base/command_line.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/prefs/pref_service.h" 12#include "base/rand_util.h" 13#include "base/strings/utf_string_conversions.h" 14#include "chrome/browser/profiles/profile.h" 15#include "chrome/browser/signin/chrome_signin_client_factory.h" 16#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 17#include "chrome/browser/signin/signin_manager_factory.h" 18#include "chrome/browser/supervised_user/supervised_user_constants.h" 19#include "chrome/browser/supervised_user/supervised_user_refresh_token_fetcher.h" 20#include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h" 21#include "chrome/browser/supervised_user/supervised_user_shared_settings_service_factory.h" 22#include "chrome/browser/supervised_user/supervised_user_shared_settings_update.h" 23#include "chrome/browser/supervised_user/supervised_user_sync_service.h" 24#include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h" 25#include "chrome/common/chrome_switches.h" 26#include "chrome/common/pref_names.h" 27#include "components/signin/core/browser/profile_oauth2_token_service.h" 28#include "components/signin/core/browser/signin_client.h" 29#include "components/signin/core/browser/signin_manager.h" 30#include "content/public/browser/browser_thread.h" 31#include "google_apis/gaia/gaia_urls.h" 32#include "google_apis/gaia/google_service_auth_error.h" 33#include "sync/util/get_session_name.h" 34 35using base::DictionaryValue; 36 37namespace { 38 39SupervisedUserRegistrationUtility* g_instance_for_tests = NULL; 40 41// Actual implementation of SupervisedUserRegistrationUtility. 42class SupervisedUserRegistrationUtilityImpl 43 : public SupervisedUserRegistrationUtility, 44 public SupervisedUserSyncServiceObserver { 45 public: 46 SupervisedUserRegistrationUtilityImpl( 47 PrefService* prefs, 48 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher, 49 SupervisedUserSyncService* service, 50 SupervisedUserSharedSettingsService* shared_settings_service); 51 52 virtual ~SupervisedUserRegistrationUtilityImpl(); 53 54 // Registers a new supervised user with the server. |supervised_user_id| is a 55 // new unique ID for the new supervised user. If its value is the same as that 56 // of one of the existing supervised users, then the same user will be created 57 // on this machine (and if he has no avatar in sync, his avatar will be 58 // updated). |info| contains necessary information like the display name of 59 // the user and his avatar. |callback| is called with the result of the 60 // registration. We use the info here and not the profile, because on Chrome 61 // OS the profile of the supervised user does not yet exist. 62 virtual void Register(const std::string& supervised_user_id, 63 const SupervisedUserRegistrationInfo& info, 64 const RegistrationCallback& callback) OVERRIDE; 65 66 // SupervisedUserSyncServiceObserver: 67 virtual void OnSupervisedUserAcknowledged( 68 const std::string& supervised_user_id) OVERRIDE; 69 virtual void OnSupervisedUsersSyncingStopped() OVERRIDE; 70 virtual void OnSupervisedUsersChanged() OVERRIDE; 71 72 private: 73 // Fetches the supervised user token when we have the device name. 74 void FetchToken(const std::string& client_name); 75 76 // Called when we have received a token for the supervised user. 77 void OnReceivedToken(const GoogleServiceAuthError& error, 78 const std::string& token); 79 80 // Dispatches the callback and cleans up if all the conditions have been met. 81 void CompleteRegistrationIfReady(); 82 83 // Aborts any registration currently in progress. If |run_callback| is true, 84 // calls the callback specified in Register() with the given |error|. 85 void AbortPendingRegistration(bool run_callback, 86 const GoogleServiceAuthError& error); 87 88 // If |run_callback| is true, dispatches the callback with the saved token 89 // (which may be empty) and the given |error|. In any case, resets internal 90 // variables to be ready for the next registration. 91 void CompleteRegistration(bool run_callback, 92 const GoogleServiceAuthError& error); 93 94 // Cancels any registration currently in progress, without calling the 95 // callback or reporting an error. 96 void CancelPendingRegistration(); 97 98 // SupervisedUserSharedSettingsUpdate acknowledgment callback for password 99 // data in shared settings. 100 void OnPasswordChangeAcknowledged(bool success); 101 102 PrefService* prefs_; 103 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher_; 104 105 // A |KeyedService| owned by the custodian profile. 106 SupervisedUserSyncService* supervised_user_sync_service_; 107 108 // A |KeyedService| owned by the custodian profile. 109 SupervisedUserSharedSettingsService* supervised_user_shared_settings_service_; 110 111 std::string pending_supervised_user_id_; 112 std::string pending_supervised_user_token_; 113 bool pending_supervised_user_acknowledged_; 114 bool is_existing_supervised_user_; 115 bool avatar_updated_; 116 RegistrationCallback callback_; 117 scoped_ptr<SupervisedUserSharedSettingsUpdate> password_update_; 118 119 base::WeakPtrFactory<SupervisedUserRegistrationUtilityImpl> weak_ptr_factory_; 120 121 DISALLOW_COPY_AND_ASSIGN(SupervisedUserRegistrationUtilityImpl); 122}; 123 124} // namespace 125 126SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo( 127 const base::string16& name, 128 int avatar_index) 129 : avatar_index(avatar_index), 130 name(name) { 131} 132 133SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {} 134 135ScopedTestingSupervisedUserRegistrationUtility:: 136 ScopedTestingSupervisedUserRegistrationUtility( 137 SupervisedUserRegistrationUtility* instance) { 138 SupervisedUserRegistrationUtility::SetUtilityForTests(instance); 139} 140 141ScopedTestingSupervisedUserRegistrationUtility:: 142 ~ScopedTestingSupervisedUserRegistrationUtility() { 143 SupervisedUserRegistrationUtility::SetUtilityForTests(NULL); 144} 145 146// static 147scoped_ptr<SupervisedUserRegistrationUtility> 148SupervisedUserRegistrationUtility::Create(Profile* profile) { 149 if (g_instance_for_tests) { 150 SupervisedUserRegistrationUtility* result = g_instance_for_tests; 151 g_instance_for_tests = NULL; 152 return make_scoped_ptr(result); 153 } 154 155 ProfileOAuth2TokenService* token_service = 156 ProfileOAuth2TokenServiceFactory::GetForProfile(profile); 157 SigninManagerBase* signin_manager = 158 SigninManagerFactory::GetForProfile(profile); 159 SigninClient* signin_client = 160 ChromeSigninClientFactory::GetForProfile(profile); 161 std::string signin_scoped_device_id = 162 signin_client->GetSigninScopedDeviceId(); 163 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher = 164 SupervisedUserRefreshTokenFetcher::Create( 165 token_service, 166 signin_manager->GetAuthenticatedAccountId(), 167 signin_scoped_device_id, 168 profile->GetRequestContext()); 169 SupervisedUserSyncService* supervised_user_sync_service = 170 SupervisedUserSyncServiceFactory::GetForProfile(profile); 171 SupervisedUserSharedSettingsService* supervised_user_shared_settings_service = 172 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(profile); 173 return make_scoped_ptr(SupervisedUserRegistrationUtility::CreateImpl( 174 profile->GetPrefs(), 175 token_fetcher.Pass(), 176 supervised_user_sync_service, 177 supervised_user_shared_settings_service)); 178} 179 180// static 181std::string SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId() { 182 std::string new_supervised_user_id; 183 base::Base64Encode(base::RandBytesAsString(8), &new_supervised_user_id); 184 return new_supervised_user_id; 185} 186 187// static 188void SupervisedUserRegistrationUtility::SetUtilityForTests( 189 SupervisedUserRegistrationUtility* utility) { 190 if (g_instance_for_tests) 191 delete g_instance_for_tests; 192 g_instance_for_tests = utility; 193} 194 195// static 196SupervisedUserRegistrationUtility* 197SupervisedUserRegistrationUtility::CreateImpl( 198 PrefService* prefs, 199 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher, 200 SupervisedUserSyncService* service, 201 SupervisedUserSharedSettingsService* shared_settings_service) { 202 return new SupervisedUserRegistrationUtilityImpl(prefs, 203 token_fetcher.Pass(), 204 service, 205 shared_settings_service); 206} 207 208namespace { 209 210SupervisedUserRegistrationUtilityImpl::SupervisedUserRegistrationUtilityImpl( 211 PrefService* prefs, 212 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher, 213 SupervisedUserSyncService* service, 214 SupervisedUserSharedSettingsService* shared_settings_service) 215 : prefs_(prefs), 216 token_fetcher_(token_fetcher.Pass()), 217 supervised_user_sync_service_(service), 218 supervised_user_shared_settings_service_(shared_settings_service), 219 pending_supervised_user_acknowledged_(false), 220 is_existing_supervised_user_(false), 221 avatar_updated_(false), 222 weak_ptr_factory_(this) { 223 supervised_user_sync_service_->AddObserver(this); 224} 225 226SupervisedUserRegistrationUtilityImpl:: 227~SupervisedUserRegistrationUtilityImpl() { 228 supervised_user_sync_service_->RemoveObserver(this); 229 CancelPendingRegistration(); 230} 231 232void SupervisedUserRegistrationUtilityImpl::Register( 233 const std::string& supervised_user_id, 234 const SupervisedUserRegistrationInfo& info, 235 const RegistrationCallback& callback) { 236 DCHECK(pending_supervised_user_id_.empty()); 237 callback_ = callback; 238 pending_supervised_user_id_ = supervised_user_id; 239 240 bool need_password_update = !info.password_data.empty(); 241 const base::DictionaryValue* dict = 242 prefs_->GetDictionary(prefs::kSupervisedUsers); 243 is_existing_supervised_user_ = dict->HasKey(supervised_user_id); 244 if (!is_existing_supervised_user_) { 245 supervised_user_sync_service_->AddSupervisedUser( 246 pending_supervised_user_id_, 247 base::UTF16ToUTF8(info.name), 248 info.master_key, 249 info.password_signature_key, 250 info.password_encryption_key, 251 info.avatar_index); 252 } else { 253 const base::DictionaryValue* value = NULL; 254 bool success = 255 dict->GetDictionaryWithoutPathExpansion(supervised_user_id, &value); 256 DCHECK(success); 257 std::string key; 258 bool need_keys = !info.password_signature_key.empty() || 259 !info.password_encryption_key.empty(); 260 bool have_keys = 261 value->GetString(SupervisedUserSyncService::kPasswordSignatureKey, 262 &key) && 263 !key.empty() && 264 value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey, 265 &key) && 266 !key.empty(); 267 268 bool keys_need_update = need_keys && !have_keys; 269 270 if (keys_need_update) { 271 supervised_user_sync_service_->UpdateSupervisedUser( 272 pending_supervised_user_id_, 273 base::UTF16ToUTF8(info.name), 274 info.master_key, 275 info.password_signature_key, 276 info.password_encryption_key, 277 info.avatar_index); 278 } else { 279 // The user already exists and does not need to be updated. 280 need_password_update = false; 281 OnSupervisedUserAcknowledged(supervised_user_id); 282 } 283 avatar_updated_ = 284 supervised_user_sync_service_->UpdateSupervisedUserAvatarIfNeeded( 285 supervised_user_id, 286 info.avatar_index); 287 } 288#if defined(OS_CHROMEOS) 289 const char* kAvatarKey = supervised_users::kChromeOSAvatarIndex; 290#else 291 const char* kAvatarKey = supervised_users::kChromeAvatarIndex; 292#endif 293 supervised_user_shared_settings_service_->SetValue( 294 pending_supervised_user_id_, kAvatarKey, 295 base::FundamentalValue(info.avatar_index)); 296 if (need_password_update) { 297 password_update_.reset(new SupervisedUserSharedSettingsUpdate( 298 supervised_user_shared_settings_service_, 299 pending_supervised_user_id_, 300 supervised_users::kChromeOSPasswordData, 301 scoped_ptr<base::Value>(info.password_data.DeepCopy()), 302 base::Bind( 303 &SupervisedUserRegistrationUtilityImpl:: 304 OnPasswordChangeAcknowledged, 305 weak_ptr_factory_.GetWeakPtr()))); 306 } 307 308 syncer::GetSessionName( 309 content::BrowserThread::GetBlockingPool(), 310 base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken, 311 weak_ptr_factory_.GetWeakPtr())); 312} 313 314void SupervisedUserRegistrationUtilityImpl::CancelPendingRegistration() { 315 AbortPendingRegistration( 316 false, // Don't run the callback. The error will be ignored. 317 GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 318} 319 320void SupervisedUserRegistrationUtilityImpl::OnSupervisedUserAcknowledged( 321 const std::string& supervised_user_id) { 322 DCHECK_EQ(pending_supervised_user_id_, supervised_user_id); 323 DCHECK(!pending_supervised_user_acknowledged_); 324 pending_supervised_user_acknowledged_ = true; 325 CompleteRegistrationIfReady(); 326} 327 328void SupervisedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged( 329 bool success) { 330 DCHECK(password_update_); 331 DCHECK(success); 332 password_update_.reset(); 333 CompleteRegistrationIfReady(); 334} 335 336void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersSyncingStopped() { 337 AbortPendingRegistration( 338 true, // Run the callback. 339 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED)); 340} 341 342void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersChanged() {} 343 344void SupervisedUserRegistrationUtilityImpl::FetchToken( 345 const std::string& client_name) { 346 token_fetcher_->Start( 347 pending_supervised_user_id_, client_name, 348 base::Bind(&SupervisedUserRegistrationUtilityImpl::OnReceivedToken, 349 weak_ptr_factory_.GetWeakPtr())); 350} 351 352void SupervisedUserRegistrationUtilityImpl::OnReceivedToken( 353 const GoogleServiceAuthError& error, 354 const std::string& token) { 355 if (error.state() != GoogleServiceAuthError::NONE) { 356 CompleteRegistration(true, error); 357 return; 358 } 359 360 DCHECK(!token.empty()); 361 pending_supervised_user_token_ = token; 362 CompleteRegistrationIfReady(); 363} 364 365void SupervisedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() { 366 bool skip_check = CommandLine::ForCurrentProcess()->HasSwitch( 367 switches::kNoSupervisedUserAcknowledgmentCheck); 368 369 if (!pending_supervised_user_acknowledged_ && !skip_check) 370 return; 371 if (password_update_ && !skip_check) 372 return; 373 if (pending_supervised_user_token_.empty()) 374 return; 375 376 GoogleServiceAuthError error(GoogleServiceAuthError::NONE); 377 CompleteRegistration(true, error); 378} 379 380void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration( 381 bool run_callback, 382 const GoogleServiceAuthError& error) { 383 pending_supervised_user_token_.clear(); 384 CompleteRegistration(run_callback, error); 385} 386 387void SupervisedUserRegistrationUtilityImpl::CompleteRegistration( 388 bool run_callback, 389 const GoogleServiceAuthError& error) { 390 if (callback_.is_null()) 391 return; 392 393 if (pending_supervised_user_token_.empty()) { 394 DCHECK(!pending_supervised_user_id_.empty()); 395 396 if (!is_existing_supervised_user_) { 397 // Remove the pending supervised user if we weren't successful. 398 // However, check that we are not importing a supervised user 399 // before deleting it from sync to avoid accidental deletion of 400 // existing supervised users by just canceling the registration for 401 // example. 402 supervised_user_sync_service_->DeleteSupervisedUser( 403 pending_supervised_user_id_); 404 } else if (avatar_updated_) { 405 // Canceling (or failing) a supervised user import that did set the avatar 406 // should undo this change. 407 supervised_user_sync_service_->ClearSupervisedUserAvatar( 408 pending_supervised_user_id_); 409 } 410 } 411 412 if (run_callback) 413 callback_.Run(error, pending_supervised_user_token_); 414 callback_.Reset(); 415} 416 417} // namespace 418