Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / supervised_user / legacy / supervised_user_registration_utility.cc
blobb8563d2bbe9bb88f1290b71b1907302b829e744a
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 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(
329 bool success) {
330 DCHECK(password_update_);
331 DCHECK(success);
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);
357 return;
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)
370 return;
371 if (password_update_ && !skip_check)
372 return;
373 if (pending_supervised_user_token_.empty())
374 return;
376 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
377 CompleteRegistration(true, error);
380 void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
381 bool run_callback,
382 const GoogleServiceAuthError& error) {
383 pending_supervised_user_token_.clear();
384 CompleteRegistration(run_callback, error);
387 void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
388 bool run_callback,
389 const GoogleServiceAuthError& error) {
390 if (callback_.is_null())
391 return;
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
401 // example.
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_);
412 if (run_callback)
413 callback_.Run(error, pending_supervised_user_token_);
414 callback_.Reset();
417 } // namespace