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_
);