OLD | NEW |
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 Loading... |
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 Loading... |
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: |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 | 192 |
340 NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type)); | 193 NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type)); |
341 return true; | 194 return true; |
342 } | 195 } |
343 | 196 |
344 // Users must always sign out before they sign in again. | 197 // Users must always sign out before they sign in again. |
345 void SigninManager::StartSignIn(const std::string& username, | 198 void SigninManager::StartSignIn(const std::string& username, |
346 const std::string& password, | 199 const std::string& password, |
347 const std::string& login_token, | 200 const std::string& login_token, |
348 const std::string& login_captcha) { | 201 const std::string& login_captcha) { |
349 DCHECK(authenticated_username_.empty() || | 202 DCHECK(GetAuthenticatedUsername().empty() || |
350 gaia::AreEmailsSame(username, authenticated_username_)); | 203 gaia::AreEmailsSame(username, GetAuthenticatedUsername())); |
351 | 204 |
352 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_LOGIN, username, password)) | 205 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_LOGIN, username, password)) |
353 return; | 206 return; |
354 | 207 |
355 client_login_->StartClientLogin(username, | 208 client_login_->StartClientLogin(username, |
356 password, | 209 password, |
357 "", | 210 "", |
358 login_token, | 211 login_token, |
359 login_captcha, | 212 login_captcha, |
360 GaiaAuthFetcher::HostedAccountsNotAllowed); | 213 GaiaAuthFetcher::HostedAccountsNotAllowed); |
361 | 214 |
362 // Register for token availability. The signin manager will pre-login the | 215 // 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 | 216 // 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_)) { | 217 if (AreSigninCookiesAllowed(profile_)) { |
368 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 218 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
369 registrar_.Add(this, | 219 registrar_.Add(this, |
370 chrome::NOTIFICATION_TOKEN_AVAILABLE, | 220 chrome::NOTIFICATION_TOKEN_AVAILABLE, |
371 content::Source<TokenService>(token_service)); | 221 content::Source<TokenService>(token_service)); |
372 } | 222 } |
373 #endif | |
374 } | 223 } |
375 | 224 |
376 void SigninManager::ProvideSecondFactorAccessCode( | 225 void SigninManager::ProvideSecondFactorAccessCode( |
377 const std::string& access_code) { | 226 const std::string& access_code) { |
378 DCHECK(!possibly_invalid_username_.empty() && !password_.empty() && | 227 DCHECK(!possibly_invalid_username_.empty() && !password_.empty() && |
379 last_result_.data.empty()); | 228 last_result_.data.empty()); |
380 DCHECK(type_ == SIGNIN_TYPE_CLIENT_LOGIN); | 229 DCHECK(type_ == SIGNIN_TYPE_CLIENT_LOGIN); |
381 | 230 |
382 client_login_.reset(new GaiaAuthFetcher(this, | 231 client_login_.reset(new GaiaAuthFetcher(this, |
383 GaiaConstants::kChromeSource, | 232 GaiaConstants::kChromeSource, |
384 profile_->GetRequestContext())); | 233 profile_->GetRequestContext())); |
385 client_login_->StartClientLogin(possibly_invalid_username_, | 234 client_login_->StartClientLogin(possibly_invalid_username_, |
386 access_code, | 235 access_code, |
387 "", | 236 "", |
388 std::string(), | 237 std::string(), |
389 std::string(), | 238 std::string(), |
390 GaiaAuthFetcher::HostedAccountsNotAllowed); | 239 GaiaAuthFetcher::HostedAccountsNotAllowed); |
391 } | 240 } |
392 | 241 |
393 void SigninManager::StartSignInWithCredentials(const std::string& session_index, | 242 void SigninManager::StartSignInWithCredentials(const std::string& session_index, |
394 const std::string& username, | 243 const std::string& username, |
395 const std::string& password) { | 244 const std::string& password) { |
396 DCHECK(authenticated_username_.empty() || | 245 DCHECK(GetAuthenticatedUsername().empty() || |
397 gaia::AreEmailsSame(username, authenticated_username_)); | 246 gaia::AreEmailsSame(username, GetAuthenticatedUsername())); |
398 | 247 |
399 if (!PrepareForSignin(SIGNIN_TYPE_WITH_CREDENTIALS, username, password)) | 248 if (!PrepareForSignin(SIGNIN_TYPE_WITH_CREDENTIALS, username, password)) |
400 return; | 249 return; |
401 | 250 |
402 if (password.empty()) { | 251 if (password.empty()) { |
403 // Chrome must verify the GAIA cookies first if auto sign-in is triggered | 252 // 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 | 253 // with no password provided. This is to protect Chrome against forged |
405 // GAIA cookies from a super-domain. | 254 // GAIA cookies from a super-domain. |
406 VerifyGaiaCookiesBeforeSignIn(session_index); | 255 VerifyGaiaCookiesBeforeSignIn(session_index); |
407 } else { | 256 } else { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 if (success) { | 300 if (success) { |
452 client_login_->StartCookieForOAuthLoginTokenExchange(session_index); | 301 client_login_->StartCookieForOAuthLoginTokenExchange(session_index); |
453 } else { | 302 } else { |
454 HandleAuthError(GoogleServiceAuthError( | 303 HandleAuthError(GoogleServiceAuthError( |
455 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), true); | 304 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), true); |
456 } | 305 } |
457 } | 306 } |
458 | 307 |
459 void SigninManager::StartSignInWithOAuth(const std::string& username, | 308 void SigninManager::StartSignInWithOAuth(const std::string& username, |
460 const std::string& password) { | 309 const std::string& password) { |
461 DCHECK(authenticated_username_.empty()); | 310 DCHECK(GetAuthenticatedUsername().empty()); |
462 | 311 |
463 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_OAUTH, username, password)) | 312 if (!PrepareForSignin(SIGNIN_TYPE_CLIENT_OAUTH, username, password)) |
464 return; | 313 return; |
465 | 314 |
466 std::vector<std::string> scopes; | 315 std::vector<std::string> scopes; |
467 scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope()); | 316 scopes.push_back(GaiaUrls::GetInstance()->oauth1_login_scope()); |
468 const std::string& locale = g_browser_process->GetApplicationLocale(); | 317 const std::string& locale = g_browser_process->GetApplicationLocale(); |
469 | 318 |
470 client_login_->StartClientOAuth( | 319 client_login_->StartClientOAuth( |
471 username, password, scopes, std::string(), locale); | 320 username, password, scopes, std::string(), locale); |
472 | 321 |
473 // Register for token availability. The signin manager will pre-login the | 322 // Register for token availability. The signin manager will pre-login the |
474 // user when the GAIA service token is ready for use. Only do this if we | 323 // user when the GAIA service token is ready for use. |
475 // are not running in ChomiumOS, since it handles pre-login itself, and if | |
476 // cookies are not disabled for Google accounts. | |
477 #if !defined(OS_CHROMEOS) | |
478 if (AreSigninCookiesAllowed(profile_)) { | 324 if (AreSigninCookiesAllowed(profile_)) { |
479 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 325 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
480 registrar_.Add(this, | 326 registrar_.Add(this, |
481 chrome::NOTIFICATION_TOKEN_AVAILABLE, | 327 chrome::NOTIFICATION_TOKEN_AVAILABLE, |
482 content::Source<TokenService>(token_service)); | 328 content::Source<TokenService>(token_service)); |
483 } | 329 } |
484 #endif | |
485 } | 330 } |
486 | 331 |
487 void SigninManager::ProvideOAuthChallengeResponse( | 332 void SigninManager::ProvideOAuthChallengeResponse( |
488 GoogleServiceAuthError::State type, | 333 GoogleServiceAuthError::State type, |
489 const std::string& token, | 334 const std::string& token, |
490 const std::string& solution) { | 335 const std::string& solution) { |
491 DCHECK(!possibly_invalid_username_.empty() && !password_.empty()); | 336 DCHECK(!possibly_invalid_username_.empty() && !password_.empty()); |
492 DCHECK(type_ == SIGNIN_TYPE_CLIENT_OAUTH); | 337 DCHECK(type_ == SIGNIN_TYPE_CLIENT_OAUTH); |
493 | 338 |
494 client_login_.reset(new GaiaAuthFetcher(this, | 339 client_login_.reset(new GaiaAuthFetcher(this, |
495 GaiaConstants::kChromeSource, | 340 GaiaConstants::kChromeSource, |
496 profile_->GetRequestContext())); | 341 profile_->GetRequestContext())); |
497 client_login_->StartClientOAuthChallengeResponse(type, token, solution); | 342 client_login_->StartClientOAuthChallengeResponse(type, token, solution); |
498 } | 343 } |
499 | 344 |
500 void SigninManager::ClearTransientSigninData() { | 345 void SigninManager::ClearTransientSigninData() { |
501 DCHECK(IsInitialized()); | 346 DCHECK(IsInitialized()); |
502 | 347 |
503 CleanupNotificationRegistration(); | 348 CleanupNotificationRegistration(); |
504 client_login_.reset(); | 349 client_login_.reset(); |
505 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) | 350 #if defined(ENABLE_CONFIGURATION_POLICY) |
506 policy_client_.reset(); | 351 policy_client_.reset(); |
507 #endif | 352 #endif |
508 last_result_ = ClientLoginResult(); | 353 last_result_ = ClientLoginResult(); |
509 possibly_invalid_username_.clear(); | 354 possibly_invalid_username_.clear(); |
510 password_.clear(); | 355 password_.clear(); |
511 had_two_factor_error_ = false; | 356 had_two_factor_error_ = false; |
512 type_ = SIGNIN_TYPE_NONE; | 357 type_ = SIGNIN_TYPE_NONE; |
513 temp_oauth_login_tokens_ = ClientOAuthResult(); | 358 temp_oauth_login_tokens_ = ClientOAuthResult(); |
514 } | 359 } |
515 | 360 |
516 void SigninManager::HandleAuthError(const GoogleServiceAuthError& error, | 361 void SigninManager::HandleAuthError(const GoogleServiceAuthError& error, |
517 bool clear_transient_data) { | 362 bool clear_transient_data) { |
518 // In some cases, the user should not be signed out. For example, the failure | 363 // In some cases, the user should not be signed out. For example, the failure |
519 // may be due to a captcha or OTP challenge. In these cases, the transient | 364 // may be due to a captcha or OTP challenge. In these cases, the transient |
520 // data must be kept to properly handle the follow up. This routine clears | 365 // data must be kept to properly handle the follow up. This routine clears |
521 // the data before sending out the notification so the SigninManager is no | 366 // the data before sending out the notification so the SigninManager is no |
522 // longer in the AuthInProgress state when the notification goes out. | 367 // longer in the AuthInProgress state when the notification goes out. |
523 if (clear_transient_data) | 368 if (clear_transient_data) |
524 ClearTransientSigninData(); | 369 ClearTransientSigninData(); |
525 | 370 |
526 content::NotificationService::current()->Notify( | 371 content::NotificationService::current()->Notify( |
527 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED, | 372 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED, |
528 content::Source<Profile>(profile_), | 373 content::Source<Profile>(profile_), |
529 content::Details<const GoogleServiceAuthError>(&error)); | 374 content::Details<const GoogleServiceAuthError>(&error)); |
530 } | 375 } |
531 | 376 |
532 void SigninManager::SignOut() { | 377 void SigninManager::SignOut() { |
533 DCHECK(IsInitialized()); | 378 DCHECK(IsInitialized()); |
534 | 379 |
535 if (authenticated_username_.empty()) { | 380 if (GetAuthenticatedUsername().empty()) { |
536 if (AuthInProgress()) { | 381 if (AuthInProgress()) { |
537 // If the user is in the process of signing in, then treat a call to | 382 // If the user is in the process of signing in, then treat a call to |
538 // SignOut as a cancellation request. | 383 // SignOut as a cancellation request. |
539 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); | 384 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); |
540 HandleAuthError(error, true); | 385 HandleAuthError(error, true); |
541 } else { | 386 } else { |
542 // Clean up our transient data and exit if we aren't signed in. | 387 // Clean up our transient data and exit if we aren't signed in. |
543 // This avoids a perf regression from clearing out the TokenDB if | 388 // This avoids a perf regression from clearing out the TokenDB if |
544 // SignOut() is invoked on startup to clean up any incomplete previous | 389 // SignOut() is invoked on startup to clean up any incomplete previous |
545 // signin attempts. | 390 // signin attempts. |
546 ClearTransientSigninData(); | 391 ClearTransientSigninData(); |
547 } | 392 } |
548 return; | 393 return; |
549 } | 394 } |
550 | 395 |
551 if (prohibit_signout_) { | 396 if (prohibit_signout_) { |
552 DVLOG(1) << "Ignoring attempt to sign out while signout is prohibited"; | 397 DVLOG(1) << "Ignoring attempt to sign out while signout is prohibited"; |
553 return; | 398 return; |
554 } | 399 } |
555 DCHECK(!authenticated_username_.empty()); | |
556 GoogleServiceSignoutDetails details(authenticated_username_); | |
557 | 400 |
558 ClearTransientSigninData(); | 401 ClearTransientSigninData(); |
559 authenticated_username_.clear(); | |
560 profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername); | |
561 | |
562 // Erase (now) stale information from AboutSigninInternals. | |
563 NotifyDiagnosticsObservers(USERNAME, std::string()); | |
564 NotifyDiagnosticsObservers(LSID, std::string()); | |
565 NotifyDiagnosticsObservers(signin_internals_util::SID, std::string()); | |
566 | |
567 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | |
568 content::NotificationService::current()->Notify( | |
569 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, | |
570 content::Source<Profile>(profile_), | |
571 content::Details<const GoogleServiceSignoutDetails>(&details)); | |
572 RevokeOAuthLoginToken(); | 402 RevokeOAuthLoginToken(); |
573 token_service->ResetCredentialsInMemory(); | 403 SigninManagerBase::SignOut(); |
574 token_service->EraseTokensFromDB(); | |
575 } | 404 } |
576 | 405 |
577 void SigninManager::RevokeOAuthLoginToken() { | 406 void SigninManager::RevokeOAuthLoginToken() { |
578 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 407 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
579 if (token_service->HasOAuthLoginToken()) { | 408 if (token_service->HasOAuthLoginToken()) { |
580 revoke_token_fetcher_.reset( | 409 revoke_token_fetcher_.reset( |
581 new GaiaAuthFetcher(this, | 410 new GaiaAuthFetcher(this, |
582 GaiaConstants::kChromeSource, | 411 GaiaConstants::kChromeSource, |
583 profile_->GetRequestContext())); | 412 profile_->GetRequestContext())); |
584 revoke_token_fetcher_->StartRevokeOAuth2Token( | 413 revoke_token_fetcher_->StartRevokeOAuth2Token( |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 // expected, return an error. | 525 // expected, return an error. |
697 if (type_ == SIGNIN_TYPE_WITH_CREDENTIALS && | 526 if (type_ == SIGNIN_TYPE_WITH_CREDENTIALS && |
698 !gaia::AreEmailsSame(display_email_iter->second, | 527 !gaia::AreEmailsSame(display_email_iter->second, |
699 possibly_invalid_username_)) { | 528 possibly_invalid_username_)) { |
700 OnGetUserInfoKeyNotFound(kGetInfoDisplayEmailKey); | 529 OnGetUserInfoKeyNotFound(kGetInfoDisplayEmailKey); |
701 return; | 530 return; |
702 } | 531 } |
703 | 532 |
704 possibly_invalid_username_ = email_iter->second; | 533 possibly_invalid_username_ = email_iter->second; |
705 | 534 |
706 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) | 535 #if defined(ENABLE_CONFIGURATION_POLICY) |
707 // TODO(atwilson): Move this code out to OneClickSignin instead of having | 536 // TODO(atwilson): Move this code out to OneClickSignin instead of having |
708 // it embedded in SigninManager - we don't want UI logic in SigninManager. | 537 // it embedded in SigninManager - we don't want UI logic in SigninManager. |
709 // If this is a new signin (authenticated_username_ is not set) and we have | 538 // If this is a new signin (authenticated_username_ is not set) and we have |
710 // an OAuth token, try loading policy for this user now, before any signed in | 539 // an OAuth token, try loading policy for this user now, before any signed in |
711 // services are initialized. If there's no oauth token (the user is using the | 540 // services are initialized. If there's no oauth token (the user is using the |
712 // old ClientLogin flow) then policy will get loaded once the TokenService | 541 // old ClientLogin flow) then policy will get loaded once the TokenService |
713 // finishes initializing (not ideal, but it's a reasonable fallback). | 542 // finishes initializing (not ideal, but it's a reasonable fallback). |
714 if (authenticated_username_.empty() && | 543 if (GetAuthenticatedUsername().empty() && |
715 !temp_oauth_login_tokens_.refresh_token.empty()) { | 544 !temp_oauth_login_tokens_.refresh_token.empty()) { |
716 policy::UserPolicySigninService* policy_service = | 545 policy::UserPolicySigninService* policy_service = |
717 policy::UserPolicySigninServiceFactory::GetForProfile(profile_); | 546 policy::UserPolicySigninServiceFactory::GetForProfile(profile_); |
718 policy_service->RegisterPolicyClient( | 547 policy_service->RegisterPolicyClient( |
719 possibly_invalid_username_, | 548 possibly_invalid_username_, |
720 temp_oauth_login_tokens_.refresh_token, | 549 temp_oauth_login_tokens_.refresh_token, |
721 base::Bind(&SigninManager::OnRegisteredForPolicy, | 550 base::Bind(&SigninManager::OnRegisteredForPolicy, |
722 weak_pointer_factory_.GetWeakPtr())); | 551 weak_pointer_factory_.GetWeakPtr())); |
723 return; | 552 return; |
724 } | 553 } |
725 #endif | 554 #endif |
726 | 555 |
727 // Not waiting for policy load - just complete signin directly. | 556 // Not waiting for policy load - just complete signin directly. |
728 CompleteSigninAfterPolicyLoad(); | 557 CompleteSigninAfterPolicyLoad(); |
729 } | 558 } |
730 | 559 |
731 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) | 560 #if defined(ENABLE_CONFIGURATION_POLICY) |
732 void SigninManager::OnRegisteredForPolicy( | 561 void SigninManager::OnRegisteredForPolicy( |
733 scoped_ptr<policy::CloudPolicyClient> client) { | 562 scoped_ptr<policy::CloudPolicyClient> client) { |
734 // If there's no token for the user (no policy) just finish signing in. | 563 // If there's no token for the user (no policy) just finish signing in. |
735 if (!client.get()) { | 564 if (!client.get()) { |
736 DVLOG(1) << "Policy registration failed"; | 565 DVLOG(1) << "Policy registration failed"; |
737 CompleteSigninAfterPolicyLoad(); | 566 CompleteSigninAfterPolicyLoad(); |
738 return; | 567 return; |
739 } | 568 } |
740 | 569 |
741 // Stash away a copy of our CloudPolicyClient (should not already have one). | 570 // Stash away a copy of our CloudPolicyClient (should not already have one). |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 SignOut(); | 656 SignOut(); |
828 } | 657 } |
829 } | 658 } |
830 #endif | 659 #endif |
831 | 660 |
832 void SigninManager::CompleteSigninAfterPolicyLoad() { | 661 void SigninManager::CompleteSigninAfterPolicyLoad() { |
833 DCHECK(!possibly_invalid_username_.empty()); | 662 DCHECK(!possibly_invalid_username_.empty()); |
834 SetAuthenticatedUsername(possibly_invalid_username_); | 663 SetAuthenticatedUsername(possibly_invalid_username_); |
835 possibly_invalid_username_.clear(); | 664 possibly_invalid_username_.clear(); |
836 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, | 665 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, |
837 authenticated_username_); | 666 GetAuthenticatedUsername()); |
838 | 667 |
839 GoogleServiceSigninSuccessDetails details(authenticated_username_, | 668 GoogleServiceSigninSuccessDetails details(GetAuthenticatedUsername(), |
840 password_); | 669 password_); |
841 content::NotificationService::current()->Notify( | 670 content::NotificationService::current()->Notify( |
842 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, | 671 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, |
843 content::Source<Profile>(profile_), | 672 content::Source<Profile>(profile_), |
844 content::Details<const GoogleServiceSigninSuccessDetails>(&details)); | 673 content::Details<const GoogleServiceSigninSuccessDetails>(&details)); |
845 | 674 |
846 password_.clear(); // Don't need it anymore. | 675 password_.clear(); // Don't need it anymore. |
847 DisableOneClickSignIn(profile_); // Don't ever offer again. | 676 DisableOneClickSignIn(profile_); // Don't ever offer again. |
848 | 677 |
849 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 678 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
(...skipping 30 matching lines...) Expand all Loading... |
880 | 709 |
881 void SigninManager::OnUbertokenFailure(const GoogleServiceAuthError& error) { | 710 void SigninManager::OnUbertokenFailure(const GoogleServiceAuthError& error) { |
882 LOG(WARNING) << " Unable to login the user to the web: " << error.ToString(); | 711 LOG(WARNING) << " Unable to login the user to the web: " << error.ToString(); |
883 ubertoken_fetcher_.reset(); | 712 ubertoken_fetcher_.reset(); |
884 } | 713 } |
885 | 714 |
886 void SigninManager::Observe(int type, | 715 void SigninManager::Observe(int type, |
887 const content::NotificationSource& source, | 716 const content::NotificationSource& source, |
888 const content::NotificationDetails& details) { | 717 const content::NotificationDetails& details) { |
889 switch (type) { | 718 switch (type) { |
890 #if !defined(OS_CHROMEOS) | |
891 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { | 719 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { |
892 TokenService::TokenAvailableDetails* tok_details = | 720 TokenService::TokenAvailableDetails* tok_details = |
893 content::Details<TokenService::TokenAvailableDetails>( | 721 content::Details<TokenService::TokenAvailableDetails>( |
894 details).ptr(); | 722 details).ptr(); |
895 | 723 |
896 // If a GAIA service token has become available, use it to pre-login the | 724 // If a GAIA service token has become available, use it to pre-login the |
897 // user to other services that depend on GAIA credentials. | 725 // user to other services that depend on GAIA credentials. |
898 if (tok_details->service() == | 726 if (tok_details->service() == |
899 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { | 727 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { |
900 ubertoken_fetcher_.reset(new UbertokenFetcher(profile_, this)); | 728 ubertoken_fetcher_.reset(new UbertokenFetcher(profile_, this)); |
(...skipping 11 matching lines...) Expand all Loading... |
912 // if this was from the current signin process. | 740 // if this was from the current signin process. |
913 registrar_.Remove(this, | 741 registrar_.Remove(this, |
914 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 742 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
915 source); | 743 source); |
916 if (signin_process_id_ == | 744 if (signin_process_id_ == |
917 content::Source<content::RenderProcessHost>(source)->GetID()) { | 745 content::Source<content::RenderProcessHost>(source)->GetID()) { |
918 signin_process_id_ = kInvalidProcessId; | 746 signin_process_id_ = kInvalidProcessId; |
919 } | 747 } |
920 break; | 748 break; |
921 } | 749 } |
922 #endif | |
923 default: | 750 default: |
924 NOTREACHED(); | 751 NOTREACHED(); |
925 } | 752 } |
926 } | 753 } |
927 | 754 |
928 void SigninManager::Shutdown() { | |
929 if (signin_global_error_.get()) { | |
930 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError( | |
931 signin_global_error_.get()); | |
932 signin_global_error_.reset(); | |
933 } | |
934 } | |
935 | |
936 void SigninManager::ProhibitSignout(bool prohibit_signout) { | 755 void SigninManager::ProhibitSignout(bool prohibit_signout) { |
937 prohibit_signout_ = prohibit_signout; | 756 prohibit_signout_ = prohibit_signout; |
938 } | 757 } |
939 | 758 |
940 bool SigninManager::IsSignoutProhibited() const { | 759 bool SigninManager::IsSignoutProhibited() const { |
941 return prohibit_signout_; | 760 return prohibit_signout_; |
942 } | 761 } |
943 | |
944 void SigninManager::OnGoogleServicesUsernamePatternChanged() { | |
945 if (!authenticated_username_.empty() && | |
946 !IsAllowedUsername(authenticated_username_)) { | |
947 // Signed in user is invalid according to the current policy so sign | |
948 // the user out. | |
949 SignOut(); | |
950 } | |
951 } | |
952 | |
953 void SigninManager::OnSigninAllowedPrefChanged() { | |
954 if (!IsSigninAllowed()) | |
955 SignOut(); | |
956 } | |
957 | |
958 void SigninManager::AddSigninDiagnosticsObserver( | |
959 SigninDiagnosticsObserver* observer) { | |
960 signin_diagnostics_observers_.AddObserver(observer); | |
961 } | |
962 | |
963 void SigninManager::RemoveSigninDiagnosticsObserver( | |
964 SigninDiagnosticsObserver* observer) { | |
965 signin_diagnostics_observers_.RemoveObserver(observer); | |
966 } | |
967 | |
968 void SigninManager::NotifyDiagnosticsObservers( | |
969 const UntimedSigninStatusField& field, | |
970 const std::string& value) { | |
971 FOR_EACH_OBSERVER(SigninDiagnosticsObserver, | |
972 signin_diagnostics_observers_, | |
973 NotifySigninValueChanged(field, value)); | |
974 } | |
975 | |
976 void SigninManager::NotifyDiagnosticsObservers( | |
977 const TimedSigninStatusField& field, | |
978 const std::string& value) { | |
979 FOR_EACH_OBSERVER(SigninDiagnosticsObserver, | |
980 signin_diagnostics_observers_, | |
981 NotifySigninValueChanged(field, value)); | |
982 } | |
OLD | NEW |