• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/managed_mode/managed_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/managed_mode/managed_user_refresh_token_fetcher.h"
15 #include "chrome/browser/managed_mode/managed_user_sync_service.h"
16 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/signin/profile_oauth2_token_service.h"
19 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
20 #include "chrome/browser/sync/glue/device_info.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "google_apis/gaia/gaia_urls.h"
24 #include "google_apis/gaia/google_service_auth_error.h"
25 
26 using base::DictionaryValue;
27 
28 namespace {
29 
30 ManagedUserRegistrationUtility* g_instance_for_tests = NULL;
31 
32 // Actual implementation of ManagedUserRegistrationUtility.
33 class ManagedUserRegistrationUtilityImpl
34     : public ManagedUserRegistrationUtility,
35       public ManagedUserSyncServiceObserver {
36  public:
37   ManagedUserRegistrationUtilityImpl(
38       PrefService* prefs,
39       scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
40       ManagedUserSyncService* service);
41 
42   virtual ~ManagedUserRegistrationUtilityImpl();
43 
44   // Registers a new managed user with the server. |managed_user_id| is a new
45   // unique ID for the new managed user. If its value is the same as that of
46   // of one of the existing managed users, then the same user will be created
47   // on this machine (and if he has no avatar in sync, his avatar will
48   // be updated). |info| contains necessary information like
49   // the display name of the user and his avatar. |callback| is called
50   // with the result of the registration. We use the info here and not the
51   // profile, because on Chrome OS the profile of the managed user does not
52   // yet exist.
53   virtual void Register(const std::string& managed_user_id,
54                         const ManagedUserRegistrationInfo& info,
55                         const RegistrationCallback& callback) OVERRIDE;
56 
57   // ManagedUserSyncServiceObserver:
58   virtual void OnManagedUserAcknowledged(const std::string& managed_user_id)
59       OVERRIDE;
60   virtual void OnManagedUsersSyncingStopped() OVERRIDE;
61 
62  private:
63   // Fetches the managed user token when we have the device name.
64   void FetchToken(const std::string& client_name);
65 
66   // Called when we have received a token for the managed user.
67   void OnReceivedToken(const GoogleServiceAuthError& error,
68                        const std::string& token);
69 
70   // Dispatches the callback and cleans up if all the conditions have been met.
71   void CompleteRegistrationIfReady();
72 
73   // Aborts any registration currently in progress. If |run_callback| is true,
74   // calls the callback specified in Register() with the given |error|.
75   void AbortPendingRegistration(bool run_callback,
76                                 const GoogleServiceAuthError& error);
77 
78   // If |run_callback| is true, dispatches the callback with the saved token
79   // (which may be empty) and the given |error|. In any case, resets internal
80   // variables to be ready for the next registration.
81   void CompleteRegistration(bool run_callback,
82                             const GoogleServiceAuthError& error);
83 
84   // Cancels any registration currently in progress, without calling the
85   // callback or reporting an error.
86   void CancelPendingRegistration();
87 
88   PrefService* prefs_;
89   scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher_;
90 
91   // A |BrowserContextKeyedService| owned by the custodian profile.
92   ManagedUserSyncService* managed_user_sync_service_;
93 
94   std::string pending_managed_user_id_;
95   std::string pending_managed_user_token_;
96   bool pending_managed_user_acknowledged_;
97   bool is_existing_managed_user_;
98   bool avatar_updated_;
99   RegistrationCallback callback_;
100 
101   base::WeakPtrFactory<ManagedUserRegistrationUtilityImpl> weak_ptr_factory_;
102 
103   DISALLOW_COPY_AND_ASSIGN(ManagedUserRegistrationUtilityImpl);
104 };
105 
106 } // namespace
107 
ManagedUserRegistrationInfo(const base::string16 & name,int avatar_index)108 ManagedUserRegistrationInfo::ManagedUserRegistrationInfo(
109     const base::string16& name,
110     int avatar_index)
111     : avatar_index(avatar_index),
112       name(name) {
113 }
114 
115 ScopedTestingManagedUserRegistrationUtility::
ScopedTestingManagedUserRegistrationUtility(ManagedUserRegistrationUtility * instance)116     ScopedTestingManagedUserRegistrationUtility(
117         ManagedUserRegistrationUtility* instance) {
118   ManagedUserRegistrationUtility::SetUtilityForTests(instance);
119 }
120 
121 ScopedTestingManagedUserRegistrationUtility::
~ScopedTestingManagedUserRegistrationUtility()122     ~ScopedTestingManagedUserRegistrationUtility() {
123   ManagedUserRegistrationUtility::SetUtilityForTests(NULL);
124 }
125 
126 // static
127 scoped_ptr<ManagedUserRegistrationUtility>
Create(Profile * profile)128 ManagedUserRegistrationUtility::Create(Profile* profile) {
129   if (g_instance_for_tests) {
130     ManagedUserRegistrationUtility* result = g_instance_for_tests;
131     g_instance_for_tests = NULL;
132     return make_scoped_ptr(result);
133   }
134 
135   ProfileOAuth2TokenService* token_service =
136       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
137   scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher =
138       ManagedUserRefreshTokenFetcher::Create(
139           token_service,
140           token_service->GetPrimaryAccountId(),
141           profile->GetRequestContext());
142   ManagedUserSyncService* managed_user_sync_service =
143       ManagedUserSyncServiceFactory::GetForProfile(profile);
144   return make_scoped_ptr(ManagedUserRegistrationUtility::CreateImpl(
145       profile->GetPrefs(),
146       token_fetcher.Pass(),
147       managed_user_sync_service));
148 }
149 
150 // static
GenerateNewManagedUserId()151 std::string ManagedUserRegistrationUtility::GenerateNewManagedUserId() {
152   std::string new_managed_user_id;
153   base::Base64Encode(base::RandBytesAsString(8), &new_managed_user_id);
154   return new_managed_user_id;
155 }
156 
157 // static
SetUtilityForTests(ManagedUserRegistrationUtility * utility)158 void ManagedUserRegistrationUtility::SetUtilityForTests(
159     ManagedUserRegistrationUtility* utility) {
160   if (g_instance_for_tests)
161     delete g_instance_for_tests;
162   g_instance_for_tests = utility;
163 }
164 
165 // static
CreateImpl(PrefService * prefs,scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,ManagedUserSyncService * service)166 ManagedUserRegistrationUtility* ManagedUserRegistrationUtility::CreateImpl(
167       PrefService* prefs,
168       scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
169       ManagedUserSyncService* service) {
170   return new ManagedUserRegistrationUtilityImpl(prefs,
171                                                 token_fetcher.Pass(),
172                                                 service);
173 }
174 
175 namespace {
176 
ManagedUserRegistrationUtilityImpl(PrefService * prefs,scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,ManagedUserSyncService * service)177 ManagedUserRegistrationUtilityImpl::ManagedUserRegistrationUtilityImpl(
178     PrefService* prefs,
179     scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
180     ManagedUserSyncService* service)
181     : prefs_(prefs),
182       token_fetcher_(token_fetcher.Pass()),
183       managed_user_sync_service_(service),
184       pending_managed_user_acknowledged_(false),
185       is_existing_managed_user_(false),
186       avatar_updated_(false),
187       weak_ptr_factory_(this) {
188   managed_user_sync_service_->AddObserver(this);
189 }
190 
~ManagedUserRegistrationUtilityImpl()191 ManagedUserRegistrationUtilityImpl::~ManagedUserRegistrationUtilityImpl() {
192   managed_user_sync_service_->RemoveObserver(this);
193   CancelPendingRegistration();
194 }
195 
Register(const std::string & managed_user_id,const ManagedUserRegistrationInfo & info,const RegistrationCallback & callback)196 void ManagedUserRegistrationUtilityImpl::Register(
197     const std::string& managed_user_id,
198     const ManagedUserRegistrationInfo& info,
199     const RegistrationCallback& callback) {
200   DCHECK(pending_managed_user_id_.empty());
201   callback_ = callback;
202   pending_managed_user_id_ = managed_user_id;
203 
204   const DictionaryValue* dict = prefs_->GetDictionary(prefs::kManagedUsers);
205   is_existing_managed_user_ = dict->HasKey(managed_user_id);
206   if (!is_existing_managed_user_) {
207     managed_user_sync_service_->AddManagedUser(pending_managed_user_id_,
208                                                base::UTF16ToUTF8(info.name),
209                                                info.master_key,
210                                                info.avatar_index);
211   } else {
212     avatar_updated_ =
213         managed_user_sync_service_->UpdateManagedUserAvatarIfNeeded(
214             managed_user_id,
215             info.avatar_index);
216 
217     // User already exists, don't wait for acknowledgment.
218     OnManagedUserAcknowledged(managed_user_id);
219   }
220 
221   browser_sync::DeviceInfo::GetClientName(
222       base::Bind(&ManagedUserRegistrationUtilityImpl::FetchToken,
223                  weak_ptr_factory_.GetWeakPtr()));
224 }
225 
CancelPendingRegistration()226 void ManagedUserRegistrationUtilityImpl::CancelPendingRegistration() {
227   AbortPendingRegistration(
228       false,  // Don't run the callback. The error will be ignored.
229       GoogleServiceAuthError(GoogleServiceAuthError::NONE));
230 }
231 
OnManagedUserAcknowledged(const std::string & managed_user_id)232 void ManagedUserRegistrationUtilityImpl::OnManagedUserAcknowledged(
233     const std::string& managed_user_id) {
234   DCHECK_EQ(pending_managed_user_id_, managed_user_id);
235   DCHECK(!pending_managed_user_acknowledged_);
236   pending_managed_user_acknowledged_ = true;
237   CompleteRegistrationIfReady();
238 }
239 
OnManagedUsersSyncingStopped()240 void ManagedUserRegistrationUtilityImpl::OnManagedUsersSyncingStopped() {
241   AbortPendingRegistration(
242       true,  // Run the callback.
243       GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
244 }
245 
FetchToken(const std::string & client_name)246 void ManagedUserRegistrationUtilityImpl::FetchToken(
247     const std::string& client_name) {
248   token_fetcher_->Start(
249       pending_managed_user_id_, client_name,
250       base::Bind(&ManagedUserRegistrationUtilityImpl::OnReceivedToken,
251                  weak_ptr_factory_.GetWeakPtr()));
252 }
253 
OnReceivedToken(const GoogleServiceAuthError & error,const std::string & token)254 void ManagedUserRegistrationUtilityImpl::OnReceivedToken(
255     const GoogleServiceAuthError& error,
256     const std::string& token) {
257   if (error.state() != GoogleServiceAuthError::NONE) {
258     CompleteRegistration(true, error);
259     return;
260   }
261 
262   DCHECK(!token.empty());
263   pending_managed_user_token_ = token;
264   CompleteRegistrationIfReady();
265 }
266 
CompleteRegistrationIfReady()267 void ManagedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
268   bool require_acknowledgment =
269       !pending_managed_user_acknowledged_ &&
270       !CommandLine::ForCurrentProcess()->HasSwitch(
271           switches::kNoManagedUserAcknowledgmentCheck);
272   if (require_acknowledgment || pending_managed_user_token_.empty())
273     return;
274 
275   GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
276   CompleteRegistration(true, error);
277 }
278 
AbortPendingRegistration(bool run_callback,const GoogleServiceAuthError & error)279 void ManagedUserRegistrationUtilityImpl::AbortPendingRegistration(
280     bool run_callback,
281     const GoogleServiceAuthError& error) {
282   pending_managed_user_token_.clear();
283   CompleteRegistration(run_callback, error);
284 }
285 
CompleteRegistration(bool run_callback,const GoogleServiceAuthError & error)286 void ManagedUserRegistrationUtilityImpl::CompleteRegistration(
287     bool run_callback,
288     const GoogleServiceAuthError& error) {
289   if (callback_.is_null())
290     return;
291 
292   if (pending_managed_user_token_.empty()) {
293     DCHECK(!pending_managed_user_id_.empty());
294 
295     if (!is_existing_managed_user_) {
296       // Remove the pending managed user if we weren't successful.
297       // However, check that we are not importing a managed user
298       // before deleting it from sync to avoid accidental deletion of
299       // existing managed users by just canceling the registration for example.
300       managed_user_sync_service_->DeleteManagedUser(pending_managed_user_id_);
301     } else if (avatar_updated_) {
302       // Canceling (or failing) a managed user import that did set the avatar
303       // should undo this change.
304       managed_user_sync_service_->ClearManagedUserAvatar(
305           pending_managed_user_id_);
306     }
307   }
308 
309   if (run_callback)
310     callback_.Run(error, pending_managed_user_token_);
311   callback_.Reset();
312 }
313 
314 } // namespace
315