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: |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |