Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / supervised_user / legacy / supervised_user_registration_utility.cc
blob5242fd63e96a717e0fd220107d3db88d9e04997c
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"
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/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;
37 namespace {
39 SupervisedUserRegistrationUtility* g_instance_for_tests = NULL;
41 // Actual implementation of SupervisedUserRegistrationUtility.
42 class 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);
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;
72 private:
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);
102 PrefService* prefs_;
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);
124 } // namespace
126 SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo(
127 const base::string16& name,
128 int avatar_index)
129 : avatar_index(avatar_index),
130 name(name) {
133 SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {}
135 ScopedTestingSupervisedUserRegistrationUtility::
136 ScopedTestingSupervisedUserRegistrationUtility(
137 SupervisedUserRegistrationUtility* instance) {
138 SupervisedUserRegistrationUtility::SetUtilityForTests(instance);
141 ScopedTestingSupervisedUserRegistrationUtility::
142 ~ScopedTestingSupervisedUserRegistrationUtility() {
143 SupervisedUserRegistrationUtility::SetUtilityForTests(NULL);
146 // static
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(
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));
180 // static
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;
187 // static
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;
195 // static
196 SupervisedUserRegistrationUtility*
197 SupervisedUserRegistrationUtility::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);
208 namespace {
210 SupervisedUserRegistrationUtilityImpl::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);
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),
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();
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),
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);
283 avatar_updated_ =
284 supervised_user_sync_service_->UpdateSupervisedUserAvatarIfNeeded(
285 supervised_user_id,
286 info.avatar_index);
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())));
308 syncer::GetSessionName(
309 content::BrowserThread::GetBlockingPool()
310 ->GetTaskRunnerWithShutdownBehavior(
311 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(),
312 base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken,
313 weak_ptr_factory_.GetWeakPtr()));
316 void SupervisedUserRegistrationUtilityImpl::CancelPendingRegistration() {
317 AbortPendingRegistration(
318 false, // Don't run the callback. The error will be ignored.
319 GoogleServiceAuthError(GoogleServiceAuthError::NONE));
322 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUserAcknowledged(
323 const std::string& supervised_user_id) {
324 DCHECK_EQ(pending_supervised_user_id_, supervised_user_id);
325 DCHECK(!pending_supervised_user_acknowledged_);
326 pending_supervised_user_acknowledged_ = true;
327 CompleteRegistrationIfReady();
330 void SupervisedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged(
331 bool success) {
332 DCHECK(password_update_);
333 DCHECK(success);
334 password_update_.reset();
335 CompleteRegistrationIfReady();
338 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersSyncingStopped() {
339 AbortPendingRegistration(
340 true, // Run the callback.
341 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
344 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersChanged() {}
346 void SupervisedUserRegistrationUtilityImpl::FetchToken(
347 const std::string& client_name) {
348 token_fetcher_->Start(
349 pending_supervised_user_id_, client_name,
350 base::Bind(&SupervisedUserRegistrationUtilityImpl::OnReceivedToken,
351 weak_ptr_factory_.GetWeakPtr()));
354 void SupervisedUserRegistrationUtilityImpl::OnReceivedToken(
355 const GoogleServiceAuthError& error,
356 const std::string& token) {
357 if (error.state() != GoogleServiceAuthError::NONE) {
358 CompleteRegistration(true, error);
359 return;
362 DCHECK(!token.empty());
363 pending_supervised_user_token_ = token;
364 CompleteRegistrationIfReady();
367 void SupervisedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
368 bool skip_check = base::CommandLine::ForCurrentProcess()->HasSwitch(
369 switches::kNoSupervisedUserAcknowledgmentCheck);
371 if (!pending_supervised_user_acknowledged_ && !skip_check)
372 return;
373 if (password_update_ && !skip_check)
374 return;
375 if (pending_supervised_user_token_.empty())
376 return;
378 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
379 CompleteRegistration(true, error);
382 void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
383 bool run_callback,
384 const GoogleServiceAuthError& error) {
385 pending_supervised_user_token_.clear();
386 CompleteRegistration(run_callback, error);
389 void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
390 bool run_callback,
391 const GoogleServiceAuthError& error) {
392 if (callback_.is_null())
393 return;
395 if (pending_supervised_user_token_.empty()) {
396 DCHECK(!pending_supervised_user_id_.empty());
398 if (!is_existing_supervised_user_) {
399 // Remove the pending supervised user if we weren't successful.
400 // However, check that we are not importing a supervised user
401 // before deleting it from sync to avoid accidental deletion of
402 // existing supervised users by just canceling the registration for
403 // example.
404 supervised_user_sync_service_->DeleteSupervisedUser(
405 pending_supervised_user_id_);
406 } else if (avatar_updated_) {
407 // Canceling (or failing) a supervised user import that did set the avatar
408 // should undo this change.
409 supervised_user_sync_service_->ClearSupervisedUserAvatar(
410 pending_supervised_user_id_);
414 if (run_callback)
415 callback_.Run(error, pending_supervised_user_token_);
416 callback_.Reset();
419 } // namespace