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/legacy/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/legacy/supervised_user_refresh_token_fetcher.h"
19 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.h"
20 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_factory.h"
21 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_update.h"
22 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service.h"
23 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service_factory.h"
24 #include "chrome/browser/supervised_user/supervised_user_constants.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"
35 using base::DictionaryValue
;
39 SupervisedUserRegistrationUtility
* g_instance_for_tests
= NULL
;
41 // Actual implementation of SupervisedUserRegistrationUtility.
42 class SupervisedUserRegistrationUtilityImpl
43 : public SupervisedUserRegistrationUtility
,
44 public SupervisedUserSyncServiceObserver
{
46 SupervisedUserRegistrationUtilityImpl(
48 scoped_ptr
<SupervisedUserRefreshTokenFetcher
> token_fetcher
,
49 SupervisedUserSyncService
* service
,
50 SupervisedUserSharedSettingsService
* shared_settings_service
);
52 ~SupervisedUserRegistrationUtilityImpl() override
;
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 void Register(const std::string
& supervised_user_id
,
63 const SupervisedUserRegistrationInfo
& info
,
64 const RegistrationCallback
& callback
) override
;
66 // SupervisedUserSyncServiceObserver:
67 void OnSupervisedUserAcknowledged(
68 const std::string
& supervised_user_id
) override
;
69 void OnSupervisedUsersSyncingStopped() override
;
70 void OnSupervisedUsersChanged() override
;
73 // Fetches the supervised user token when we have the device name.
74 void FetchToken(const std::string
& client_name
);
76 // Called when we have received a token for the supervised user.
77 void OnReceivedToken(const GoogleServiceAuthError
& error
,
78 const std::string
& token
);
80 // Dispatches the callback and cleans up if all the conditions have been met.
81 void CompleteRegistrationIfReady();
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
);
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
);
94 // Cancels any registration currently in progress, without calling the
95 // callback or reporting an error.
96 void CancelPendingRegistration();
98 // SupervisedUserSharedSettingsUpdate acknowledgment callback for password
99 // data in shared settings.
100 void OnPasswordChangeAcknowledged(bool success
);
103 scoped_ptr
<SupervisedUserRefreshTokenFetcher
> token_fetcher_
;
105 // A |KeyedService| owned by the custodian profile.
106 SupervisedUserSyncService
* supervised_user_sync_service_
;
108 // A |KeyedService| owned by the custodian profile.
109 SupervisedUserSharedSettingsService
* supervised_user_shared_settings_service_
;
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_
;
119 base::WeakPtrFactory
<SupervisedUserRegistrationUtilityImpl
> weak_ptr_factory_
;
121 DISALLOW_COPY_AND_ASSIGN(SupervisedUserRegistrationUtilityImpl
);
126 SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo(
127 const base::string16
& name
,
129 : avatar_index(avatar_index
),
133 SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {}
135 ScopedTestingSupervisedUserRegistrationUtility::
136 ScopedTestingSupervisedUserRegistrationUtility(
137 SupervisedUserRegistrationUtility
* instance
) {
138 SupervisedUserRegistrationUtility::SetUtilityForTests(instance
);
141 ScopedTestingSupervisedUserRegistrationUtility::
142 ~ScopedTestingSupervisedUserRegistrationUtility() {
143 SupervisedUserRegistrationUtility::SetUtilityForTests(NULL
);
147 scoped_ptr
<SupervisedUserRegistrationUtility
>
148 SupervisedUserRegistrationUtility::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
);
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(
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(
175 token_fetcher
.Pass(),
176 supervised_user_sync_service
,
177 supervised_user_shared_settings_service
));
181 std::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
;
188 void SupervisedUserRegistrationUtility::SetUtilityForTests(
189 SupervisedUserRegistrationUtility
* utility
) {
190 if (g_instance_for_tests
)
191 delete g_instance_for_tests
;
192 g_instance_for_tests
= utility
;
196 SupervisedUserRegistrationUtility
*
197 SupervisedUserRegistrationUtility::CreateImpl(
199 scoped_ptr
<SupervisedUserRefreshTokenFetcher
> token_fetcher
,
200 SupervisedUserSyncService
* service
,
201 SupervisedUserSharedSettingsService
* shared_settings_service
) {
202 return new SupervisedUserRegistrationUtilityImpl(prefs
,
203 token_fetcher
.Pass(),
205 shared_settings_service
);
210 SupervisedUserRegistrationUtilityImpl::SupervisedUserRegistrationUtilityImpl(
212 scoped_ptr
<SupervisedUserRefreshTokenFetcher
> token_fetcher
,
213 SupervisedUserSyncService
* service
,
214 SupervisedUserSharedSettingsService
* shared_settings_service
)
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);
226 SupervisedUserRegistrationUtilityImpl::
227 ~SupervisedUserRegistrationUtilityImpl() {
228 supervised_user_sync_service_
->RemoveObserver(this);
229 CancelPendingRegistration();
232 void 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
;
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
),
249 info
.password_signature_key
,
250 info
.password_encryption_key
,
253 const base::DictionaryValue
* value
= NULL
;
255 dict
->GetDictionaryWithoutPathExpansion(supervised_user_id
, &value
);
258 bool need_keys
= !info
.password_signature_key
.empty() ||
259 !info
.password_encryption_key
.empty();
261 value
->GetString(SupervisedUserSyncService::kPasswordSignatureKey
,
264 value
->GetString(SupervisedUserSyncService::kPasswordEncryptionKey
,
268 bool keys_need_update
= need_keys
&& !have_keys
;
270 if (keys_need_update
) {
271 supervised_user_sync_service_
->UpdateSupervisedUser(
272 pending_supervised_user_id_
,
273 base::UTF16ToUTF8(info
.name
),
275 info
.password_signature_key
,
276 info
.password_encryption_key
,
279 // The user already exists and does not need to be updated.
280 need_password_update
= false;
281 OnSupervisedUserAcknowledged(supervised_user_id
);
284 supervised_user_sync_service_
->UpdateSupervisedUserAvatarIfNeeded(
288 #if defined(OS_CHROMEOS)
289 const char* kAvatarKey
= supervised_users::kChromeOSAvatarIndex
;
291 const char* kAvatarKey
= supervised_users::kChromeAvatarIndex
;
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()),
303 &SupervisedUserRegistrationUtilityImpl::
304 OnPasswordChangeAcknowledged
,
305 weak_ptr_factory_
.GetWeakPtr())));
308 syncer::GetSessionName(
309 content::BrowserThread::GetBlockingPool(),
310 base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken
,
311 weak_ptr_factory_
.GetWeakPtr()));
314 void SupervisedUserRegistrationUtilityImpl::CancelPendingRegistration() {
315 AbortPendingRegistration(
316 false, // Don't run the callback. The error will be ignored.
317 GoogleServiceAuthError(GoogleServiceAuthError::NONE
));
320 void 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();
328 void SupervisedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged(
330 DCHECK(password_update_
);
332 password_update_
.reset();
333 CompleteRegistrationIfReady();
336 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersSyncingStopped() {
337 AbortPendingRegistration(
338 true, // Run the callback.
339 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED
));
342 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersChanged() {}
344 void 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()));
352 void SupervisedUserRegistrationUtilityImpl::OnReceivedToken(
353 const GoogleServiceAuthError
& error
,
354 const std::string
& token
) {
355 if (error
.state() != GoogleServiceAuthError::NONE
) {
356 CompleteRegistration(true, error
);
360 DCHECK(!token
.empty());
361 pending_supervised_user_token_
= token
;
362 CompleteRegistrationIfReady();
365 void SupervisedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
366 bool skip_check
= base::CommandLine::ForCurrentProcess()->HasSwitch(
367 switches::kNoSupervisedUserAcknowledgmentCheck
);
369 if (!pending_supervised_user_acknowledged_
&& !skip_check
)
371 if (password_update_
&& !skip_check
)
373 if (pending_supervised_user_token_
.empty())
376 GoogleServiceAuthError
error(GoogleServiceAuthError::NONE
);
377 CompleteRegistration(true, error
);
380 void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
382 const GoogleServiceAuthError
& error
) {
383 pending_supervised_user_token_
.clear();
384 CompleteRegistration(run_callback
, error
);
387 void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
389 const GoogleServiceAuthError
& error
) {
390 if (callback_
.is_null())
393 if (pending_supervised_user_token_
.empty()) {
394 DCHECK(!pending_supervised_user_id_
.empty());
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
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_
);
413 callback_
.Run(error
, pending_supervised_user_token_
);