• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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