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

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: Fix unsigned check in tests again 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();
146 } 208 }
209
210 // static
211 std::vector<std::string> AccountReconcilor::ParseListAccountsData(
212 const std::string& data) {
213 std::vector<std::string> account_ids;
214
215 // Parse returned data and make sure we have data.
216 scoped_ptr<base::Value> value(base::JSONReader::Read(data));
217 if (!value)
218 return account_ids;
219
220 base::ListValue* list;
221 if (!value->GetAsList(&list) || list->GetSize() < 2)
222 return account_ids;
223
224 // Get list of account info.
225 base::ListValue* accounts;
226 if (!list->GetList(1, &accounts) || 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 if (accounts->GetList(i, &account) && account != NULL) {
234 std::string email;
235 if (account->GetString(3, &email) && !email.empty())
236 account_ids.push_back(email);
237 }
238 }
239
240 return account_ids;
241 }
242
243 void AccountReconcilor::OnListAccountsFailure(
244 const GoogleServiceAuthError& error) {
245 gaia_fetcher_.reset();
246 DVLOG(1) << "AccountReconcilor::OnListAccountsFailure: " << error.ToString();
247
248 are_gaia_accounts_set_ = true;
249 FinishReconcileAction();
250 }
251
252 void AccountReconcilor::ValidateAccountsFromTokenService() {
253 primary_account_ =
254 SigninManagerFactory::GetForProfile(profile_)->GetAuthenticatedUsername();
255 DCHECK(!primary_account_.empty());
256
257 ProfileOAuth2TokenService* token_service =
258 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
259 chrome_accounts_ = token_service->GetAccounts();
260 DCHECK(chrome_accounts_.size() > 0);
261
262 DVLOG(1) << "AccountReconcilor::ValidateAccountsFromTokenService: "
263 << "Chrome " << chrome_accounts_.size() << " accounts, "
264 << "Primary is '" << primary_account_ << "'";
265
266 DCHECK(!requests_);
267 requests_ =
268 new scoped_ptr<OAuth2TokenService::Request>[chrome_accounts_.size()];
269 for (size_t i = 0; i < chrome_accounts_.size(); ++i) {
270 requests_[i] = token_service->StartRequest(chrome_accounts_[i],
271 OAuth2TokenService::ScopeSet(),
272 this);
273 }
274 }
275
276 void AccountReconcilor::OnGetTokenSuccess(
277 const OAuth2TokenService::Request* request,
278 const std::string& access_token,
279 const base::Time& expiration_time) {
280 DVLOG(1) << "AccountReconcilor::OnGetTokenSuccess: valid "
281 << request->GetAccountId();
282 valid_chrome_accounts_.insert(request->GetAccountId());
283 FinishReconcileAction();
284 }
285
286 void AccountReconcilor::OnGetTokenFailure(
287 const OAuth2TokenService::Request* request,
288 const GoogleServiceAuthError& error) {
289 DVLOG(1) << "AccountReconcilor::OnGetTokenSuccess: invalid "
290 << request->GetAccountId();
291 invalid_chrome_accounts_.insert(request->GetAccountId());
292 FinishReconcileAction();
293 }
294
295 void AccountReconcilor::FinishReconcileAction() {
296 // Make sure that the process of validating the gaia cookie and the oauth2
297 // tokens individually is done before proceeding with reconciliation.
298 if (!are_gaia_accounts_set_ ||
299 (chrome_accounts_.size() != (valid_chrome_accounts_.size() +
300 invalid_chrome_accounts_.size()))) {
301 return;
302 }
303
304 DVLOG(1) << "AccountReconcilor::FinishReconcileAction";
305
306 bool are_primaries_equal =
307 gaia_accounts_.size() > 0 && primary_account_ == gaia_accounts_[0];
308 bool have_same_accounts = chrome_accounts_.size() == gaia_accounts_.size();
309 if (have_same_accounts) {
310 for (size_t i = 0; i < gaia_accounts_.size(); ++i) {
311 if (std::find(chrome_accounts_.begin(), chrome_accounts_.end(),
312 gaia_accounts_[i]) == chrome_accounts_.end()) {
313 have_same_accounts = false;
314 break;
315 }
316 }
317 }
318
319 if (!are_primaries_equal || !have_same_accounts) {
320 // TODO(rogerta): fix things up.
321 }
322 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698