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.
5 #include "chrome/browser/supervised_user/supervised_user_registration_utility.h"
7 #include "base/base64.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/browser/sync/glue/device_info.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/pref_names.h"
28 #include "components/signin/core/browser/profile_oauth2_token_service.h"
29 #include "components/signin/core/browser/signin_client.h"
30 #include "components/signin/core/browser/signin_manager.h"
31 #include "google_apis/gaia/gaia_urls.h"
32 #include "google_apis/gaia/google_service_auth_error.h"
34 using base::DictionaryValue;
38 SupervisedUserRegistrationUtility* g_instance_for_tests = NULL;
40 // Actual implementation of SupervisedUserRegistrationUtility.
41 class SupervisedUserRegistrationUtilityImpl
42 : public SupervisedUserRegistrationUtility,
43 public SupervisedUserSyncServiceObserver {
45 SupervisedUserRegistrationUtilityImpl(
47 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
48 SupervisedUserSyncService* service,
49 SupervisedUserSharedSettingsService* shared_settings_service);
51 virtual ~SupervisedUserRegistrationUtilityImpl();
53 // Registers a new supervised user with the server. |supervised_user_id| is a
54 // new unique ID for the new supervised user. If its value is the same as that
55 // of one of the existing supervised users, then the same user will be created
56 // on this machine (and if he has no avatar in sync, his avatar will be
57 // updated). |info| contains necessary information like the display name of
58 // the user and his avatar. |callback| is called with the result of the
59 // registration. We use the info here and not the profile, because on Chrome
60 // OS the profile of the supervised user does not yet exist.
61 virtual void Register(const std::string& supervised_user_id,
62 const SupervisedUserRegistrationInfo& info,
63 const RegistrationCallback& callback) OVERRIDE;
65 // SupervisedUserSyncServiceObserver:
66 virtual void OnSupervisedUserAcknowledged(
67 const std::string& supervised_user_id) OVERRIDE;
68 virtual void OnSupervisedUsersSyncingStopped() OVERRIDE;
69 virtual void OnSupervisedUsersChanged() OVERRIDE;
72 // Fetches the supervised user token when we have the device name.
73 void FetchToken(const std::string& client_name);
75 // Called when we have received a token for the supervised user.
76 void OnReceivedToken(const GoogleServiceAuthError& error,
77 const std::string& token);
79 // Dispatches the callback and cleans up if all the conditions have been met.
80 void CompleteRegistrationIfReady();
82 // Aborts any registration currently in progress. If |run_callback| is true,
83 // calls the callback specified in Register() with the given |error|.
84 void AbortPendingRegistration(bool run_callback,
85 const GoogleServiceAuthError& error);
87 // If |run_callback| is true, dispatches the callback with the saved token
88 // (which may be empty) and the given |error|. In any case, resets internal
89 // variables to be ready for the next registration.
90 void CompleteRegistration(bool run_callback,
91 const GoogleServiceAuthError& error);
93 // Cancels any registration currently in progress, without calling the
94 // callback or reporting an error.
95 void CancelPendingRegistration();
97 // SupervisedUserSharedSettingsUpdate acknowledgment callback for password
98 // data in shared settings.
99 void OnPasswordChangeAcknowledged(bool success);
102 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher_;
104 // A |KeyedService| owned by the custodian profile.
105 SupervisedUserSyncService* supervised_user_sync_service_;
107 // A |KeyedService| owned by the custodian profile.
108 SupervisedUserSharedSettingsService* supervised_user_shared_settings_service_;
110 std::string pending_supervised_user_id_;
111 std::string pending_supervised_user_token_;
112 bool pending_supervised_user_acknowledged_;
113 bool is_existing_supervised_user_;
114 bool avatar_updated_;
115 RegistrationCallback callback_;
116 scoped_ptr<SupervisedUserSharedSettingsUpdate> password_update_;
118 base::WeakPtrFactory<SupervisedUserRegistrationUtilityImpl> weak_ptr_factory_;
120 DISALLOW_COPY_AND_ASSIGN(SupervisedUserRegistrationUtilityImpl);
125 SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo(
126 const base::string16& name,
128 : avatar_index(avatar_index),
132 SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {}
134 ScopedTestingSupervisedUserRegistrationUtility::
135 ScopedTestingSupervisedUserRegistrationUtility(
136 SupervisedUserRegistrationUtility* instance) {
137 SupervisedUserRegistrationUtility::SetUtilityForTests(instance);
140 ScopedTestingSupervisedUserRegistrationUtility::
141 ~ScopedTestingSupervisedUserRegistrationUtility() {
142 SupervisedUserRegistrationUtility::SetUtilityForTests(NULL);
146 scoped_ptr<SupervisedUserRegistrationUtility>
147 SupervisedUserRegistrationUtility::Create(Profile* profile) {
148 if (g_instance_for_tests) {
149 SupervisedUserRegistrationUtility* result = g_instance_for_tests;
150 g_instance_for_tests = NULL;
151 return make_scoped_ptr(result);
154 ProfileOAuth2TokenService* token_service =
155 ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
156 SigninManagerBase* signin_manager =
157 SigninManagerFactory::GetForProfile(profile);
158 SigninClient* signin_client =
159 ChromeSigninClientFactory::GetForProfile(profile);
160 std::string signin_scoped_device_id =
161 signin_client->GetSigninScopedDeviceId();
162 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher =
163 SupervisedUserRefreshTokenFetcher::Create(
165 signin_manager->GetAuthenticatedAccountId(),
166 signin_scoped_device_id,
167 profile->GetRequestContext());
168 SupervisedUserSyncService* supervised_user_sync_service =
169 SupervisedUserSyncServiceFactory::GetForProfile(profile);
170 SupervisedUserSharedSettingsService* supervised_user_shared_settings_service =
171 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(profile);
172 return make_scoped_ptr(SupervisedUserRegistrationUtility::CreateImpl(
174 token_fetcher.Pass(),
175 supervised_user_sync_service,
176 supervised_user_shared_settings_service));
180 std::string SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId() {
181 std::string new_supervised_user_id;
182 base::Base64Encode(base::RandBytesAsString(8), &new_supervised_user_id);
183 return new_supervised_user_id;
187 void SupervisedUserRegistrationUtility::SetUtilityForTests(
188 SupervisedUserRegistrationUtility* utility) {
189 if (g_instance_for_tests)
190 delete g_instance_for_tests;
191 g_instance_for_tests = utility;
195 SupervisedUserRegistrationUtility*
196 SupervisedUserRegistrationUtility::CreateImpl(
198 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
199 SupervisedUserSyncService* service,
200 SupervisedUserSharedSettingsService* shared_settings_service) {
201 return new SupervisedUserRegistrationUtilityImpl(prefs,
202 token_fetcher.Pass(),
204 shared_settings_service);
209 SupervisedUserRegistrationUtilityImpl::SupervisedUserRegistrationUtilityImpl(
211 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
212 SupervisedUserSyncService* service,
213 SupervisedUserSharedSettingsService* shared_settings_service)
215 token_fetcher_(token_fetcher.Pass()),
216 supervised_user_sync_service_(service),
217 supervised_user_shared_settings_service_(shared_settings_service),
218 pending_supervised_user_acknowledged_(false),
219 is_existing_supervised_user_(false),
220 avatar_updated_(false),
221 weak_ptr_factory_(this) {
222 supervised_user_sync_service_->AddObserver(this);
225 SupervisedUserRegistrationUtilityImpl::
226 ~SupervisedUserRegistrationUtilityImpl() {
227 supervised_user_sync_service_->RemoveObserver(this);
228 CancelPendingRegistration();
231 void SupervisedUserRegistrationUtilityImpl::Register(
232 const std::string& supervised_user_id,
233 const SupervisedUserRegistrationInfo& info,
234 const RegistrationCallback& callback) {
235 DCHECK(pending_supervised_user_id_.empty());
236 callback_ = callback;
237 pending_supervised_user_id_ = supervised_user_id;
239 bool need_password_update = !info.password_data.empty();
240 const base::DictionaryValue* dict =
241 prefs_->GetDictionary(prefs::kSupervisedUsers);
242 is_existing_supervised_user_ = dict->HasKey(supervised_user_id);
243 if (!is_existing_supervised_user_) {
244 supervised_user_sync_service_->AddSupervisedUser(
245 pending_supervised_user_id_,
246 base::UTF16ToUTF8(info.name),
248 info.password_signature_key,
249 info.password_encryption_key,
252 const base::DictionaryValue* value = NULL;
254 dict->GetDictionaryWithoutPathExpansion(supervised_user_id, &value);
257 bool need_keys = !info.password_signature_key.empty() ||
258 !info.password_encryption_key.empty();
260 value->GetString(SupervisedUserSyncService::kPasswordSignatureKey,
263 value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey,
267 bool keys_need_update = need_keys && !have_keys;
269 if (keys_need_update) {
270 supervised_user_sync_service_->UpdateSupervisedUser(
271 pending_supervised_user_id_,
272 base::UTF16ToUTF8(info.name),
274 info.password_signature_key,
275 info.password_encryption_key,
278 // The user already exists and does not need to be updated.
279 need_password_update = false;
280 OnSupervisedUserAcknowledged(supervised_user_id);
283 supervised_user_sync_service_->UpdateSupervisedUserAvatarIfNeeded(
287 #if defined(OS_CHROMEOS)
288 const char* kAvatarKey = supervised_users::kChromeOSAvatarIndex;
290 const char* kAvatarKey = supervised_users::kChromeAvatarIndex;
292 supervised_user_shared_settings_service_->SetValue(
293 pending_supervised_user_id_, kAvatarKey,
294 base::FundamentalValue(info.avatar_index));
295 if (need_password_update) {
296 password_update_.reset(new SupervisedUserSharedSettingsUpdate(
297 supervised_user_shared_settings_service_,
298 pending_supervised_user_id_,
299 supervised_users::kChromeOSPasswordData,
300 scoped_ptr<base::Value>(info.password_data.DeepCopy()),
302 &SupervisedUserRegistrationUtilityImpl::
303 OnPasswordChangeAcknowledged,
304 weak_ptr_factory_.GetWeakPtr())));
307 browser_sync::DeviceInfo::GetClientName(
308 base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken,
309 weak_ptr_factory_.GetWeakPtr()));
312 void SupervisedUserRegistrationUtilityImpl::CancelPendingRegistration() {
313 AbortPendingRegistration(
314 false, // Don't run the callback. The error will be ignored.
315 GoogleServiceAuthError(GoogleServiceAuthError::NONE));
318 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUserAcknowledged(
319 const std::string& supervised_user_id) {
320 DCHECK_EQ(pending_supervised_user_id_, supervised_user_id);
321 DCHECK(!pending_supervised_user_acknowledged_);
322 pending_supervised_user_acknowledged_ = true;
323 CompleteRegistrationIfReady();
326 void SupervisedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged(
328 DCHECK(password_update_);
330 password_update_.reset();
331 CompleteRegistrationIfReady();
334 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersSyncingStopped() {
335 AbortPendingRegistration(
336 true, // Run the callback.
337 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
340 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersChanged() {}
342 void SupervisedUserRegistrationUtilityImpl::FetchToken(
343 const std::string& client_name) {
344 token_fetcher_->Start(
345 pending_supervised_user_id_, client_name,
346 base::Bind(&SupervisedUserRegistrationUtilityImpl::OnReceivedToken,
347 weak_ptr_factory_.GetWeakPtr()));
350 void SupervisedUserRegistrationUtilityImpl::OnReceivedToken(
351 const GoogleServiceAuthError& error,
352 const std::string& token) {
353 if (error.state() != GoogleServiceAuthError::NONE) {
354 CompleteRegistration(true, error);
358 DCHECK(!token.empty());
359 pending_supervised_user_token_ = token;
360 CompleteRegistrationIfReady();
363 void SupervisedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
364 bool skip_check = CommandLine::ForCurrentProcess()->HasSwitch(
365 switches::kNoSupervisedUserAcknowledgmentCheck);
367 if (!pending_supervised_user_acknowledged_ && !skip_check)
369 if (password_update_ && !skip_check)
371 if (pending_supervised_user_token_.empty())
374 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
375 CompleteRegistration(true, error);
378 void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
380 const GoogleServiceAuthError& error) {
381 pending_supervised_user_token_.clear();
382 CompleteRegistration(run_callback, error);
385 void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
387 const GoogleServiceAuthError& error) {
388 if (callback_.is_null())
391 if (pending_supervised_user_token_.empty()) {
392 DCHECK(!pending_supervised_user_id_.empty());
394 if (!is_existing_supervised_user_) {
395 // Remove the pending supervised user if we weren't successful.
396 // However, check that we are not importing a supervised user
397 // before deleting it from sync to avoid accidental deletion of
398 // existing supervised users by just canceling the registration for
400 supervised_user_sync_service_->DeleteSupervisedUser(
401 pending_supervised_user_id_);
402 } else if (avatar_updated_) {
403 // Canceling (or failing) a supervised user import that did set the avatar
404 // should undo this change.
405 supervised_user_sync_service_->ClearSupervisedUserAvatar(
406 pending_supervised_user_id_);
411 callback_.Run(error, pending_supervised_user_token_);