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