Add GCMChannelStatusSyncer to schedule requests and enable/disable GCM
[chromium-blink-merge.git] / chrome / browser / supervised_user / supervised_user_registration_utility.cc
blobc1eb8b09f754271cf39868f0c0ed918f71f088b0
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"
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/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;
36 namespace {
38 SupervisedUserRegistrationUtility* g_instance_for_tests = NULL;
40 // Actual implementation of SupervisedUserRegistrationUtility.
41 class SupervisedUserRegistrationUtilityImpl
42 : public SupervisedUserRegistrationUtility,
43 public SupervisedUserSyncServiceObserver {
44 public:
45 SupervisedUserRegistrationUtilityImpl(
46 PrefService* prefs,
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;
71 private:
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);
101 PrefService* prefs_;
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);
123 } // namespace
125 SupervisedUserRegistrationInfo::SupervisedUserRegistrationInfo(
126 const base::string16& name,
127 int avatar_index)
128 : avatar_index(avatar_index),
129 name(name) {
132 SupervisedUserRegistrationInfo::~SupervisedUserRegistrationInfo() {}
134 ScopedTestingSupervisedUserRegistrationUtility::
135 ScopedTestingSupervisedUserRegistrationUtility(
136 SupervisedUserRegistrationUtility* instance) {
137 SupervisedUserRegistrationUtility::SetUtilityForTests(instance);
140 ScopedTestingSupervisedUserRegistrationUtility::
141 ~ScopedTestingSupervisedUserRegistrationUtility() {
142 SupervisedUserRegistrationUtility::SetUtilityForTests(NULL);
145 // static
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(
164 token_service,
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(
173 profile->GetPrefs(),
174 token_fetcher.Pass(),
175 supervised_user_sync_service,
176 supervised_user_shared_settings_service));
179 // static
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;
186 // static
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;
194 // static
195 SupervisedUserRegistrationUtility*
196 SupervisedUserRegistrationUtility::CreateImpl(
197 PrefService* prefs,
198 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
199 SupervisedUserSyncService* service,
200 SupervisedUserSharedSettingsService* shared_settings_service) {
201 return new SupervisedUserRegistrationUtilityImpl(prefs,
202 token_fetcher.Pass(),
203 service,
204 shared_settings_service);
207 namespace {
209 SupervisedUserRegistrationUtilityImpl::SupervisedUserRegistrationUtilityImpl(
210 PrefService* prefs,
211 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher,
212 SupervisedUserSyncService* service,
213 SupervisedUserSharedSettingsService* shared_settings_service)
214 : prefs_(prefs),
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),
247 info.master_key,
248 info.password_signature_key,
249 info.password_encryption_key,
250 info.avatar_index);
251 } else {
252 const base::DictionaryValue* value = NULL;
253 bool success =
254 dict->GetDictionaryWithoutPathExpansion(supervised_user_id, &value);
255 DCHECK(success);
256 std::string key;
257 bool need_keys = !info.password_signature_key.empty() ||
258 !info.password_encryption_key.empty();
259 bool have_keys =
260 value->GetString(SupervisedUserSyncService::kPasswordSignatureKey,
261 &key) &&
262 !key.empty() &&
263 value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey,
264 &key) &&
265 !key.empty();
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),
273 info.master_key,
274 info.password_signature_key,
275 info.password_encryption_key,
276 info.avatar_index);
277 } else {
278 // The user already exists and does not need to be updated.
279 need_password_update = false;
280 OnSupervisedUserAcknowledged(supervised_user_id);
282 avatar_updated_ =
283 supervised_user_sync_service_->UpdateSupervisedUserAvatarIfNeeded(
284 supervised_user_id,
285 info.avatar_index);
287 #if defined(OS_CHROMEOS)
288 const char* kAvatarKey = supervised_users::kChromeOSAvatarIndex;
289 #else
290 const char* kAvatarKey = supervised_users::kChromeAvatarIndex;
291 #endif
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()),
301 base::Bind(
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(
327 bool success) {
328 DCHECK(password_update_);
329 DCHECK(success);
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);
355 return;
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)
368 return;
369 if (password_update_ && !skip_check)
370 return;
371 if (pending_supervised_user_token_.empty())
372 return;
374 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
375 CompleteRegistration(true, error);
378 void SupervisedUserRegistrationUtilityImpl::AbortPendingRegistration(
379 bool run_callback,
380 const GoogleServiceAuthError& error) {
381 pending_supervised_user_token_.clear();
382 CompleteRegistration(run_callback, error);
385 void SupervisedUserRegistrationUtilityImpl::CompleteRegistration(
386 bool run_callback,
387 const GoogleServiceAuthError& error) {
388 if (callback_.is_null())
389 return;
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
399 // example.
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_);
410 if (run_callback)
411 callback_.Run(error, pending_supervised_user_token_);
412 callback_.Reset();
415 } // namespace