- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / managed_mode / managed_user_registration_utility.cc
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/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"
27
28 using base::DictionaryValue;
29
30 namespace {
31
32 ManagedUserRegistrationUtility* g_instance_for_tests = NULL;
33
34 // Actual implementation of ManagedUserRegistrationUtility.
35 class ManagedUserRegistrationUtilityImpl
36     : public ManagedUserRegistrationUtility,
37       public ManagedUserSyncServiceObserver {
38  public:
39   ManagedUserRegistrationUtilityImpl(
40       PrefService* prefs,
41       scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
42       ManagedUserSyncService* service);
43
44   virtual ~ManagedUserRegistrationUtilityImpl();
45
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
54   // yet exist.
55   virtual void Register(const std::string& managed_user_id,
56                         const ManagedUserRegistrationInfo& info,
57                         const RegistrationCallback& callback) OVERRIDE;
58
59   // ManagedUserSyncServiceObserver:
60   virtual void OnManagedUserAcknowledged(const std::string& managed_user_id)
61       OVERRIDE;
62   virtual void OnManagedUsersSyncingStopped() OVERRIDE;
63
64  private:
65   // Fetches the managed user token when we have the device name.
66   void FetchToken(const std::string& client_name);
67
68   // Called when we have received a token for the managed user.
69   void OnReceivedToken(const GoogleServiceAuthError& error,
70                        const std::string& token);
71
72   // Dispatches the callback and cleans up if all the conditions have been met.
73   void CompleteRegistrationIfReady();
74
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);
79
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);
85
86   // Cancels any registration currently in progress, without calling the
87   // callback or reporting an error.
88   void CancelPendingRegistration();
89
90   base::WeakPtrFactory<ManagedUserRegistrationUtilityImpl> weak_ptr_factory_;
91   PrefService* prefs_;
92   scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher_;
93
94   // A |BrowserContextKeyedService| owned by the custodian profile.
95   ManagedUserSyncService* managed_user_sync_service_;
96
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_;
103
104   DISALLOW_COPY_AND_ASSIGN(ManagedUserRegistrationUtilityImpl);
105 };
106
107 } // namespace
108
109 ManagedUserRegistrationInfo::ManagedUserRegistrationInfo(const string16& name,
110                                                          int avatar_index)
111     : avatar_index(avatar_index),
112       name(name) {
113 }
114
115 ScopedTestingManagedUserRegistrationUtility::
116     ScopedTestingManagedUserRegistrationUtility(
117         ManagedUserRegistrationUtility* instance) {
118   ManagedUserRegistrationUtility::SetUtilityForTests(instance);
119 }
120
121 ScopedTestingManagedUserRegistrationUtility::
122     ~ScopedTestingManagedUserRegistrationUtility() {
123   ManagedUserRegistrationUtility::SetUtilityForTests(NULL);
124 }
125
126 // static
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);
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
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);
155   DCHECK(success);
156   return new_managed_user_id;
157 }
158
159 // static
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;
165 }
166
167 // static
168 ManagedUserRegistrationUtility* ManagedUserRegistrationUtility::CreateImpl(
169       PrefService* prefs,
170       scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
171       ManagedUserSyncService* service) {
172   return new ManagedUserRegistrationUtilityImpl(prefs,
173                                                 token_fetcher.Pass(),
174                                                 service);
175 }
176
177 namespace {
178
179 ManagedUserRegistrationUtilityImpl::ManagedUserRegistrationUtilityImpl(
180     PrefService* prefs,
181     scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher,
182     ManagedUserSyncService* service)
183     : weak_ptr_factory_(this),
184       prefs_(prefs),
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);
191 }
192
193 ManagedUserRegistrationUtilityImpl::~ManagedUserRegistrationUtilityImpl() {
194   managed_user_sync_service_->RemoveObserver(this);
195   CancelPendingRegistration();
196 }
197
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;
205
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),
211                                                info.master_key,
212                                                info.avatar_index);
213   } else {
214     avatar_updated_ =
215         managed_user_sync_service_->UpdateManagedUserAvatarIfNeeded(
216             managed_user_id,
217             info.avatar_index);
218
219     // User already exists, don't wait for acknowledgment.
220     OnManagedUserAcknowledged(managed_user_id);
221   }
222
223   browser_sync::DeviceInfo::GetClientName(
224       base::Bind(&ManagedUserRegistrationUtilityImpl::FetchToken,
225                  weak_ptr_factory_.GetWeakPtr()));
226 }
227
228 void ManagedUserRegistrationUtilityImpl::CancelPendingRegistration() {
229   AbortPendingRegistration(
230       false,  // Don't run the callback. The error will be ignored.
231       GoogleServiceAuthError(GoogleServiceAuthError::NONE));
232 }
233
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();
240 }
241
242 void ManagedUserRegistrationUtilityImpl::OnManagedUsersSyncingStopped() {
243   AbortPendingRegistration(
244       true,  // Run the callback.
245       GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
246 }
247
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()));
254 }
255
256 void ManagedUserRegistrationUtilityImpl::OnReceivedToken(
257     const GoogleServiceAuthError& error,
258     const std::string& token) {
259   if (error.state() != GoogleServiceAuthError::NONE) {
260     CompleteRegistration(true, error);
261     return;
262   }
263
264   DCHECK(!token.empty());
265   pending_managed_user_token_ = token;
266   CompleteRegistrationIfReady();
267 }
268
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())
275     return;
276
277   GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
278   CompleteRegistration(true, error);
279 }
280
281 void ManagedUserRegistrationUtilityImpl::AbortPendingRegistration(
282     bool run_callback,
283     const GoogleServiceAuthError& error) {
284   pending_managed_user_token_.clear();
285   CompleteRegistration(run_callback, error);
286 }
287
288 void ManagedUserRegistrationUtilityImpl::CompleteRegistration(
289     bool run_callback,
290     const GoogleServiceAuthError& error) {
291   if (callback_.is_null())
292     return;
293
294   if (pending_managed_user_token_.empty()) {
295     DCHECK(!pending_managed_user_id_.empty());
296
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_);
308     }
309   }
310
311   if (run_callback)
312     callback_.Run(error, pending_managed_user_token_);
313   callback_.Reset();
314 }
315
316 } // namespace