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.
5 #include "chrome/browser/managed_mode/managed_user_registration_utility.h"
7 #include "base/base64.h"
9 #include "base/command_line.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/prefs/scoped_user_pref_update.h"
13 #include "base/rand_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h"
16 #include "chrome/browser/managed_mode/managed_user_service.h"
17 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
18 #include "chrome/browser/managed_mode/managed_user_sync_service.h"
19 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
20 #include "chrome/browser/signin/profile_oauth2_token_service.h"
21 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
22 #include "chrome/browser/sync/glue/device_info.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h"
25 #include "google_apis/gaia/gaia_urls.h"
26 #include "google_apis/gaia/google_service_auth_error.h"
28 using base::DictionaryValue;
32 ManagedUserRegistrationUtility* g_instance_for_tests = NULL;
34 // Actual implementation of ManagedUserRegistrationUtility.
35 class ManagedUserRegistrationUtilityImpl
36 : public ManagedUserRegistrationUtility,
37 public ManagedUserSyncServiceObserver {
39 ManagedUserRegistrationUtilityImpl(
41 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
42 ManagedUserSyncService* service);
44 virtual ~ManagedUserRegistrationUtilityImpl();
46 // Registers a new managed user with the server. |managed_user_id| is a new
47 // unique ID for the new managed user. If its value is the same as that of
48 // of one of the existing managed users, then the same user will be created
49 // on this machine (and if he has no avatar in sync, his avatar will
50 // be updated). |info| contains necessary information like
51 // the display name of the user and his avatar. |callback| is called
52 // with the result of the registration. We use the info here and not the
53 // profile, because on Chrome OS the profile of the managed user does not
55 virtual void Register(const std::string& managed_user_id,
56 const ManagedUserRegistrationInfo& info,
57 const RegistrationCallback& callback) OVERRIDE;
59 // ManagedUserSyncServiceObserver:
60 virtual void OnManagedUserAcknowledged(const std::string& managed_user_id)
62 virtual void OnManagedUsersSyncingStopped() OVERRIDE;
65 // Fetches the managed user token when we have the device name.
66 void FetchToken(const std::string& client_name);
68 // Called when we have received a token for the managed user.
69 void OnReceivedToken(const GoogleServiceAuthError& error,
70 const std::string& token);
72 // Dispatches the callback and cleans up if all the conditions have been met.
73 void CompleteRegistrationIfReady();
75 // Aborts any registration currently in progress. If |run_callback| is true,
76 // calls the callback specified in Register() with the given |error|.
77 void AbortPendingRegistration(bool run_callback,
78 const GoogleServiceAuthError& error);
80 // If |run_callback| is true, dispatches the callback with the saved token
81 // (which may be empty) and the given |error|. In any case, resets internal
82 // variables to be ready for the next registration.
83 void CompleteRegistration(bool run_callback,
84 const GoogleServiceAuthError& error);
86 // Cancels any registration currently in progress, without calling the
87 // callback or reporting an error.
88 void CancelPendingRegistration();
90 base::WeakPtrFactory<ManagedUserRegistrationUtilityImpl> weak_ptr_factory_;
92 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher_;
94 // A |BrowserContextKeyedService| owned by the custodian profile.
95 ManagedUserSyncService* managed_user_sync_service_;
97 std::string pending_managed_user_id_;
98 std::string pending_managed_user_token_;
99 bool pending_managed_user_acknowledged_;
100 bool is_existing_managed_user_;
101 bool avatar_updated_;
102 RegistrationCallback callback_;
104 DISALLOW_COPY_AND_ASSIGN(ManagedUserRegistrationUtilityImpl);
109 ManagedUserRegistrationInfo::ManagedUserRegistrationInfo(const string16& name,
111 : avatar_index(avatar_index),
115 ScopedTestingManagedUserRegistrationUtility::
116 ScopedTestingManagedUserRegistrationUtility(
117 ManagedUserRegistrationUtility* instance) {
118 ManagedUserRegistrationUtility::SetUtilityForTests(instance);
121 ScopedTestingManagedUserRegistrationUtility::
122 ~ScopedTestingManagedUserRegistrationUtility() {
123 ManagedUserRegistrationUtility::SetUtilityForTests(NULL);
127 scoped_ptr<ManagedUserRegistrationUtility>
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);
135 ProfileOAuth2TokenService* token_service =
136 ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
137 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher =
138 ManagedUserRefreshTokenFetcher::Create(
140 token_service->GetPrimaryAccountId(),
141 profile->GetRequestContext());
142 ManagedUserSyncService* managed_user_sync_service =
143 ManagedUserSyncServiceFactory::GetForProfile(profile);
144 return make_scoped_ptr(ManagedUserRegistrationUtility::CreateImpl(
146 token_fetcher.Pass(),
147 managed_user_sync_service));
151 std::string ManagedUserRegistrationUtility::GenerateNewManagedUserId() {
152 std::string new_managed_user_id;
153 bool success = base::Base64Encode(base::RandBytesAsString(8),
154 &new_managed_user_id);
156 return new_managed_user_id;
160 void ManagedUserRegistrationUtility::SetUtilityForTests(
161 ManagedUserRegistrationUtility* utility) {
162 if (g_instance_for_tests)
163 delete g_instance_for_tests;
164 g_instance_for_tests = utility;
168 ManagedUserRegistrationUtility* ManagedUserRegistrationUtility::CreateImpl(
170 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
171 ManagedUserSyncService* service) {
172 return new ManagedUserRegistrationUtilityImpl(prefs,
173 token_fetcher.Pass(),
179 ManagedUserRegistrationUtilityImpl::ManagedUserRegistrationUtilityImpl(
181 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
182 ManagedUserSyncService* service)
183 : weak_ptr_factory_(this),
185 token_fetcher_(token_fetcher.Pass()),
186 managed_user_sync_service_(service),
187 pending_managed_user_acknowledged_(false),
188 is_existing_managed_user_(false),
189 avatar_updated_(false) {
190 managed_user_sync_service_->AddObserver(this);
193 ManagedUserRegistrationUtilityImpl::~ManagedUserRegistrationUtilityImpl() {
194 managed_user_sync_service_->RemoveObserver(this);
195 CancelPendingRegistration();
198 void ManagedUserRegistrationUtilityImpl::Register(
199 const std::string& managed_user_id,
200 const ManagedUserRegistrationInfo& info,
201 const RegistrationCallback& callback) {
202 DCHECK(pending_managed_user_id_.empty());
203 callback_ = callback;
204 pending_managed_user_id_ = managed_user_id;
206 const DictionaryValue* dict = prefs_->GetDictionary(prefs::kManagedUsers);
207 is_existing_managed_user_ = dict->HasKey(managed_user_id);
208 if (!is_existing_managed_user_) {
209 managed_user_sync_service_->AddManagedUser(pending_managed_user_id_,
210 base::UTF16ToUTF8(info.name),
215 managed_user_sync_service_->UpdateManagedUserAvatarIfNeeded(
219 // User already exists, don't wait for acknowledgment.
220 OnManagedUserAcknowledged(managed_user_id);
223 browser_sync::DeviceInfo::GetClientName(
224 base::Bind(&ManagedUserRegistrationUtilityImpl::FetchToken,
225 weak_ptr_factory_.GetWeakPtr()));
228 void ManagedUserRegistrationUtilityImpl::CancelPendingRegistration() {
229 AbortPendingRegistration(
230 false, // Don't run the callback. The error will be ignored.
231 GoogleServiceAuthError(GoogleServiceAuthError::NONE));
234 void ManagedUserRegistrationUtilityImpl::OnManagedUserAcknowledged(
235 const std::string& managed_user_id) {
236 DCHECK_EQ(pending_managed_user_id_, managed_user_id);
237 DCHECK(!pending_managed_user_acknowledged_);
238 pending_managed_user_acknowledged_ = true;
239 CompleteRegistrationIfReady();
242 void ManagedUserRegistrationUtilityImpl::OnManagedUsersSyncingStopped() {
243 AbortPendingRegistration(
244 true, // Run the callback.
245 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
248 void ManagedUserRegistrationUtilityImpl::FetchToken(
249 const std::string& client_name) {
250 token_fetcher_->Start(
251 pending_managed_user_id_, client_name,
252 base::Bind(&ManagedUserRegistrationUtilityImpl::OnReceivedToken,
253 weak_ptr_factory_.GetWeakPtr()));
256 void ManagedUserRegistrationUtilityImpl::OnReceivedToken(
257 const GoogleServiceAuthError& error,
258 const std::string& token) {
259 if (error.state() != GoogleServiceAuthError::NONE) {
260 CompleteRegistration(true, error);
264 DCHECK(!token.empty());
265 pending_managed_user_token_ = token;
266 CompleteRegistrationIfReady();
269 void ManagedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
270 bool require_acknowledgment =
271 !pending_managed_user_acknowledged_ &&
272 !CommandLine::ForCurrentProcess()->HasSwitch(
273 switches::kNoManagedUserAcknowledgmentCheck);
274 if (require_acknowledgment || pending_managed_user_token_.empty())
277 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
278 CompleteRegistration(true, error);
281 void ManagedUserRegistrationUtilityImpl::AbortPendingRegistration(
283 const GoogleServiceAuthError& error) {
284 pending_managed_user_token_.clear();
285 CompleteRegistration(run_callback, error);
288 void ManagedUserRegistrationUtilityImpl::CompleteRegistration(
290 const GoogleServiceAuthError& error) {
291 if (callback_.is_null())
294 if (pending_managed_user_token_.empty()) {
295 DCHECK(!pending_managed_user_id_.empty());
297 if (!is_existing_managed_user_) {
298 // Remove the pending managed user if we weren't successful.
299 // However, check that we are not importing a managed user
300 // before deleting it from sync to avoid accidental deletion of
301 // existing managed users by just canceling the registration for example.
302 managed_user_sync_service_->DeleteManagedUser(pending_managed_user_id_);
303 } else if (avatar_updated_) {
304 // Canceling (or failing) a managed user import that did set the avatar
305 // should undo this change.
306 managed_user_sync_service_->ClearManagedUserAvatar(
307 pending_managed_user_id_);
312 callback_.Run(error, pending_managed_user_token_);