| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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/sync/engine/auth_watcher.h" | 5 #include "chrome/browser/sync/engine/auth_watcher.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "chrome/browser/sync/engine/all_status.h" | 9 #include "chrome/browser/sync/engine/all_status.h" |
| 10 #include "chrome/browser/sync/engine/authenticator.h" | 10 #include "chrome/browser/sync/engine/authenticator.h" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 | 71 |
| 72 void AuthWatcher::PersistCredentials() { | 72 void AuthWatcher::PersistCredentials() { |
| 73 DCHECK_EQ(MessageLoop::current(), message_loop()); | 73 DCHECK_EQ(MessageLoop::current(), message_loop()); |
| 74 gaia::GaiaAuthenticator::AuthResults results = gaia_->results(); | 74 gaia::GaiaAuthenticator::AuthResults results = gaia_->results(); |
| 75 | 75 |
| 76 // We just successfully signed in again, let's clear out any residual cached | 76 // We just successfully signed in again, let's clear out any residual cached |
| 77 // login data from earlier sessions. | 77 // login data from earlier sessions. |
| 78 ClearAuthenticationData(); | 78 ClearAuthenticationData(); |
| 79 | 79 |
| 80 user_settings_->StoreEmailForSignin(results.email, results.primary_email); | 80 user_settings_->StoreEmailForSignin(results.email, results.primary_email); |
| 81 user_settings_->RememberSigninType(results.email, results.signin); | |
| 82 user_settings_->RememberSigninType(results.primary_email, results.signin); | |
| 83 results.email = results.primary_email; | 81 results.email = results.primary_email; |
| 84 gaia_->SetUsernamePassword(results.primary_email, results.password); | 82 gaia_->SetUsernamePassword(results.primary_email, results.password); |
| 85 if (!user_settings_->VerifyAgainstStoredHash(results.email, results.password)) | 83 if (!user_settings_->VerifyAgainstStoredHash(results.email, results.password)) |
| 86 user_settings_->StoreHashedPassword(results.email, results.password); | 84 user_settings_->StoreHashedPassword(results.email, results.password); |
| 87 | 85 |
| 88 if (gaia::PERSIST_TO_DISK == results.credentials_saved) { | 86 user_settings_->SetAuthTokenForService(results.email, |
| 89 user_settings_->SetAuthTokenForService(results.email, | 87 SYNC_SERVICE_NAME, |
| 90 SYNC_SERVICE_NAME, | 88 gaia_->auth_token()); |
| 91 gaia_->auth_token()); | |
| 92 } | |
| 93 } | 89 } |
| 94 | 90 |
| 95 // TODO(chron): Full integration test suite needed. http://crbug.com/35429 | 91 // TODO(chron): Full integration test suite needed. http://crbug.com/35429 |
| 96 void AuthWatcher::RenewAuthToken(const std::string& updated_token) { | 92 void AuthWatcher::RenewAuthToken(const std::string& updated_token) { |
| 97 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, | 93 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 98 &AuthWatcher::DoRenewAuthToken, updated_token)); | 94 &AuthWatcher::DoRenewAuthToken, updated_token)); |
| 99 } | 95 } |
| 100 | 96 |
| 101 void AuthWatcher::DoRenewAuthToken(const std::string& updated_token) { | 97 void AuthWatcher::DoRenewAuthToken(const std::string& updated_token) { |
| 102 DCHECK_EQ(MessageLoop::current(), message_loop()); | 98 DCHECK_EQ(MessageLoop::current(), message_loop()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 123 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, | 119 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 124 &AuthWatcher::DoAuthenticateWithLsid, lsid)); | 120 &AuthWatcher::DoAuthenticateWithLsid, lsid)); |
| 125 } | 121 } |
| 126 | 122 |
| 127 void AuthWatcher::DoAuthenticateWithLsid(const std::string& lsid) { | 123 void AuthWatcher::DoAuthenticateWithLsid(const std::string& lsid) { |
| 128 DCHECK_EQ(MessageLoop::current(), message_loop()); | 124 DCHECK_EQ(MessageLoop::current(), message_loop()); |
| 129 | 125 |
| 130 AuthWatcherEvent event = { AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START }; | 126 AuthWatcherEvent event = { AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START }; |
| 131 NotifyListeners(&event); | 127 NotifyListeners(&event); |
| 132 | 128 |
| 133 if (gaia_->AuthenticateWithLsid(lsid, true)) { | 129 if (gaia_->AuthenticateWithLsid(lsid)) { |
| 134 PersistCredentials(); | 130 PersistCredentials(); |
| 135 DoAuthenticateWithToken(gaia_->email(), gaia_->auth_token()); | 131 DoAuthenticateWithToken(gaia_->email(), gaia_->auth_token()); |
| 136 } else { | 132 } else { |
| 137 ProcessGaiaAuthFailure(); | 133 ProcessGaiaAuthFailure(); |
| 138 } | 134 } |
| 139 } | 135 } |
| 140 | 136 |
| 141 const char kAuthWatcher[] = "AuthWatcher"; | 137 const char kAuthWatcher[] = "AuthWatcher"; |
| 142 | 138 |
| 143 void AuthWatcher::AuthenticateWithToken(const std::string& gaia_email, | 139 void AuthWatcher::AuthenticateWithToken(const std::string& gaia_email, |
| 144 const std::string& auth_token) { | 140 const std::string& auth_token) { |
| 145 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, | 141 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 146 &AuthWatcher::DoAuthenticateWithToken, gaia_email, auth_token)); | 142 &AuthWatcher::DoAuthenticateWithToken, gaia_email, auth_token)); |
| 147 } | 143 } |
| 148 | 144 |
| 149 void AuthWatcher::DoAuthenticateWithToken(const std::string& gaia_email, | 145 void AuthWatcher::DoAuthenticateWithToken(const std::string& gaia_email, |
| 150 const std::string& auth_token) { | 146 const std::string& auth_token) { |
| 151 DCHECK_EQ(MessageLoop::current(), message_loop()); | 147 DCHECK_EQ(MessageLoop::current(), message_loop()); |
| 152 | 148 |
| 153 Authenticator auth(scm_, user_settings_); | 149 Authenticator auth(scm_, user_settings_); |
| 154 Authenticator::AuthenticationResult result = | 150 Authenticator::AuthenticationResult result = |
| 155 auth.AuthenticateToken(auth_token); | 151 auth.AuthenticateToken(auth_token); |
| 156 string email = gaia_email; | 152 string email = gaia_email; |
| 157 if (auth.display_email() && *auth.display_email()) { | 153 if (auth.display_email() && *auth.display_email()) { |
| 158 email = auth.display_email(); | 154 email = auth.display_email(); |
| 159 LOG(INFO) << "Auth returned email " << email << " for gaia email " << | 155 LOG(INFO) << "Auth returned email " << email << " for gaia email " << |
| 160 gaia_email; | 156 gaia_email; |
| 161 } | 157 } |
| 158 |
| 162 AuthWatcherEvent event = {AuthWatcherEvent::ILLEGAL_VALUE , 0}; | 159 AuthWatcherEvent event = {AuthWatcherEvent::ILLEGAL_VALUE , 0}; |
| 163 gaia_->SetUsername(email); | 160 gaia_->SetUsername(email); |
| 164 gaia_->SetAuthToken(auth_token, gaia::SAVE_IN_MEMORY_ONLY); | 161 gaia_->SetAuthToken(auth_token); |
| 165 const bool was_authenticated = NOT_AUTHENTICATED != status_; | 162 const bool was_authenticated = NOT_AUTHENTICATED != status_; |
| 166 switch (result) { | 163 switch (result) { |
| 167 case Authenticator::SUCCESS: | 164 case Authenticator::SUCCESS: |
| 168 { | 165 { |
| 169 status_ = GAIA_AUTHENTICATED; | 166 status_ = GAIA_AUTHENTICATED; |
| 170 const std::string& share_name = email; | 167 const std::string& share_name = email; |
| 171 user_settings_->SwitchUser(email); | 168 user_settings_->SwitchUser(email); |
| 172 | 169 |
| 173 // Set the authentication token for notifications | 170 // Set the authentication token for notifications |
| 174 talk_mediator_->SetAuthToken(email, auth_token, SYNC_SERVICE_NAME); | 171 talk_mediator_->SetAuthToken(email, auth_token, SYNC_SERVICE_NAME); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 return user_settings_->VerifyAgainstStoredHash(email, password) | 225 return user_settings_->VerifyAgainstStoredHash(email, password) |
| 229 && AuthenticateLocally(email); | 226 && AuthenticateLocally(email); |
| 230 } | 227 } |
| 231 | 228 |
| 232 void AuthWatcher::ProcessGaiaAuthFailure() { | 229 void AuthWatcher::ProcessGaiaAuthFailure() { |
| 233 DCHECK_EQ(MessageLoop::current(), message_loop()); | 230 DCHECK_EQ(MessageLoop::current(), message_loop()); |
| 234 gaia::GaiaAuthenticator::AuthResults results = gaia_->results(); | 231 gaia::GaiaAuthenticator::AuthResults results = gaia_->results(); |
| 235 if (LOCALLY_AUTHENTICATED == status_) { | 232 if (LOCALLY_AUTHENTICATED == status_) { |
| 236 return; // nothing todo | 233 return; // nothing todo |
| 237 } else if (AuthenticateLocally(results.email, results.password)) { | 234 } else if (AuthenticateLocally(results.email, results.password)) { |
| 238 // We save the "Remember me" checkbox by putting a non-null auth | 235 // TODO(chron): Do we really want a bogus token? |
| 239 // token into the last_user table. So if we're offline and the | 236 const string auth_token("bogus"); |
| 240 // user checks the box, insert a bogus auth token. | 237 user_settings_->SetAuthTokenForService(results.email, |
| 241 if (gaia::PERSIST_TO_DISK == results.credentials_saved) { | 238 SYNC_SERVICE_NAME, |
| 242 const string auth_token("bogus"); | 239 auth_token); |
| 243 user_settings_->SetAuthTokenForService(results.email, | |
| 244 SYNC_SERVICE_NAME, | |
| 245 auth_token); | |
| 246 } | |
| 247 const bool unavailable = | 240 const bool unavailable = |
| 248 gaia::ConnectionUnavailable == results.auth_error || | 241 gaia::ConnectionUnavailable == results.auth_error || |
| 249 gaia::Unknown == results.auth_error || | 242 gaia::Unknown == results.auth_error || |
| 250 gaia::ServiceUnavailable == results.auth_error; | 243 gaia::ServiceUnavailable == results.auth_error; |
| 251 if (unavailable) | 244 if (unavailable) |
| 252 return; | 245 return; |
| 253 } | 246 } |
| 254 AuthWatcherEvent myevent = { AuthWatcherEvent::GAIA_AUTH_FAILED, &results }; | 247 AuthWatcherEvent myevent = { AuthWatcherEvent::GAIA_AUTH_FAILED, &results }; |
| 255 NotifyListeners(&myevent); | 248 NotifyListeners(&myevent); |
| 256 } | 249 } |
| 257 | 250 |
| 258 void AuthWatcher::DoAuthenticate(const AuthRequest& request) { | 251 void AuthWatcher::DoAuthenticate(const AuthRequest& request) { |
| 259 DCHECK_EQ(MessageLoop::current(), message_loop()); | 252 DCHECK_EQ(MessageLoop::current(), message_loop()); |
| 260 | 253 |
| 261 AuthWatcherEvent event = { AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START }; | 254 AuthWatcherEvent event = { AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START }; |
| 262 NotifyListeners(&event); | 255 NotifyListeners(&event); |
| 263 | 256 |
| 264 current_attempt_trigger_ = request.trigger; | 257 current_attempt_trigger_ = request.trigger; |
| 265 | 258 |
| 266 gaia::SaveCredentials save = request.persist_creds_to_disk ? | |
| 267 gaia::PERSIST_TO_DISK : gaia::SAVE_IN_MEMORY_ONLY; | |
| 268 gaia::SignIn const signin = user_settings_-> | |
| 269 RecallSigninType(request.email, gaia::GMAIL_SIGNIN); | |
| 270 | |
| 271 // We let the caller be lazy and try using the last captcha token seen by | 259 // We let the caller be lazy and try using the last captcha token seen by |
| 272 // the gaia authenticator if they haven't provided a token but have sent | 260 // the gaia authenticator if they haven't provided a token but have sent |
| 273 // a challenge response. Of course, if the captcha token is specified, | 261 // a challenge response. Of course, if the captcha token is specified, |
| 274 // we use that one instead. | 262 // we use that one instead. |
| 275 std::string captcha_token(request.captcha_token); | 263 std::string captcha_token(request.captcha_token); |
| 276 if (!request.captcha_value.empty() && captcha_token.empty()) | 264 if (!request.captcha_value.empty() && captcha_token.empty()) |
| 277 captcha_token = gaia_->captcha_token(); | 265 captcha_token = gaia_->captcha_token(); |
| 278 | 266 |
| 279 if (!request.password.empty()) { | 267 if (!request.password.empty()) { |
| 280 bool authenticated = false; | 268 bool authenticated = false; |
| 281 if (!captcha_token.empty()) { | 269 if (!captcha_token.empty()) { |
| 282 authenticated = gaia_->Authenticate(request.email, request.password, | 270 authenticated = gaia_->Authenticate(request.email, request.password, |
| 283 save, captcha_token, | 271 captcha_token, |
| 284 request.captcha_value, signin); | 272 request.captcha_value); |
| 285 } else { | 273 } else { |
| 286 authenticated = gaia_->Authenticate(request.email, request.password, | 274 authenticated = gaia_->Authenticate(request.email, request.password); |
| 287 save, signin); | |
| 288 } | 275 } |
| 289 if (authenticated) { | 276 if (authenticated) { |
| 290 PersistCredentials(); | 277 PersistCredentials(); |
| 291 DoAuthenticateWithToken(gaia_->email(), gaia_->auth_token()); | 278 DoAuthenticateWithToken(gaia_->email(), gaia_->auth_token()); |
| 292 } else { | 279 } else { |
| 293 ProcessGaiaAuthFailure(); | 280 ProcessGaiaAuthFailure(); |
| 294 } | 281 } |
| 295 } else if (!request.auth_token.empty()) { | 282 } else if (!request.auth_token.empty()) { |
| 296 DoAuthenticateWithToken(request.email, request.auth_token); | 283 DoAuthenticateWithToken(request.email, request.auth_token); |
| 297 } else { | 284 } else { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 327 status_ == LOCALLY_AUTHENTICATED)) { | 314 status_ == LOCALLY_AUTHENTICATED)) { |
| 328 // We're either online or just got reconnected and want to try to | 315 // We're either online or just got reconnected and want to try to |
| 329 // authenticate. If we've got a saved token this should just work. If not | 316 // authenticate. If we've got a saved token this should just work. If not |
| 330 // the auth failure should trigger UI indications that we're not logged in. | 317 // the auth failure should trigger UI indications that we're not logged in. |
| 331 | 318 |
| 332 // METRIC: If we get a SYNC_AUTH_ERROR, our token expired. | 319 // METRIC: If we get a SYNC_AUTH_ERROR, our token expired. |
| 333 gaia::GaiaAuthenticator::AuthResults authresults = gaia_->results(); | 320 gaia::GaiaAuthenticator::AuthResults authresults = gaia_->results(); |
| 334 AuthRequest request = { authresults.email, authresults.password, | 321 AuthRequest request = { authresults.email, authresults.password, |
| 335 authresults.auth_token, std::string(), | 322 authresults.auth_token, std::string(), |
| 336 std::string(), | 323 std::string(), |
| 337 gaia::PERSIST_TO_DISK == | |
| 338 authresults.credentials_saved, | |
| 339 AuthWatcherEvent::EXPIRED_CREDENTIALS }; | 324 AuthWatcherEvent::EXPIRED_CREDENTIALS }; |
| 340 DoAuthenticate(request); | 325 DoAuthenticate(request); |
| 341 } | 326 } |
| 342 } | 327 } |
| 343 | 328 |
| 344 AuthWatcher::~AuthWatcher() { | 329 AuthWatcher::~AuthWatcher() { |
| 345 auth_backend_thread_.Stop(); | 330 auth_backend_thread_.Stop(); |
| 346 // The gaia authenticator takes a const MessageLoop* because it only uses it | 331 // The gaia authenticator takes a const MessageLoop* because it only uses it |
| 347 // to ensure all methods are invoked on the given loop. Once our thread has | 332 // to ensure all methods are invoked on the given loop. Once our thread has |
| 348 // stopped, the current message loop will be NULL, and no methods should be | 333 // stopped, the current message loop will be NULL, and no methods should be |
| 349 // invoked on |gaia_| after this point. We could set it to NULL, but | 334 // invoked on |gaia_| after this point. We could set it to NULL, but |
| 350 // abstaining allows for even more sanity checking that nothing is invoked on | 335 // abstaining allows for even more sanity checking that nothing is invoked on |
| 351 // it from now on. | 336 // it from now on. |
| 352 } | 337 } |
| 353 | 338 |
| 354 void AuthWatcher::Authenticate(const string& email, const string& password, | 339 void AuthWatcher::Authenticate(const string& email, const string& password, |
| 355 const string& captcha_token, const string& captcha_value, | 340 const string& captcha_token, const string& captcha_value) { |
| 356 bool persist_creds_to_disk) { | |
| 357 LOG(INFO) << "AuthWatcher::Authenticate called"; | 341 LOG(INFO) << "AuthWatcher::Authenticate called"; |
| 358 | 342 |
| 359 string empty; | 343 string empty; |
| 360 AuthRequest request = { FormatAsEmailAddress(email), password, empty, | 344 AuthRequest request = { FormatAsEmailAddress(email), password, empty, |
| 361 captcha_token, captcha_value, persist_creds_to_disk, | 345 captcha_token, captcha_value, |
| 362 AuthWatcherEvent::USER_INITIATED }; | 346 AuthWatcherEvent::USER_INITIATED }; |
| 363 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, | 347 message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 364 &AuthWatcher::DoAuthenticate, request)); | 348 &AuthWatcher::DoAuthenticate, request)); |
| 365 } | 349 } |
| 366 | 350 |
| 367 void AuthWatcher::ClearAuthenticationData() { | 351 void AuthWatcher::ClearAuthenticationData() { |
| 368 scm_->set_auth_token(std::string()); | 352 scm_->set_auth_token(std::string()); |
| 369 user_settings_->ClearAllServiceTokens(); | 353 user_settings_->ClearAllServiceTokens(); |
| 370 } | 354 } |
| 371 | 355 |
| 372 string AuthWatcher::email() const { | 356 string AuthWatcher::email() const { |
| 373 return gaia_->email(); | 357 return gaia_->email(); |
| 374 } | 358 } |
| 375 | 359 |
| 376 void AuthWatcher::NotifyListeners(AuthWatcherEvent* event) { | 360 void AuthWatcher::NotifyListeners(AuthWatcherEvent* event) { |
| 377 event->trigger = current_attempt_trigger_; | 361 event->trigger = current_attempt_trigger_; |
| 378 channel_->NotifyListeners(*event); | 362 channel_->NotifyListeners(*event); |
| 379 } | 363 } |
| 380 | 364 |
| 381 } // namespace browser_sync | 365 } // namespace browser_sync |
| OLD | NEW |