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/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"
26 using base::DictionaryValue
;
30 ManagedUserRegistrationUtility
* g_instance_for_tests
= NULL
;
32 // Actual implementation of ManagedUserRegistrationUtility.
33 class ManagedUserRegistrationUtilityImpl
34 : public ManagedUserRegistrationUtility
,
35 public ManagedUserSyncServiceObserver
{
37 ManagedUserRegistrationUtilityImpl(
39 scoped_ptr
<ManagedUserRefreshTokenFetcher
> token_fetcher
,
40 ManagedUserSyncService
* service
);
42 virtual ~ManagedUserRegistrationUtilityImpl();
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
53 virtual void Register(const std::string
& managed_user_id
,
54 const ManagedUserRegistrationInfo
& info
,
55 const RegistrationCallback
& callback
) OVERRIDE
;
57 // ManagedUserSyncServiceObserver:
58 virtual void OnManagedUserAcknowledged(const std::string
& managed_user_id
)
60 virtual void OnManagedUsersSyncingStopped() OVERRIDE
;
63 // Fetches the managed user token when we have the device name.
64 void FetchToken(const std::string
& client_name
);
66 // Called when we have received a token for the managed user.
67 void OnReceivedToken(const GoogleServiceAuthError
& error
,
68 const std::string
& token
);
70 // Dispatches the callback and cleans up if all the conditions have been met.
71 void CompleteRegistrationIfReady();
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
);
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
);
84 // Cancels any registration currently in progress, without calling the
85 // callback or reporting an error.
86 void CancelPendingRegistration();
89 scoped_ptr
<ManagedUserRefreshTokenFetcher
> token_fetcher_
;
91 // A |BrowserContextKeyedService| owned by the custodian profile.
92 ManagedUserSyncService
* managed_user_sync_service_
;
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_
;
99 RegistrationCallback callback_
;
101 base::WeakPtrFactory
<ManagedUserRegistrationUtilityImpl
> weak_ptr_factory_
;
103 DISALLOW_COPY_AND_ASSIGN(ManagedUserRegistrationUtilityImpl
);
108 ManagedUserRegistrationInfo::ManagedUserRegistrationInfo(
109 const base::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 base::Base64Encode(base::RandBytesAsString(8), &new_managed_user_id
);
154 return new_managed_user_id
;
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
;
166 ManagedUserRegistrationUtility
* ManagedUserRegistrationUtility::CreateImpl(
168 scoped_ptr
<ManagedUserRefreshTokenFetcher
> token_fetcher
,
169 ManagedUserSyncService
* service
) {
170 return new ManagedUserRegistrationUtilityImpl(prefs
,
171 token_fetcher
.Pass(),
177 ManagedUserRegistrationUtilityImpl::ManagedUserRegistrationUtilityImpl(
179 scoped_ptr
<ManagedUserRefreshTokenFetcher
> token_fetcher
,
180 ManagedUserSyncService
* service
)
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);
191 ManagedUserRegistrationUtilityImpl::~ManagedUserRegistrationUtilityImpl() {
192 managed_user_sync_service_
->RemoveObserver(this);
193 CancelPendingRegistration();
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
;
204 const base::DictionaryValue
* dict
=
205 prefs_
->GetDictionary(prefs::kManagedUsers
);
206 is_existing_managed_user_
= dict
->HasKey(managed_user_id
);
207 if (!is_existing_managed_user_
) {
208 managed_user_sync_service_
->AddManagedUser(pending_managed_user_id_
,
209 base::UTF16ToUTF8(info
.name
),
214 managed_user_sync_service_
->UpdateManagedUserAvatarIfNeeded(
218 // User already exists, don't wait for acknowledgment.
219 OnManagedUserAcknowledged(managed_user_id
);
222 browser_sync::DeviceInfo::GetClientName(
223 base::Bind(&ManagedUserRegistrationUtilityImpl::FetchToken
,
224 weak_ptr_factory_
.GetWeakPtr()));
227 void ManagedUserRegistrationUtilityImpl::CancelPendingRegistration() {
228 AbortPendingRegistration(
229 false, // Don't run the callback. The error will be ignored.
230 GoogleServiceAuthError(GoogleServiceAuthError::NONE
));
233 void ManagedUserRegistrationUtilityImpl::OnManagedUserAcknowledged(
234 const std::string
& managed_user_id
) {
235 DCHECK_EQ(pending_managed_user_id_
, managed_user_id
);
236 DCHECK(!pending_managed_user_acknowledged_
);
237 pending_managed_user_acknowledged_
= true;
238 CompleteRegistrationIfReady();
241 void ManagedUserRegistrationUtilityImpl::OnManagedUsersSyncingStopped() {
242 AbortPendingRegistration(
243 true, // Run the callback.
244 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED
));
247 void ManagedUserRegistrationUtilityImpl::FetchToken(
248 const std::string
& client_name
) {
249 token_fetcher_
->Start(
250 pending_managed_user_id_
, client_name
,
251 base::Bind(&ManagedUserRegistrationUtilityImpl::OnReceivedToken
,
252 weak_ptr_factory_
.GetWeakPtr()));
255 void ManagedUserRegistrationUtilityImpl::OnReceivedToken(
256 const GoogleServiceAuthError
& error
,
257 const std::string
& token
) {
258 if (error
.state() != GoogleServiceAuthError::NONE
) {
259 CompleteRegistration(true, error
);
263 DCHECK(!token
.empty());
264 pending_managed_user_token_
= token
;
265 CompleteRegistrationIfReady();
268 void ManagedUserRegistrationUtilityImpl::CompleteRegistrationIfReady() {
269 bool require_acknowledgment
=
270 !pending_managed_user_acknowledged_
&&
271 !CommandLine::ForCurrentProcess()->HasSwitch(
272 switches::kNoManagedUserAcknowledgmentCheck
);
273 if (require_acknowledgment
|| pending_managed_user_token_
.empty())
276 GoogleServiceAuthError
error(GoogleServiceAuthError::NONE
);
277 CompleteRegistration(true, error
);
280 void ManagedUserRegistrationUtilityImpl::AbortPendingRegistration(
282 const GoogleServiceAuthError
& error
) {
283 pending_managed_user_token_
.clear();
284 CompleteRegistration(run_callback
, error
);
287 void ManagedUserRegistrationUtilityImpl::CompleteRegistration(
289 const GoogleServiceAuthError
& error
) {
290 if (callback_
.is_null())
293 if (pending_managed_user_token_
.empty()) {
294 DCHECK(!pending_managed_user_id_
.empty());
296 if (!is_existing_managed_user_
) {
297 // Remove the pending managed user if we weren't successful.
298 // However, check that we are not importing a managed user
299 // before deleting it from sync to avoid accidental deletion of
300 // existing managed users by just canceling the registration for example.
301 managed_user_sync_service_
->DeleteManagedUser(pending_managed_user_id_
);
302 } else if (avatar_updated_
) {
303 // Canceling (or failing) a managed user import that did set the avatar
304 // should undo this change.
305 managed_user_sync_service_
->ClearManagedUserAvatar(
306 pending_managed_user_id_
);
311 callback_
.Run(error
, pending_managed_user_token_
);