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