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.
4
5 #include "chrome/browser/supervised_user/supervised_user_registration_utility.h"
6
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/profile_oauth2_token_service_factory.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/browser/supervised_user/supervised_user_constants.h"
18 #include "chrome/browser/supervised_user/supervised_user_refresh_token_fetcher.h"
19 #include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h"
20 #include "chrome/browser/supervised_user/supervised_user_shared_settings_service_factory.h"
21 #include "chrome/browser/supervised_user/supervised_user_shared_settings_update.h"
22 #include "chrome/browser/supervised_user/supervised_user_sync_service.h"
23 #include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h"
24 #include "chrome/browser/sync/glue/device_info.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_manager.h"
29 #include "google_apis/gaia/gaia_urls.h"
30 #include "google_apis/gaia/google_service_auth_error.h"
31
32 using base::DictionaryValue;
33
34 namespace {
35
36 SupervisedUserRegistrationUtility* g_instance_for_tests = NULL;
37
38 // Actual implementation of SupervisedUserRegistrationUtility.
39 class SupervisedUserRegistrationUtilityImpl
40 : public SupervisedUserRegistrationUtility,
41 public SupervisedUserSyncServiceObserver {
42 public:
43 SupervisedUserRegistrationUtilityImpl(
44 PrefService* prefs,
45 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
46 SupervisedUserSyncService* service,
47 SupervisedUserSharedSettingsService* shared_settings_service);
48
49 virtual ~SupervisedUserRegistrationUtilityImpl();
50
51 // Registers a new supervised user with the server. |supervised_user_id| is a
52 // new unique ID for the new supervised user. If its value is the same as that
53 // of one of the existing supervised users, then the same user will be created
54 // on this machine (and if he has no avatar in sync, his avatar will be
55 // updated). |info| contains necessary information like the display name of
56 // the user and his avatar. |callback| is called with the result of the
57 // registration. We use the info here and not the profile, because on Chrome
58 // OS the profile of the supervised user does not yet exist.
59 virtual void Register(const std::string& supervised_user_id,
60 const SupervisedUserRegistrationInfo& info,
61 const RegistrationCallback& callback) OVERRIDE;
62
63 // SupervisedUserSyncServiceObserver:
64 virtual void OnSupervisedUserAcknowledged(
65 const std::string& supervised_user_id) OVERRIDE;
66 virtual void OnSupervisedUsersSyncingStopped() OVERRIDE;
67 virtual void OnSupervisedUsersChanged() OVERRIDE;
68
69 private:
70 // Fetches the supervised user token when we have the device name.
71 void FetchToken(const std::string& client_name);
72
73 // Called when we have received a token for the supervised user.
74 void OnReceivedToken(const GoogleServiceAuthError& error,
75 const std::string& token);
76
77 // Dispatches the callback and cleans up if all the conditions have been met.
78 void CompleteRegistrationIfReady();
79
80 // Aborts any registration currently in progress. If |run_callback| is true,
81 // calls the callback specified in Register() with the given |error|.
82 void AbortPendingRegistration(bool run_callback,
83 const GoogleServiceAuthError& error);
84
85 // If |run_callback| is true, dispatches the callback with the saved token
86 // (which may be empty) and the given |error|. In any case, resets internal
87 // variables to be ready for the next registration.
88 void CompleteRegistration(bool run_callback,
89 const GoogleServiceAuthError& error);
90
91 // Cancels any registration currently in progress, without calling the
92 // callback or reporting an error.
93 void CancelPendingRegistration();
94
95 // SupervisedUserSharedSettingsUpdate acknowledgment callback for password
96 // data in shared settings.
97 void OnPasswordChangeAcknowledged(bool success);
98
99 PrefService* prefs_;
100 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher_;
101
102 // A |KeyedService| owned by the custodian profile.
103 SupervisedUserSyncService* supervised_user_sync_service_;
104
105 // A |KeyedService| owned by the custodian profile.
106 SupervisedUserSharedSettingsService* supervised_user_shared_settings_service_;
107
108 std::string pending_supervised_user_id_;
109 std::string pending_supervised_user_token_;
110 bool pending_supervised_user_acknowledged_;
111 bool is_existing_supervised_user_;
112 bool avatar_updated_;
113 RegistrationCallback callback_;
114 scoped_ptr<SupervisedUserSharedSettingsUpdate> password_update_;
115
116 base::WeakPtrFactory<SupervisedUserRegistrationUtilityImpl> weak_ptr_factory_;
117
118 DISALLOW_COPY_AND_ASSIGN(SupervisedUserRegistrationUtilityImpl);
119 };
120
121 } // namespace
122
SupervisedUserRegistrationInfo(const base::string16 & name,int avatar_index)123 SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo(
124 const base::string16& name,
125 int avatar_index)
126 : avatar_index(avatar_index),
127 name(name) {
128 }
129
~SupervisedUserRegistrationInfo()130 SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {}
131
132 ScopedTestingSupervisedUserRegistrationUtility::
ScopedTestingSupervisedUserRegistrationUtility(SupervisedUserRegistrationUtility * instance)133 ScopedTestingSupervisedUserRegistrationUtility(
134 SupervisedUserRegistrationUtility* instance) {
135 SupervisedUserRegistrationUtility::SetUtilityForTests(instance);
136 }
137
138 ScopedTestingSupervisedUserRegistrationUtility::
~ScopedTestingSupervisedUserRegistrationUtility()139 ~ScopedTestingSupervisedUserRegistrationUtility() {
140 SupervisedUserRegistrationUtility::SetUtilityForTests(NULL);
141 }
142
143 // static
144 scoped_ptr<SupervisedUserRegistrationUtility>
Create(Profile * profile)145 SupervisedUserRegistrationUtility::Create(Profile* profile) {
146 if (g_instance_for_tests) {
147 SupervisedUserRegistrationUtility* result = g_instance_for_tests;
148 g_instance_for_tests = NULL;
149 return make_scoped_ptr(result);
150 }
151
152 ProfileOAuth2TokenService* token_service =
153 ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
154 SigninManagerBase* signin_manager =
155 SigninManagerFactory::GetForProfile(profile);
156 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher =
157 SupervisedUserRefreshTokenFetcher::Create(
158 token_service,
159 signin_manager->GetAuthenticatedAccountId(),
160 profile->GetRequestContext());
161 SupervisedUserSyncService* supervised_user_sync_service =
162 SupervisedUserSyncServiceFactory::GetForProfile(profile);
163 SupervisedUserSharedSettingsService* supervised_user_shared_settings_service =
164 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(profile);
165 return make_scoped_ptr(SupervisedUserRegistrationUtility::CreateImpl(
166 profile->GetPrefs(),
167 token_fetcher.Pass(),
168 supervised_user_sync_service,
169 supervised_user_shared_settings_service));
170 }
171
172 // static
GenerateNewSupervisedUserId()173 std::string SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId() {
174 std::string new_supervised_user_id;
175 base::Base64Encode(base::RandBytesAsString(8), &new_supervised_user_id);
176 return new_supervised_user_id;
177 }
178
179 // static
SetUtilityForTests(SupervisedUserRegistrationUtility * utility)180 void SupervisedUserRegistrationUtility::SetUtilityForTests(
181 SupervisedUserRegistrationUtility* utility) {
182 if (g_instance_for_tests)
183 delete g_instance_for_tests;
184 g_instance_for_tests = utility;
185 }
186
187 // static
188 SupervisedUserRegistrationUtility*
CreateImpl(PrefService * prefs,scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,SupervisedUserSyncService * service,SupervisedUserSharedSettingsService * shared_settings_service)189 SupervisedUserRegistrationUtility::CreateImpl(
190 PrefService* prefs,
191 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
192 SupervisedUserSyncService* service,
193 SupervisedUserSharedSettingsService* shared_settings_service) {
194 return new SupervisedUserRegistrationUtilityImpl(prefs,
195 token_fetcher.Pass(),
196 service,
197 shared_settings_service);
198 }
199
200 namespace {
201
SupervisedUserRegistrationUtilityImpl(PrefService * prefs,scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,SupervisedUserSyncService * service,SupervisedUserSharedSettingsService * shared_settings_service)202 SupervisedUserRegistrationUtilityImpl::SupervisedUserRegistrationUtilityImpl(
203 PrefService* prefs,
204 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
205 SupervisedUserSyncService* service,
206 SupervisedUserSharedSettingsService* shared_settings_service)
207 : prefs_(prefs),
208 token_fetcher_(token_fetcher.Pass()),
209 supervised_user_sync_service_(service),
210 supervised_user_shared_settings_service_(shared_settings_service),
211 pending_supervised_user_acknowledged_(false),
212 is_existing_supervised_user_(false),
213 avatar_updated_(false),
214 weak_ptr_factory_(this) {
215 supervised_user_sync_service_->AddObserver(this);
216 }
217
218 SupervisedUserRegistrationUtilityImpl::
~SupervisedUserRegistrationUtilityImpl()219 ~SupervisedUserRegistrationUtilityImpl() {
220 supervised_user_sync_service_->RemoveObserver(this);
221 CancelPendingRegistration();
222 }
223
Register(const std::string & supervised_user_id,const SupervisedUserRegistrationInfo & info,const RegistrationCallback & callback)224 void SupervisedUserRegistrationUtilityImpl::Register(
225 const std::string& supervised_user_id,
226 const SupervisedUserRegistrationInfo& info,
227 const RegistrationCallback& callback) {
228 DCHECK(pending_supervised_user_id_.empty());
229 callback_ = callback;
230 pending_supervised_user_id_ = supervised_user_id;
231
232 bool need_password_update = !info.password_data.empty();
233 const base::DictionaryValue* dict =
234 prefs_->GetDictionary(prefs::kSupervisedUsers);
235 is_existing_supervised_user_ = dict->HasKey(supervised_user_id);
236 if (!is_existing_supervised_user_) {
237 supervised_user_sync_service_->AddSupervisedUser(
238 pending_supervised_user_id_,
239 base::UTF16ToUTF8(info.name),
240 info.master_key,
241 info.password_signature_key,
242 info.password_encryption_key,
243 info.avatar_index);
244 } else {
245 const base::DictionaryValue* value = NULL;
246 bool success =
247 dict->GetDictionaryWithoutPathExpansion(supervised_user_id, &value);
248 DCHECK(success);
249 std::string key;
250 bool need_keys = !info.password_signature_key.empty() ||
251 !info.password_encryption_key.empty();
252 bool have_keys =
253 value->GetString(SupervisedUserSyncService::kPasswordSignatureKey,
254 &key) &&
255 !key.empty() &&
256 value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey,
257 &key) &&
258 !key.empty();
259
260 bool keys_need_update = need_keys && !have_keys;
261
262 if (keys_need_update) {
263 supervised_user_sync_service_->UpdateSupervisedUser(
264 pending_supervised_user_id_,
265 base::UTF16ToUTF8(info.name),
266 info.master_key,
267 info.password_signature_key,
268 info.password_encryption_key,
269 info.avatar_index);
270 } else {
271 // The user already exists and does not need to be updated.
272 need_password_update = false;
273 OnSupervisedUserAcknowledged(supervised_user_id);
274 }
275 avatar_updated_ =
276 supervised_user_sync_service_->UpdateSupervisedUserAvatarIfNeeded(
277 supervised_user_id,
278 info.avatar_index);
279 }
280 #if defined(OS_CHROMEOS)
281 const char* kAvatarKey = supervised_users::kChromeOSAvatarIndex;
282 #else
283 const char* kAvatarKey = supervised_users::kChromeAvatarIndex;
284 #endif
285 supervised_user_shared_settings_service_->SetValue(
286 pending_supervised_user_id_, kAvatarKey,
287 base::FundamentalValue(info.avatar_index));
288 if (need_password_update) {
289 password_update_.reset(new SupervisedUserSharedSettingsUpdate(
290 supervised_user_shared_settings_service_,
291 pending_supervised_user_id_,
292 supervised_users::kChromeOSPasswordData,
293 scoped_ptr<base::Value>(info.password_data.DeepCopy()),
294 base::Bind(
295 &SupervisedUserRegistrationUtilityImpl::
296 OnPasswordChangeAcknowledged,
297 weak_ptr_factory_.GetWeakPtr())));
298 }
299
300 browser_sync::DeviceInfo::GetClientName(
301 base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken,
302 weak_ptr_factory_.GetWeakPtr()));
303 }
304
CancelPendingRegistration()305 void SupervisedUserRegistrationUtilityImpl::CancelPendingRegistration() {
306 AbortPendingRegistration(
307 false, // Don't run the callback. The error will be ignored.
308 GoogleServiceAuthError(GoogleServiceAuthError::NONE));
309 }
310
OnSupervisedUserAcknowledged(const std::string & supervised_user_id)311 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUserAcknowledged(
312 const std::string& supervised_user_id) {
313 DCHECK_EQ(pending_supervised_user_id_, supervised_user_id);
314 DCHECK(!pending_supervised_user_acknowledged_);
315 pending_supervised_user_acknowledged_ = true;
316 CompleteRegistrationIfReady();
317 }
318
OnPasswordChangeAcknowledged(bool success)319 void SupervisedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged(
320 bool success) {
321 DCHECK(password_update_);
322 DCHECK(success);
323 password_update_.reset();
324 CompleteRegistrationIfReady();
325 }
326
OnSupervisedUsersSyncingStopped()327 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersSyncingStopped() {
328 AbortPendingRegistration(
329 true, // Run the callback.
330 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
331 }
332
OnSupervisedUsersChanged()333 void SupervisedUserRegistrationUtilityImpl::OnSupervisedUsersChanged() {}
334
FetchToken(const std::string & client_name)335 void SupervisedUserRegistrationUtilityImpl::FetchToken(
336 const std::string& client_name) {
337 token_fetcher_->Start(
338 pending_supervised_user_id_, client_name,
339 base::Bind(&SupervisedUserRegistrationUtilityImpl::OnReceivedToken,
340 weak_ptr_factory_.GetWeakPtr()));
341 }
342
OnReceivedToken(const GoogleServiceAuthError & error,const std::string & token)343 void SupervisedUserRegistrationUtilityImpl::OnReceivedToken(
344 const GoogleServiceAuthError& error,
345 const std::string& token) {
346 if (error.state() != GoogleServiceAuthError::NONE) {
347 CompleteRegistration(true, error);
348 return;
349 }
350
351 DCHECK(!token.empty());
352 pending_supervised_user_token_ = token;
353 CompleteRegistrationIfReady();
354 }
355
CompleteRegistrationIfReady()356 void SupervisedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
357 bool skip_check = CommandLine::ForCurrentProcess()->HasSwitch(
358 switches::kNoSupervisedUserAcknowledgmentCheck);
359
360 if (!pending_supervised_user_acknowledged_ && !skip_check)
361 return;
362 if (password_update_ && !skip_check)
363 return;
364 if (pending_supervised_user_token_.empty())
365 return;
366
367 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
368 CompleteRegistration(true, error);
369 }
370
AbortPendingRegistration(bool run_callback,const GoogleServiceAuthError & error)371 void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
372 bool run_callback,
373 const GoogleServiceAuthError& error) {
374 pending_supervised_user_token_.clear();
375 CompleteRegistration(run_callback, error);
376 }
377
CompleteRegistration(bool run_callback,const GoogleServiceAuthError & error)378 void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
379 bool run_callback,
380 const GoogleServiceAuthError& error) {
381 if (callback_.is_null())
382 return;
383
384 if (pending_supervised_user_token_.empty()) {
385 DCHECK(!pending_supervised_user_id_.empty());
386
387 if (!is_existing_supervised_user_) {
388 // Remove the pending supervised user if we weren't successful.
389 // However, check that we are not importing a supervised user
390 // before deleting it from sync to avoid accidental deletion of
391 // existing supervised users by just canceling the registration for
392 // example.
393 supervised_user_sync_service_->DeleteSupervisedUser(
394 pending_supervised_user_id_);
395 } else if (avatar_updated_) {
396 // Canceling (or failing) a supervised user import that did set the avatar
397 // should undo this change.
398 supervised_user_sync_service_->ClearSupervisedUserAvatar(
399 pending_supervised_user_id_);
400 }
401 }
402
403 if (run_callback)
404 callback_.Run(error, pending_supervised_user_token_);
405 callback_.Reset();
406 }
407
408 } // namespace
409