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

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

Issue 12502017: signin: pull basic SigninManager functionality into new SigninManagerBase class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix override Created 7 years, 8 months 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/signin/signin_manager.h" 5 #include "chrome/browser/signin/signin_manager.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 29 matching lines...) Expand all
40 #include "content/public/browser/notification_service.h" 40 #include "content/public/browser/notification_service.h"
41 #include "content/public/browser/render_process_host.h" 41 #include "content/public/browser/render_process_host.h"
42 #include "google_apis/gaia/gaia_auth_fetcher.h" 42 #include "google_apis/gaia/gaia_auth_fetcher.h"
43 #include "google_apis/gaia/gaia_auth_util.h" 43 #include "google_apis/gaia/gaia_auth_util.h"
44 #include "google_apis/gaia/gaia_constants.h" 44 #include "google_apis/gaia/gaia_constants.h"
45 #include "google_apis/gaia/gaia_urls.h" 45 #include "google_apis/gaia/gaia_urls.h"
46 #include "net/base/escape.h" 46 #include "net/base/escape.h"
47 #include "net/url_request/url_request_context.h" 47 #include "net/url_request/url_request_context.h"
48 #include "third_party/icu/public/i18n/unicode/regex.h" 48 #include "third_party/icu/public/i18n/unicode/regex.h"
49 49
50 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) 50 #if defined(ENABLE_CONFIGURATION_POLICY)
51 #include "chrome/browser/policy/cloud/user_policy_signin_service.h" 51 #include "chrome/browser/policy/cloud/user_policy_signin_service.h"
52 #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h" 52 #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
53 #endif 53 #endif
54 54
55 using namespace signin_internals_util; 55 using namespace signin_internals_util;
56 56
57 using content::BrowserThread; 57 using content::BrowserThread;
58 58
59 namespace { 59 namespace {
60 60
61 const char kGetInfoDisplayEmailKey[] = "displayEmail"; 61 const char kGetInfoDisplayEmailKey[] = "displayEmail";
62 const char kGetInfoEmailKey[] = "email"; 62 const char kGetInfoEmailKey[] = "email";
63 63
64 const char kGoogleAccountsUrl[] = "https://accounts.google.com";
65
66 const int kInvalidProcessId = -1; 64 const int kInvalidProcessId = -1;
67 65
68 const char kChromiumSyncService[] = "service=chromiumsync"; 66 const char kChromiumSyncService[] = "service=chromiumsync";
69 67
70 } // namespace 68 } // namespace
71 69
72 // Under the covers, we use a dummy chrome-extension ID to serve the purposes 70 // Under the covers, we use a dummy chrome-extension ID to serve the purposes
73 // outlined in the .h file comment for this string. 71 // outlined in the .h file comment for this string.
74 const char* SigninManager::kChromeSigninEffectiveSite = 72 const char* SigninManager::kChromeSigninEffectiveSite =
75 "chrome-extension://acfccoigjajmmgbhpfbjnpckhjjegnih"; 73 "chrome-extension://acfccoigjajmmgbhpfbjnpckhjjegnih";
(...skipping 11 matching lines...) Expand all
87 return false; 85 return false;
88 86
89 // Any login UI URLs with signin=chromiumsync should be considered a web 87 // Any login UI URLs with signin=chromiumsync should be considered a web
90 // URL (relies on GAIA keeping the "service=chromiumsync" query string 88 // URL (relies on GAIA keeping the "service=chromiumsync" query string
91 // fragment present even when embedding inside a "continue" parameter). 89 // fragment present even when embedding inside a "continue" parameter).
92 return net::UnescapeURLComponent( 90 return net::UnescapeURLComponent(
93 url.query(), net::UnescapeRule::URL_SPECIAL_CHARS) 91 url.query(), net::UnescapeRule::URL_SPECIAL_CHARS)
94 .find(kChromiumSyncService) != std::string::npos; 92 .find(kChromiumSyncService) != std::string::npos;
95 } 93 }
96 94
97 // static
98 bool SigninManager::AreSigninCookiesAllowed(Profile* profile) {
99 CookieSettings* cookie_settings =
100 CookieSettings::Factory::GetForProfile(profile);
101 return AreSigninCookiesAllowed(cookie_settings);
102 }
103
104 // static
105 bool SigninManager::AreSigninCookiesAllowed(CookieSettings* cookie_settings) {
106 return cookie_settings &&
107 cookie_settings->IsSettingCookieAllowed(GURL(kGoogleAccountsUrl),
108 GURL(kGoogleAccountsUrl));
109 }
110
111 // static
112 bool SigninManager::IsAllowedUsername(const std::string& username,
113 const std::string& policy) {
114 if (policy.empty())
115 return true;
116
117 // Patterns like "*@foo.com" are not accepted by our regex engine (since they
118 // are not valid regular expressions - they should instead be ".*@foo.com").
119 // For convenience, detect these patterns and insert a "." character at the
120 // front.
121 string16 pattern = UTF8ToUTF16(policy);
122 if (pattern[0] == L'*')
123 pattern.insert(pattern.begin(), L'.');
124
125 // See if the username matches the policy-provided pattern.
126 UErrorCode status = U_ZERO_ERROR;
127 const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
128 icu::RegexMatcher matcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status);
129 if (!U_SUCCESS(status)) {
130 LOG(ERROR) << "Invalid login regex: " << pattern << ", status: " << status;
131 // If an invalid pattern is provided, then prohibit *all* logins (better to
132 // break signin than to quietly allow users to sign in).
133 return false;
134 }
135 string16 username16 = UTF8ToUTF16(username);
136 icu::UnicodeString icu_input(username16.data(), username16.length());
137 matcher.reset(icu_input);
138 status = U_ZERO_ERROR;
139 UBool match = matcher.matches(status);
140 DCHECK(U_SUCCESS(status));
141 return !!match; // !! == convert from UBool to bool.
142 }
143
144 SigninManager::SigninManager() 95 SigninManager::SigninManager()
145 : profile_(NULL), 96 : prohibit_signout_(false),
146 prohibit_signout_(false),
147 had_two_factor_error_(false), 97 had_two_factor_error_(false),
148 type_(SIGNIN_TYPE_NONE), 98 type_(SIGNIN_TYPE_NONE),
149 weak_pointer_factory_(this), 99 weak_pointer_factory_(this),
150 signin_process_id_(kInvalidProcessId) { 100 signin_process_id_(kInvalidProcessId) {
151 } 101 }
152 102
153 void SigninManager::SetSigninProcess(int process_id) { 103 void SigninManager::SetSigninProcess(int process_id) {
154 if (process_id == signin_process_id_) 104 if (process_id == signin_process_id_)
155 return; 105 return;
156 DLOG_IF(WARNING, signin_process_id_ != kInvalidProcessId) << 106 DLOG_IF(WARNING, signin_process_id_ != kInvalidProcessId) <<
157 "Replacing in-use signin process."; 107 "Replacing in-use signin process.";
158 signin_process_id_ = process_id; 108 signin_process_id_ = process_id;
159 const content::RenderProcessHost* process = 109 const content::RenderProcessHost* process =
160 content::RenderProcessHost::FromID(process_id); 110 content::RenderProcessHost::FromID(process_id);
161 DCHECK(process); 111 DCHECK(process);
162 registrar_.Add(this, 112 registrar_.Add(this,
163 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 113 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
164 content::Source<content::RenderProcessHost>(process)); 114 content::Source<content::RenderProcessHost>(process));
165 } 115 }
166 116
167 bool SigninManager::IsSigninProcess(int process_id) const { 117 bool SigninManager::IsSigninProcess(int process_id) const {
168 return process_id == signin_process_id_; 118 return process_id == signin_process_id_;
169 } 119 }
170 120
171 bool SigninManager::HasSigninProcess() const { 121 bool SigninManager::HasSigninProcess() const {
172 return signin_process_id_ != kInvalidProcessId; 122 return signin_process_id_ != kInvalidProcessId;
173 } 123 }
174 124
175 SigninManager::~SigninManager() { 125 SigninManager::~SigninManager() {
176 DCHECK(!signin_global_error_.get()) <<
177 "SigninManager::Initialize called but not SigninManager::Shutdown";
178 } 126 }
179 127
180 void SigninManager::Initialize(Profile* profile) { 128 void SigninManager::InitTokenService() {
181 // Should never call Initialize() twice. 129 SigninManagerBase::InitTokenService();
182 DCHECK(!IsInitialized());
183 profile_ = profile;
184 signin_global_error_.reset(new SigninGlobalError(this, profile));
185 GlobalErrorServiceFactory::GetForProfile(profile_)->AddGlobalError(
186 signin_global_error_.get());
187 PrefService* local_state = g_browser_process->local_state();
188 // local_state can be null during unit tests.
189 if (local_state) {
190 local_state_pref_registrar_.Init(local_state);
191 local_state_pref_registrar_.Add(
192 prefs::kGoogleServicesUsernamePattern,
193 base::Bind(&SigninManager::OnGoogleServicesUsernamePatternChanged,
194 weak_pointer_factory_.GetWeakPtr()));
195 }
196 signin_allowed_.Init(prefs::kSigninAllowed, profile_->GetPrefs(),
197 base::Bind(&SigninManager::OnSigninAllowedPrefChanged,
198 base::Unretained(this)));
199
200 // If the user is clearing the token service from the command line, then
201 // clear their login info also (not valid to be logged in without any
202 // tokens).
203 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
204 if (cmd_line->HasSwitch(switches::kClearTokenService))
205 profile->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
206
207 std::string user = profile_->GetPrefs()->GetString(
208 prefs::kGoogleServicesUsername);
209 if (!user.empty())
210 SetAuthenticatedUsername(user);
211 // TokenService can be null for unit tests.
212 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 130 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
213 if (token_service) { 131 if (token_service && !GetAuthenticatedUsername().empty())
214 token_service->Initialize(GaiaConstants::kChromeSource, profile_); 132 token_service->LoadTokensFromDB();
215 // ChromeOS will kick off TokenService::LoadTokensFromDB from
216 // OAuthLoginManager once the rest of the Profile is fully initialized.
217 // Starting it from here would cause OAuthLoginManager mismatch the origin
218 // of OAuth2 tokens.
219 #if !defined(OS_CHROMEOS)
220 if (!authenticated_username_.empty()) {
221 token_service->LoadTokensFromDB();
222 }
223 #endif
224 }
225 if ((!user.empty() && !IsAllowedUsername(user)) || !IsSigninAllowed()) {
226 // User is signed in, but the username is invalid - the administrator must
227 // have changed the policy since the last signin, so sign out the user.
228 SignOut();
229 }
230 }
231
232 bool SigninManager::IsInitialized() const {
233 return profile_ != NULL;
234 }
235
236 bool SigninManager::IsAllowedUsername(const std::string& username) const {
237 PrefService* local_state = g_browser_process->local_state();
238 if (!local_state)
239 return true; // In a unit test with no local state - all names are allowed.
240
241 std::string pattern = local_state->GetString(
242 prefs::kGoogleServicesUsernamePattern);
243 return IsAllowedUsername(username, pattern);
244 }
245
246 bool SigninManager::IsSigninAllowed() const {
247 return signin_allowed_.GetValue();
248 }
249
250 // static
251 bool SigninManager::IsSigninAllowedOnIOThread(ProfileIOData* io_data) {
252 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
253 return io_data->signin_allowed()->GetValue();
254 } 133 }
255 134
256 void SigninManager::CleanupNotificationRegistration() { 135 void SigninManager::CleanupNotificationRegistration() {
257 #if !defined(OS_CHROMEOS)
258 content::Source<TokenService> token_service( 136 content::Source<TokenService> token_service(
259 TokenServiceFactory::GetForProfile(profile_)); 137 TokenServiceFactory::GetForProfile(profile_));
260 if (registrar_.IsRegistered(this, 138 if (registrar_.IsRegistered(this,
261 chrome::NOTIFICATION_TOKEN_AVAILABLE, 139 chrome::NOTIFICATION_TOKEN_AVAILABLE,
262 token_service)) { 140 token_service)) {
263 registrar_.Remove(this, 141 registrar_.Remove(this,
264 chrome::NOTIFICATION_TOKEN_AVAILABLE, 142 chrome::NOTIFICATION_TOKEN_AVAILABLE,
265 token_service); 143 token_service);
266 } 144 }
267 #endif
268 }
269
270 const std::string& SigninManager::GetAuthenticatedUsername() const {
271 return authenticated_username_;
272 }
273
274 void SigninManager::SetAuthenticatedUsername(const std::string& username) {
275 if (!authenticated_username_.empty()) {
276 DLOG_IF(ERROR, username != authenticated_username_) <<
277 "Tried to change the authenticated username to something different: " <<
278 "Current: " << authenticated_username_ << ", New: " << username;
279 return;
280 }
281 authenticated_username_ = username;
282 // TODO(tim): We could go further in ensuring kGoogleServicesUsername and
283 // authenticated_username_ are consistent once established (e.g. remove
284 // authenticated_username_ altogether). Bug 107160.
285
286 NotifyDiagnosticsObservers(USERNAME, username);
287
288 // Go ahead and update the last signed in username here as well. Once a
289 // user is signed in the two preferences should match. Doing it here as
290 // opposed to on signin allows us to catch the upgrade scenario.
291 profile_->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername, username);
292 } 145 }
293 146
294 std::string SigninManager::SigninTypeToString( 147 std::string SigninManager::SigninTypeToString(
295 SigninManager::SigninType type) { 148 SigninManager::SigninType type) {
296 switch (type) { 149 switch (type) {
297 case SIGNIN_TYPE_NONE: 150 case SIGNIN_TYPE_NONE:
298 return "No Signin"; 151 return "No Signin";
299 case SIGNIN_TYPE_CLIENT_LOGIN: 152 case SIGNIN_TYPE_CLIENT_LOGIN:
300 return "Client Login"; 153 return "Client Login";
301 case SIGNIN_TYPE_WITH_CREDENTIALS: 154 case SIGNIN_TYPE_WITH_CREDENTIALS:
302 return "Signin with credentials"; 155 return "Signin with credentials";
303 case SIGNIN_TYPE_CLIENT_OAUTH: 156 case SIGNIN_TYPE_CLIENT_OAUTH:
304 return "Client OAuth"; 157 return "Client OAuth";
305 } 158 }
306 159
307 NOTREACHED(); 160 NOTREACHED();
308 return ""; 161 return "";
309 } 162 }
310 163
311
312 bool SigninManager::PrepareForSignin(SigninType type, 164 bool SigninManager::PrepareForSignin(SigninType type,
313 const std::string& username, 165 const std::string& username,
314 const std::string& password) { 166 const std::string& password) {
315 DCHECK(possibly_invalid_username_.empty() || 167 DCHECK(possibly_invalid_username_.empty() ||
316 possibly_invalid_username_ == username); 168 possibly_invalid_username_ == username);
317 DCHECK(!username.empty()); 169 DCHECK(!username.empty());
318 170
319 if (!IsAllowedUsername(username)) { 171 if (!IsAllowedUsername(username)) {
320 // Account is not allowed by admin policy. 172 // Account is not allowed by admin policy.
321 HandleAuthError(GoogleServiceAuthError( 173 HandleAuthError(GoogleServiceAuthError(
(...skipping 17 matching lines...) Expand all
339 191
340 NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type)); 192 NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type));
341 return true; 193 return true;
342 } 194 }
343 195
344 // Users must always sign out before they sign in again. 196 // Users must always sign out before they sign in again.
345 void SigninManager::StartSignIn(const std::string& username, 197 void SigninManager::StartSignIn(const std::string& username,
346 const std::string& password, 198 const std::string& password,
347 const std::string& login_token, 199 const std::string& login_token,
348 const std::string& login_captcha) { 200 const std::string& login_captcha) {
349 DCHECK(authenticated_username_.empty() || 201 DCHECK(GetAuthenticatedUsername().empty() ||
350 gaia::AreEmailsSame(username, authenticated_username_)); 202 gaia::AreEmailsSame(username, GetAuthenticatedUsername()));
351 203
352 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_LOGIN, username, password)) 204 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_LOGIN, username, password))
353 return; 205 return;
354 206
355 client_login_->StartClientLogin(username, 207 client_login_->StartClientLogin(username,
356 password, 208 password,
357 "", 209 "",
358 login_token, 210 login_token,
359 login_captcha, 211 login_captcha,
360 GaiaAuthFetcher::HostedAccountsNotAllowed); 212 GaiaAuthFetcher::HostedAccountsNotAllowed);
361 213
362 // Register for token availability. The signin manager will pre-login the 214 // Register for token availability. The signin manager will pre-login the
363 // user when the GAIA service token is ready for use. Only do this if we 215 // user when the GAIA service token is ready for use.
364 // are not running in ChomiumOS, since it handles pre-login itself, and if
365 // cookies are not disabled for Google accounts.
366 #if !defined(OS_CHROMEOS)
367 if (AreSigninCookiesAllowed(profile_)) { 216 if (AreSigninCookiesAllowed(profile_)) {
368 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 217 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
369 registrar_.Add(this, 218 registrar_.Add(this,
370 chrome::NOTIFICATION_TOKEN_AVAILABLE, 219 chrome::NOTIFICATION_TOKEN_AVAILABLE,
371 content::Source<TokenService>(token_service)); 220 content::Source<TokenService>(token_service));
372 } 221 }
373 #endif
374 } 222 }
375 223
376 void SigninManager::ProvideSecondFactorAccessCode( 224 void SigninManager::ProvideSecondFactorAccessCode(
377 const std::string& access_code) { 225 const std::string& access_code) {
378 DCHECK(!possibly_invalid_username_.empty() && !password_.empty() && 226 DCHECK(!possibly_invalid_username_.empty() && !password_.empty() &&
379 last_result_.data.empty()); 227 last_result_.data.empty());
380 DCHECK(type_ == SIGNIN_TYPE_CLIENT_LOGIN); 228 DCHECK(type_ == SIGNIN_TYPE_CLIENT_LOGIN);
381 229
382 client_login_.reset(new GaiaAuthFetcher(this, 230 client_login_.reset(new GaiaAuthFetcher(this,
383 GaiaConstants::kChromeSource, 231 GaiaConstants::kChromeSource,
384 profile_->GetRequestContext())); 232 profile_->GetRequestContext()));
385 client_login_->StartClientLogin(possibly_invalid_username_, 233 client_login_->StartClientLogin(possibly_invalid_username_,
386 access_code, 234 access_code,
387 "", 235 "",
388 std::string(), 236 std::string(),
389 std::string(), 237 std::string(),
390 GaiaAuthFetcher::HostedAccountsNotAllowed); 238 GaiaAuthFetcher::HostedAccountsNotAllowed);
391 } 239 }
392 240
393 void SigninManager::StartSignInWithCredentials(const std::string& session_index, 241 void SigninManager::StartSignInWithCredentials(const std::string& session_index,
394 const std::string& username, 242 const std::string& username,
395 const std::string& password) { 243 const std::string& password) {
396 DCHECK(authenticated_username_.empty() || 244 DCHECK(GetAuthenticatedUsername().empty() ||
397 gaia::AreEmailsSame(username, authenticated_username_)); 245 gaia::AreEmailsSame(username, GetAuthenticatedUsername()));
398 246
399 if (!PrepareForSignin(SIGNIN_TYPE_WITH_CREDENTIALS, username, password)) 247 if (!PrepareForSignin(SIGNIN_TYPE_WITH_CREDENTIALS, username, password))
400 return; 248 return;
401 249
402 if (password.empty()) { 250 if (password.empty()) {
403 // Chrome must verify the GAIA cookies first if auto sign-in is triggered 251 // Chrome must verify the GAIA cookies first if auto sign-in is triggered
404 // with no password provided. This is to protect Chrome against forged 252 // with no password provided. This is to protect Chrome against forged
405 // GAIA cookies from a super-domain. 253 // GAIA cookies from a super-domain.
406 VerifyGaiaCookiesBeforeSignIn(session_index); 254 VerifyGaiaCookiesBeforeSignIn(session_index);
407 } else { 255 } else {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 if (success) { 299 if (success) {
452 client_login_->StartCookieForOAuthLoginTokenExchange(session_index); 300 client_login_->StartCookieForOAuthLoginTokenExchange(session_index);
453 } else { 301 } else {
454 HandleAuthError(GoogleServiceAuthError( 302 HandleAuthError(GoogleServiceAuthError(
455 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), true); 303 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), true);
456 } 304 }
457 } 305 }
458 306
459 void SigninManager::StartSignInWithOAuth(const std::string& username, 307 void SigninManager::StartSignInWithOAuth(const std::string& username,
460 const std::string& password) { 308 const std::string& password) {
461 DCHECK(authenticated_username_.empty()); 309 DCHECK(GetAuthenticatedUsername().empty());
462 310
463 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_OAUTH, username, password)) 311 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_OAUTH, username, password))
464 return; 312 return;
465 313
466 std::vector<std::string> scopes; 314 std::vector<std::string> scopes;
467 scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope()); 315 scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope());
468 const std::string& locale = g_browser_process->GetApplicationLocale(); 316 const std::string& locale = g_browser_process->GetApplicationLocale();
469 317
470 client_login_->StartClientOAuth(username, password, scopes, "", locale); 318 client_login_->StartClientOAuth(username, password, scopes, "", locale);
471 319
472 // Register for token availability. The signin manager will pre-login the 320 // Register for token availability. The signin manager will pre-login the
473 // user when the GAIA service token is ready for use. Only do this if we 321 // user when the GAIA service token is ready for use.
474 // are not running in ChomiumOS, since it handles pre-login itself, and if
475 // cookies are not disabled for Google accounts.
476 #if !defined(OS_CHROMEOS)
477 if (AreSigninCookiesAllowed(profile_)) { 322 if (AreSigninCookiesAllowed(profile_)) {
478 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 323 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
479 registrar_.Add(this, 324 registrar_.Add(this,
480 chrome::NOTIFICATION_TOKEN_AVAILABLE, 325 chrome::NOTIFICATION_TOKEN_AVAILABLE,
481 content::Source<TokenService>(token_service)); 326 content::Source<TokenService>(token_service));
482 } 327 }
483 #endif
484 } 328 }
485 329
486 void SigninManager::ProvideOAuthChallengeResponse( 330 void SigninManager::ProvideOAuthChallengeResponse(
487 GoogleServiceAuthError::State type, 331 GoogleServiceAuthError::State type,
488 const std::string& token, 332 const std::string& token,
489 const std::string& solution) { 333 const std::string& solution) {
490 DCHECK(!possibly_invalid_username_.empty() && !password_.empty()); 334 DCHECK(!possibly_invalid_username_.empty() && !password_.empty());
491 DCHECK(type_ == SIGNIN_TYPE_CLIENT_OAUTH); 335 DCHECK(type_ == SIGNIN_TYPE_CLIENT_OAUTH);
492 336
493 client_login_.reset(new GaiaAuthFetcher(this, 337 client_login_.reset(new GaiaAuthFetcher(this,
494 GaiaConstants::kChromeSource, 338 GaiaConstants::kChromeSource,
495 profile_->GetRequestContext())); 339 profile_->GetRequestContext()));
496 client_login_->StartClientOAuthChallengeResponse(type, token, solution); 340 client_login_->StartClientOAuthChallengeResponse(type, token, solution);
497 } 341 }
498 342
499 void SigninManager::ClearTransientSigninData() { 343 void SigninManager::ClearTransientSigninData() {
500 DCHECK(IsInitialized()); 344 DCHECK(IsInitialized());
501 345
502 CleanupNotificationRegistration(); 346 CleanupNotificationRegistration();
503 client_login_.reset(); 347 client_login_.reset();
504 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) 348 #if defined(ENABLE_CONFIGURATION_POLICY)
505 policy_client_.reset(); 349 policy_client_.reset();
506 #endif 350 #endif
507 last_result_ = ClientLoginResult(); 351 last_result_ = ClientLoginResult();
508 possibly_invalid_username_.clear(); 352 possibly_invalid_username_.clear();
509 password_.clear(); 353 password_.clear();
510 had_two_factor_error_ = false; 354 had_two_factor_error_ = false;
511 type_ = SIGNIN_TYPE_NONE; 355 type_ = SIGNIN_TYPE_NONE;
512 temp_oauth_login_tokens_ = ClientOAuthResult(); 356 temp_oauth_login_tokens_ = ClientOAuthResult();
513 } 357 }
514 358
515 void SigninManager::HandleAuthError(const GoogleServiceAuthError& error, 359 void SigninManager::HandleAuthError(const GoogleServiceAuthError& error,
516 bool clear_transient_data) { 360 bool clear_transient_data) {
517 content::NotificationService::current()->Notify( 361 content::NotificationService::current()->Notify(
518 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED, 362 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
519 content::Source<Profile>(profile_), 363 content::Source<Profile>(profile_),
520 content::Details<const GoogleServiceAuthError>(&error)); 364 content::Details<const GoogleServiceAuthError>(&error));
521 365
522 // In some cases, the user should not be signed out. For example, the failure 366 // In some cases, the user should not be signed out. For example, the failure
523 // may be due to a captcha or OTP challenge. In these cases, the transient 367 // may be due to a captcha or OTP challenge. In these cases, the transient
524 // data must be kept to properly handle the follow up. 368 // data must be kept to properly handle the follow up.
525 if (clear_transient_data) 369 if (clear_transient_data)
526 ClearTransientSigninData(); 370 ClearTransientSigninData();
527 } 371 }
528 372
373 bool SigninManager::ShouldSignOut() {
374 if (prohibit_signout_)
375 return false;
376
377 // Exit if we aren't signed in (or in the process of signing in).
378 // This avoids a perf regression from clearing out the TokenDB if
379 // SignOut() is invoked on startup to clean up any incomplete previous
380 // signin attempts.
381 if (GetAuthenticatedUsername().empty() && !client_login_.get())
382 return false;
383
384 return true;
Roger Tawa OOO till Jul 10th 2013/04/05 20:53:57 call base class?
tim (not reviewing) 2013/04/05 22:14:12 We don't want to do that. This method replaces th
385 }
386
529 void SigninManager::SignOut() { 387 void SigninManager::SignOut() {
530 DCHECK(IsInitialized()); 388 DCHECK(IsInitialized());
531 if (prohibit_signout_) { 389 if (prohibit_signout_) {
532 DVLOG(1) << "Ignoring attempt to sign out while signout is prohibited"; 390 DVLOG(1) << "Ignoring attempt to sign out while signout is prohibited";
533 return; 391 return;
534 } 392 }
535 if (authenticated_username_.empty() && !client_login_.get()) {
536 // Clean up our transient data and exit if we aren't signed in (or in the
537 // process of signing in). This avoids a perf regression from clearing out
538 // the TokenDB if SignOut() is invoked on startup to clean up any
539 // incomplete previous signin attempts.
540 ClearTransientSigninData();
541 return;
542 }
543
544 GoogleServiceSignoutDetails details(authenticated_username_);
545 393
546 ClearTransientSigninData(); 394 ClearTransientSigninData();
547 authenticated_username_.clear(); 395 SigninManagerBase::SignOut();
548 profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
549
550 // Erase (now) stale information from AboutSigninInternals.
551 NotifyDiagnosticsObservers(USERNAME, "");
552 NotifyDiagnosticsObservers(LSID, "");
553 NotifyDiagnosticsObservers(
554 signin_internals_util::SID, "");
555
556 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
557 content::NotificationService::current()->Notify(
558 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
559 content::Source<Profile>(profile_),
560 content::Details<const GoogleServiceSignoutDetails>(&details));
561 token_service->ResetCredentialsInMemory();
562 token_service->EraseTokensFromDB();
563 } 396 }
564 397
565 bool SigninManager::AuthInProgress() const { 398 bool SigninManager::AuthInProgress() const {
566 return !possibly_invalid_username_.empty(); 399 return !possibly_invalid_username_.empty();
567 } 400 }
568 401
569 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) { 402 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
570 DCHECK(key == kGetInfoDisplayEmailKey || key == kGetInfoEmailKey); 403 DCHECK(key == kGetInfoDisplayEmailKey || key == kGetInfoEmailKey);
571 LOG(ERROR) << "Account is not associated with a valid email address. " 404 LOG(ERROR) << "Account is not associated with a valid email address. "
572 << "Login failed."; 405 << "Login failed.";
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 // expected, return an error. 497 // expected, return an error.
665 if (type_ == SIGNIN_TYPE_WITH_CREDENTIALS && 498 if (type_ == SIGNIN_TYPE_WITH_CREDENTIALS &&
666 !gaia::AreEmailsSame(display_email_iter->second, 499 !gaia::AreEmailsSame(display_email_iter->second,
667 possibly_invalid_username_)) { 500 possibly_invalid_username_)) {
668 OnGetUserInfoKeyNotFound(kGetInfoDisplayEmailKey); 501 OnGetUserInfoKeyNotFound(kGetInfoDisplayEmailKey);
669 return; 502 return;
670 } 503 }
671 504
672 possibly_invalid_username_ = email_iter->second; 505 possibly_invalid_username_ = email_iter->second;
673 506
674 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) 507 #if defined(ENABLE_CONFIGURATION_POLICY)
675 // TODO(atwilson): Move this code out to OneClickSignin instead of having 508 // TODO(atwilson): Move this code out to OneClickSignin instead of having
676 // it embedded in SigninManager - we don't want UI logic in SigninManager. 509 // it embedded in SigninManager - we don't want UI logic in SigninManager.
677 // If this is a new signin (authenticated_username_ is not set) and we have 510 // If this is a new signin (authenticated_username_ is not set) and we have
678 // an OAuth token, try loading policy for this user now, before any signed in 511 // an OAuth token, try loading policy for this user now, before any signed in
679 // services are initialized. If there's no oauth token (the user is using the 512 // services are initialized. If there's no oauth token (the user is using the
680 // old ClientLogin flow) then policy will get loaded once the TokenService 513 // old ClientLogin flow) then policy will get loaded once the TokenService
681 // finishes initializing (not ideal, but it's a reasonable fallback). 514 // finishes initializing (not ideal, but it's a reasonable fallback).
682 if (authenticated_username_.empty() && 515 if (GetAuthenticatedUsername().empty() &&
683 !temp_oauth_login_tokens_.refresh_token.empty()) { 516 !temp_oauth_login_tokens_.refresh_token.empty()) {
684 policy::UserPolicySigninService* policy_service = 517 policy::UserPolicySigninService* policy_service =
685 policy::UserPolicySigninServiceFactory::GetForProfile(profile_); 518 policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
686 policy_service->RegisterPolicyClient( 519 policy_service->RegisterPolicyClient(
687 possibly_invalid_username_, 520 possibly_invalid_username_,
688 temp_oauth_login_tokens_.refresh_token, 521 temp_oauth_login_tokens_.refresh_token,
689 base::Bind(&SigninManager::OnRegisteredForPolicy, 522 base::Bind(&SigninManager::OnRegisteredForPolicy,
690 weak_pointer_factory_.GetWeakPtr())); 523 weak_pointer_factory_.GetWeakPtr()));
691 return; 524 return;
692 } 525 }
693 #endif 526 #endif
694 527
695 // Not waiting for policy load - just complete signin directly. 528 // Not waiting for policy load - just complete signin directly.
696 CompleteSigninAfterPolicyLoad(); 529 CompleteSigninAfterPolicyLoad();
697 } 530 }
698 531
699 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) 532 #if defined(ENABLE_CONFIGURATION_POLICY)
700 void SigninManager::OnRegisteredForPolicy( 533 void SigninManager::OnRegisteredForPolicy(
701 scoped_ptr<policy::CloudPolicyClient> client) { 534 scoped_ptr<policy::CloudPolicyClient> client) {
702 // If there's no token for the user (no policy) just finish signing in. 535 // If there's no token for the user (no policy) just finish signing in.
703 if (!client.get()) { 536 if (!client.get()) {
704 DVLOG(1) << "Policy registration failed"; 537 DVLOG(1) << "Policy registration failed";
705 CompleteSigninAfterPolicyLoad(); 538 CompleteSigninAfterPolicyLoad();
706 return; 539 return;
707 } 540 }
708 541
709 // Stash away a copy of our CloudPolicyClient (should not already have one). 542 // Stash away a copy of our CloudPolicyClient (should not already have one).
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 SignOut(); 623 SignOut();
791 } 624 }
792 } 625 }
793 #endif 626 #endif
794 627
795 void SigninManager::CompleteSigninAfterPolicyLoad() { 628 void SigninManager::CompleteSigninAfterPolicyLoad() {
796 DCHECK(!possibly_invalid_username_.empty()); 629 DCHECK(!possibly_invalid_username_.empty());
797 SetAuthenticatedUsername(possibly_invalid_username_); 630 SetAuthenticatedUsername(possibly_invalid_username_);
798 possibly_invalid_username_.clear(); 631 possibly_invalid_username_.clear();
799 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, 632 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
800 authenticated_username_); 633 GetAuthenticatedUsername());
801 634
802 GoogleServiceSigninSuccessDetails details(authenticated_username_, 635 GoogleServiceSigninSuccessDetails details(GetAuthenticatedUsername(),
803 password_); 636 password_);
804 content::NotificationService::current()->Notify( 637 content::NotificationService::current()->Notify(
805 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, 638 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
806 content::Source<Profile>(profile_), 639 content::Source<Profile>(profile_),
807 content::Details<const GoogleServiceSigninSuccessDetails>(&details)); 640 content::Details<const GoogleServiceSigninSuccessDetails>(&details));
808 641
809 password_.clear(); // Don't need it anymore. 642 password_.clear(); // Don't need it anymore.
810 DisableOneClickSignIn(profile_); // Don't ever offer again. 643 DisableOneClickSignIn(profile_); // Don't ever offer again.
811 644
812 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 645 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
(...skipping 30 matching lines...) Expand all
843 676
844 void SigninManager::OnUbertokenFailure(const GoogleServiceAuthError& error) { 677 void SigninManager::OnUbertokenFailure(const GoogleServiceAuthError& error) {
845 LOG(WARNING) << " Unable to login the user to the web: " << error.ToString(); 678 LOG(WARNING) << " Unable to login the user to the web: " << error.ToString();
846 ubertoken_fetcher_.reset(); 679 ubertoken_fetcher_.reset();
847 } 680 }
848 681
849 void SigninManager::Observe(int type, 682 void SigninManager::Observe(int type,
850 const content::NotificationSource& source, 683 const content::NotificationSource& source,
851 const content::NotificationDetails& details) { 684 const content::NotificationDetails& details) {
852 switch (type) { 685 switch (type) {
853 #if !defined(OS_CHROMEOS)
854 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { 686 case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
855 TokenService::TokenAvailableDetails* tok_details = 687 TokenService::TokenAvailableDetails* tok_details =
856 content::Details<TokenService::TokenAvailableDetails>( 688 content::Details<TokenService::TokenAvailableDetails>(
857 details).ptr(); 689 details).ptr();
858 690
859 // If a GAIA service token has become available, use it to pre-login the 691 // If a GAIA service token has become available, use it to pre-login the
860 // user to other services that depend on GAIA credentials. 692 // user to other services that depend on GAIA credentials.
861 if (tok_details->service() == 693 if (tok_details->service() ==
862 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { 694 GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
863 ubertoken_fetcher_.reset(new UbertokenFetcher(profile_, this)); 695 ubertoken_fetcher_.reset(new UbertokenFetcher(profile_, this));
(...skipping 11 matching lines...) Expand all
875 // if this was from the current signin process. 707 // if this was from the current signin process.
876 registrar_.Remove(this, 708 registrar_.Remove(this,
877 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 709 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
878 source); 710 source);
879 if (signin_process_id_ == 711 if (signin_process_id_ ==
880 content::Source<content::RenderProcessHost>(source)->GetID()) { 712 content::Source<content::RenderProcessHost>(source)->GetID()) {
881 signin_process_id_ = kInvalidProcessId; 713 signin_process_id_ = kInvalidProcessId;
882 } 714 }
883 break; 715 break;
884 } 716 }
885 #endif
886 default: 717 default:
887 NOTREACHED(); 718 NOTREACHED();
888 } 719 }
889 } 720 }
890 721
891 void SigninManager::Shutdown() {
892 if (signin_global_error_.get()) {
893 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError(
894 signin_global_error_.get());
895 signin_global_error_.reset();
896 }
897 }
898
899 void SigninManager::ProhibitSignout() { 722 void SigninManager::ProhibitSignout() {
900 prohibit_signout_ = true; 723 prohibit_signout_ = true;
901 } 724 }
902 725
903 bool SigninManager::IsSignoutProhibited() const { 726 bool SigninManager::IsSignoutProhibited() const {
904 return prohibit_signout_; 727 return prohibit_signout_;
905 } 728 }
906
907 void SigninManager::OnGoogleServicesUsernamePatternChanged() {
908 if (!authenticated_username_.empty() &&
909 !IsAllowedUsername(authenticated_username_)) {
910 // Signed in user is invalid according to the current policy so sign
911 // the user out.
912 SignOut();
913 }
914 }
915
916 void SigninManager::OnSigninAllowedPrefChanged() {
917 if (!IsSigninAllowed())
918 SignOut();
919 }
920
921 void SigninManager::AddSigninDiagnosticsObserver(
922 SigninDiagnosticsObserver* observer) {
923 signin_diagnostics_observers_.AddObserver(observer);
924 }
925
926 void SigninManager::RemoveSigninDiagnosticsObserver(
927 SigninDiagnosticsObserver* observer) {
928 signin_diagnostics_observers_.RemoveObserver(observer);
929 }
930
931 void SigninManager::NotifyDiagnosticsObservers(
932 const UntimedSigninStatusField& field,
933 const std::string& value) {
934 FOR_EACH_OBSERVER(SigninDiagnosticsObserver,
935 signin_diagnostics_observers_,
936 NotifySigninValueChanged(field, value));
937 }
938
939 void SigninManager::NotifyDiagnosticsObservers(
940 const TimedSigninStatusField& field,
941 const std::string& value) {
942 FOR_EACH_OBSERVER(SigninDiagnosticsObserver,
943 signin_diagnostics_observers_,
944 NotifySigninValueChanged(field, value));
945 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698