Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: chrome/browser/signin/account_reconcilor.cc

Issue 57363003: Enable account reconcilor when --new-profile-management is used. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use helper function for new profile management Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/json/json_reader.h"
5 #include "base/logging.h" 6 #include "base/logging.h"
6 #include "base/time/time.h" 7 #include "base/time/time.h"
7 #include "chrome/browser/chrome_notification_types.h" 8 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/net/chrome_cookie_notification_details.h" 9 #include "chrome/browser/net/chrome_cookie_notification_details.h"
9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/signin/account_reconcilor.h" 11 #include "chrome/browser/signin/account_reconcilor.h"
11 #include "chrome/browser/signin/google_auto_login_helper.h" 12 #include "chrome/browser/signin/google_auto_login_helper.h"
12 #include "chrome/browser/signin/profile_oauth2_token_service.h" 13 #include "chrome/browser/signin/profile_oauth2_token_service.h"
13 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
14 #include "chrome/browser/signin/signin_manager.h" 15 #include "chrome/browser/signin/signin_manager.h"
15 #include "chrome/browser/signin/signin_manager_factory.h" 16 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/notification_details.h" 18 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_source.h" 19 #include "content/public/browser/notification_source.h"
20 #include "google_apis/gaia/gaia_auth_fetcher.h"
21 #include "google_apis/gaia/gaia_constants.h"
19 22
20 AccountReconcilor::AccountReconcilor(Profile* profile) : profile_(profile) { 23 AccountReconcilor::AccountReconcilor(Profile* profile)
24 : profile_(profile),
25 are_gaia_accounts_set_(false),
26 requests_(NULL) {
21 RegisterWithSigninManager(); 27 RegisterWithSigninManager();
22 RegisterWithCookieMonster(); 28 RegisterWithCookieMonster();
23 29
24 // If this profile is not connected, the reconcilor should do nothing but 30 // If this profile is not connected, the reconcilor should do nothing but
25 // wait for the connection. 31 // wait for the connection.
26 SigninManagerBase* signin_manager = 32 if (IsProfileConnected()) {
27 SigninManagerFactory::GetForProfile(profile_);
28 if (!signin_manager->GetAuthenticatedUsername().empty()) {
29 RegisterWithTokenService(); 33 RegisterWithTokenService();
30 StartPeriodicReconciliation(); 34 StartPeriodicReconciliation();
31 } 35 }
32 } 36 }
33 37
38 AccountReconcilor::~AccountReconcilor() {
39 // Make sure shutdown was called first.
40 DCHECK(registrar_.IsEmpty());
41 DCHECK(!reconciliation_timer_.IsRunning());
42 DCHECK(!requests_);
43 }
44
45 void AccountReconcilor::Shutdown() {
46 DVLOG(1) << "AccountReconcilor::Shutdown";
47 DeleteAccessTokenRequests();
48 UnregisterWithSigninManager();
49 UnregisterWithTokenService();
50 UnregisterWithCookieMonster();
51 StopPeriodicReconciliation();
52 }
53
54 void AccountReconcilor::DeleteAccessTokenRequests() {
55 delete[] requests_;
56 requests_ = NULL;
57 }
58
34 void AccountReconcilor::RegisterWithCookieMonster() { 59 void AccountReconcilor::RegisterWithCookieMonster() {
35 content::Source<Profile> source(profile_); 60 content::Source<Profile> source(profile_);
36 registrar_.Add(this, chrome::NOTIFICATION_COOKIE_CHANGED, source); 61 registrar_.Add(this, chrome::NOTIFICATION_COOKIE_CHANGED, source);
37 } 62 }
38 63
39 void AccountReconcilor::UnregisterWithCookieMonster() { 64 void AccountReconcilor::UnregisterWithCookieMonster() {
40 content::Source<Profile> source(profile_); 65 content::Source<Profile> source(profile_);
41 registrar_.Remove(this, chrome::NOTIFICATION_COOKIE_CHANGED, source); 66 registrar_.Remove(this, chrome::NOTIFICATION_COOKIE_CHANGED, source);
42 } 67 }
43 68
(...skipping 15 matching lines...) Expand all
59 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 84 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
60 token_service->AddObserver(this); 85 token_service->AddObserver(this);
61 } 86 }
62 87
63 void AccountReconcilor::UnregisterWithTokenService() { 88 void AccountReconcilor::UnregisterWithTokenService() {
64 ProfileOAuth2TokenService* token_service = 89 ProfileOAuth2TokenService* token_service =
65 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 90 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
66 token_service->RemoveObserver(this); 91 token_service->RemoveObserver(this);
67 } 92 }
68 93
94 bool AccountReconcilor::IsProfileConnected() {
95 return !SigninManagerFactory::GetForProfile(profile_)->
96 GetAuthenticatedUsername().empty();
97 }
98
69 void AccountReconcilor::StartPeriodicReconciliation() { 99 void AccountReconcilor::StartPeriodicReconciliation() {
100 DVLOG(1) << "AccountReconcilor::StartPeriodicReconciliation";
70 // TODO(rogerta): pick appropriate thread and timeout value. 101 // TODO(rogerta): pick appropriate thread and timeout value.
71 reconciliation_timer_.Start( 102 reconciliation_timer_.Start(
72 FROM_HERE, 103 FROM_HERE,
73 base::TimeDelta::FromMinutes(5), 104 base::TimeDelta::FromSeconds(300),
74 this, 105 this,
75 &AccountReconcilor::PeriodicReconciliation); 106 &AccountReconcilor::PeriodicReconciliation);
76 } 107 }
77 108
78 void AccountReconcilor::StopPeriodicReconciliation() { 109 void AccountReconcilor::StopPeriodicReconciliation() {
110 DVLOG(1) << "AccountReconcilor::StopPeriodicReconciliation";
79 reconciliation_timer_.Stop(); 111 reconciliation_timer_.Stop();
80 } 112 }
81 113
82 void AccountReconcilor::PeriodicReconciliation() { 114 void AccountReconcilor::PeriodicReconciliation() {
83 PerformReconcileAction(); 115 DVLOG(1) << "AccountReconcilor::PeriodicReconciliation";
116 StartReconcileAction();
84 } 117 }
85 118
86 void AccountReconcilor::Observe(int type, 119 void AccountReconcilor::Observe(int type,
87 const content::NotificationSource& source, 120 const content::NotificationSource& source,
88 const content::NotificationDetails& details) { 121 const content::NotificationDetails& details) {
89 switch (type) { 122 switch (type) {
90 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: 123 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL:
124 DVLOG(1) << "AccountReconcilor::Observe: signed in";
91 RegisterWithTokenService(); 125 RegisterWithTokenService();
92 StartPeriodicReconciliation(); 126 StartPeriodicReconciliation();
93 break; 127 break;
94 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: 128 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
129 DVLOG(1) << "AccountReconcilor::Observe: signed out";
95 UnregisterWithTokenService(); 130 UnregisterWithTokenService();
96 StopPeriodicReconciliation(); 131 StopPeriodicReconciliation();
97 break; 132 break;
98 case chrome::NOTIFICATION_COOKIE_CHANGED: 133 case chrome::NOTIFICATION_COOKIE_CHANGED:
99 OnCookieChanged(content::Details<ChromeCookieDetails>(details).ptr()); 134 OnCookieChanged(content::Details<ChromeCookieDetails>(details).ptr());
100 break; 135 break;
101 default: 136 default:
102 NOTREACHED(); 137 NOTREACHED();
103 break; 138 break;
104 } 139 }
105 } 140 }
106 141
107 void AccountReconcilor::OnCookieChanged(ChromeCookieDetails* details) { 142 void AccountReconcilor::OnCookieChanged(ChromeCookieDetails* details) {
108 // TODO(acleung): Filter out cookies by looking at the domain. 143 // TODO(acleung): Filter out cookies by looking at the domain.
109 // PerformReconcileAction(); 144 // StartReconcileAction();
110 } 145 }
111 146
112 void AccountReconcilor::OnRefreshTokenAvailable(const std::string& account_id) { 147 void AccountReconcilor::OnRefreshTokenAvailable(const std::string& account_id) {
148 DVLOG(1) << "AccountReconcilor::OnRefreshTokenAvailable: " << account_id;
113 PerformMergeAction(account_id); 149 PerformMergeAction(account_id);
114 } 150 }
115 151
116 void AccountReconcilor::OnRefreshTokenRevoked(const std::string& account_id) { 152 void AccountReconcilor::OnRefreshTokenRevoked(const std::string& account_id) {
153 DVLOG(1) << "AccountReconcilor::OnRefreshTokenRevoked: " << account_id;
117 PerformRemoveAction(account_id); 154 PerformRemoveAction(account_id);
118 } 155 }
119 156
120 void AccountReconcilor::OnRefreshTokensLoaded() {} 157 void AccountReconcilor::OnRefreshTokensLoaded() {}
121 158
122 void AccountReconcilor::PerformMergeAction(const std::string& account_id) { 159 void AccountReconcilor::PerformMergeAction(const std::string& account_id) {
123 // GoogleAutoLoginHelper deletes itself upon success / failure. 160 // GoogleAutoLoginHelper deletes itself upon success / failure.
124 GoogleAutoLoginHelper* helper = new GoogleAutoLoginHelper(profile_); 161 GoogleAutoLoginHelper* helper = new GoogleAutoLoginHelper(profile_);
125 helper->LogIn(account_id); 162 helper->LogIn(account_id);
126 } 163 }
127 164
128 void AccountReconcilor::PerformRemoveAction(const std::string& account_id) { 165 void AccountReconcilor::PerformRemoveAction(const std::string& account_id) {
129 // TODO(acleung): Implement this: 166 // TODO(acleung): Implement this:
130 } 167 }
131 168
132 void AccountReconcilor::PerformReconcileAction() { 169 void AccountReconcilor::StartReconcileAction() {
133 // TODO(acleung): Implement this: 170 if (!IsProfileConnected())
171 return;
172
173 // Reset state for validating gaia cookie.
174 are_gaia_accounts_set_ = false;
175 gaia_accounts_.clear();
176 GetAccountsFromCookie();
177
178 // Reset state for validating oauth2 tokens.
179 primary_account_.clear();
180 chrome_accounts_.clear();
181 DeleteAccessTokenRequests();
182 valid_chrome_accounts_.clear();
183 invalid_chrome_accounts_.clear();
184 ValidateAccountsFromTokenService();
134 } 185 }
135 186
136 AccountReconcilor::~AccountReconcilor() { 187 void AccountReconcilor::GetAccountsFromCookie() {
137 // Make sure shutdown was called first. 188 gaia_fetcher_.reset(new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
138 DCHECK(registrar_.IsEmpty()); 189 profile_->GetRequestContext()));
190 gaia_fetcher_->StartListAccounts();
139 } 191 }
140 192
141 void AccountReconcilor::Shutdown() { 193 void AccountReconcilor::OnListAccountsSuccess(const std::string& data) {
142 UnregisterWithSigninManager(); 194 gaia_fetcher_.reset();
143 UnregisterWithTokenService(); 195
144 UnregisterWithCookieMonster(); 196 // Get account information from response data.
145 StopPeriodicReconciliation(); 197 gaia_accounts_ = ParseListAccountsData(data);
198 if (gaia_accounts_.size() > 0) {
199 DVLOG(1) << "AccountReconcilor::OnListAccountsSuccess: "
200 << "Gaia " << gaia_accounts_.size() << " accounts, "
201 << "Primary is '" << gaia_accounts_[0] << "'";
202 } else {
203 DVLOG(1) << "AccountReconcilor::OnListAccountsSuccess: No accounts";
204 }
205
206 are_gaia_accounts_set_ = true;
207 FinishReconcileAction();
acleung1 2013/11/05 00:04:28 What if I just want a list of accounts for Perform
Roger Tawa OOO till Jul 10th 2013/11/05 21:33:28 Could you use gaia auth fetcher directly and call
146 } 208 }
209
210 std::vector<std::string> AccountReconcilor::ParseListAccountsData(
211 const std::string& data) {
212 std::vector<std::string> account_ids;
213
214 // Parse returned data and make sure we have data.
215 scoped_ptr<base::Value> value(base::JSONReader::Read(data));
216 if (!value)
217 return account_ids;
218
219 base::ListValue* list;
220 if (!value->GetAsList(&list) || list->GetSize() < 2)
221 return account_ids;
222
223 // Get list of account info.
224 base::ListValue* accounts;
225 list->GetList(1, &accounts);
226 if (accounts == NULL)
227 return account_ids;
228
229 // Build a vector of accounts from the cookie. Order is important: the first
230 // account in the list is the primary account.
231 for (size_t i = 0; i < accounts->GetSize(); ++i) {
232 base::ListValue* account;
233 accounts->GetList(i, &account);
234 if (accounts != NULL) {
235 std::string email;
236 account->GetString(3, &email);
237 if (!email.empty())
238 account_ids.push_back(email);
239 }
240 }
241
242 return account_ids;
243 }
244
245 void AccountReconcilor::OnListAccountsFailure(
246 const GoogleServiceAuthError& error) {
247 gaia_fetcher_.reset();
248 DVLOG(1) << "AccountReconcilor::OnListAccountsFailure: " << error.ToString();
249
250 are_gaia_accounts_set_ = true;
251 FinishReconcileAction();
252 }
253
254 void AccountReconcilor::ValidateAccountsFromTokenService() {
255 primary_account_ =
256 SigninManagerFactory::GetForProfile(profile_)->GetAuthenticatedUsername();
257 DCHECK(!primary_account_.empty());
258
259 ProfileOAuth2TokenService* token_service =
260 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
261 chrome_accounts_ = token_service->GetAccounts();
262 DCHECK(chrome_accounts_.size() > 0);
263
264 DVLOG(1) << "AccountReconcilor::ValidateAccountsFromTokenService: "
265 << "Chrome " << chrome_accounts_.size() << " accounts, "
266 << "Primary is '" << primary_account_ << "'";
267
268 DCHECK(!requests_);
269 requests_ =
270 new scoped_ptr<OAuth2TokenService::Request>[chrome_accounts_.size()];
271 for (size_t i = 0; i < chrome_accounts_.size(); ++i) {
272 requests_[i] = token_service->StartRequest(chrome_accounts_[i],
273 OAuth2TokenService::ScopeSet(),
274 this);
275 }
276 }
277
278 void AccountReconcilor::OnGetTokenSuccess(
279 const OAuth2TokenService::Request* request,
280 const std::string& access_token,
281 const base::Time& expiration_time) {
282 DVLOG(1) << "AccountReconcilor::OnGetTokenSuccess: valid "
283 << request->GetAccountId();
284 valid_chrome_accounts_.insert(request->GetAccountId());
285 FinishReconcileAction();
286 }
287
288 void AccountReconcilor::OnGetTokenFailure(
289 const OAuth2TokenService::Request* request,
290 const GoogleServiceAuthError& error) {
291 DVLOG(1) << "AccountReconcilor::OnGetTokenSuccess: invalid "
292 << request->GetAccountId();
293 invalid_chrome_accounts_.insert(request->GetAccountId());
294 FinishReconcileAction();
295 }
296
297 void AccountReconcilor::FinishReconcileAction() {
298 // Make sure that the process of validating the gaia cookie and the oauth2
299 // tokens individually is done before proceeding with reconciliation.
300 if (!are_gaia_accounts_set_ ||
301 (chrome_accounts_.size() != (valid_chrome_accounts_.size() +
302 invalid_chrome_accounts_.size()))) {
303 return;
304 }
305
306 DVLOG(1) << "AccountReconcilor::FinishReconcileAction";
307
308 bool are_primaries_equal =
309 gaia_accounts_.size() > 0 && primary_account_ == gaia_accounts_[0];
310 bool have_same_accounts = chrome_accounts_.size() == gaia_accounts_.size();
311 if (have_same_accounts) {
312 for (size_t i = 0; i < gaia_accounts_.size(); ++i) {
313 if (std::find(chrome_accounts_.begin(), chrome_accounts_.end(),
314 gaia_accounts_[i]) == chrome_accounts_.end()) {
315 have_same_accounts = false;
316 break;
317 }
318 }
319 }
320
321 if (!are_primaries_equal || !have_same_accounts) {
322 // TODO(rogerta): fix things up.
323 }
324 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698