diff options
author | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-02 15:45:28 +0000 |
---|---|---|
committer | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-02 15:45:28 +0000 |
commit | d7883d0f35538d7f26031b069f941de51ce6c5d0 (patch) | |
tree | 03fbd7f0c6c508f23575624852f6c5c248f5b2d2 /chrome | |
parent | ef8f5ba5bffca6bfea249fec46c7c7419922c6a9 (diff) | |
download | chromium_src-d7883d0f35538d7f26031b069f941de51ce6c5d0.zip chromium_src-d7883d0f35538d7f26031b069f941de51ce6c5d0.tar.gz chromium_src-d7883d0f35538d7f26031b069f941de51ce6c5d0.tar.bz2 |
Revert 43382 - Move fetching of fullfledged auth cookies to a time when we have the user's real profile available. Also, enable the use of a localaccount on Chrome OS
[Valgrind was red, per investigation by rohitrao]
many of the changes here are just callsite fixes, because I changed the signature of a function. I also moved my code into the chromeos namespace, which accounts for several other files. The important stuff is in:
1) google_authenticator*
2) cookie_fetcher*
3) login_utils.cc
Review URL: http://codereview.chromium.org/1515003
TBR=cmasone@google.com
Review URL: http://codereview.chromium.org/1517015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43478 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
27 files changed, 332 insertions, 1073 deletions
diff --git a/chrome/browser/chromeos/login/auth_response_handler.cc b/chrome/browser/chromeos/login/auth_response_handler.cc index d1d3708..fea29af 100644 --- a/chrome/browser/chromeos/login/auth_response_handler.cc +++ b/chrome/browser/chromeos/login/auth_response_handler.cc @@ -4,9 +4,6 @@ #include "chrome/browser/chromeos/login/auth_response_handler.h" -namespace chromeos { - -const int kHttpSuccess = 200; const char AuthResponseHandler::kClientLoginUrl[] = "https://www.google.com/accounts/ClientLogin"; const char AuthResponseHandler::kIssueAuthTokenUrl[] = @@ -16,5 +13,3 @@ const char AuthResponseHandler::kIssueAuthTokenUrl[] = const char AuthResponseHandler::kTokenAuthUrl[] = "https://www.google.com/accounts/TokenAuth?" "continue=http://www.google.com/webhp&source=chromeos&auth="; - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/auth_response_handler.h b/chrome/browser/chromeos/login/auth_response_handler.h index 04e9d1d..0c672c7 100644 --- a/chrome/browser/chromeos/login/auth_response_handler.h +++ b/chrome/browser/chromeos/login/auth_response_handler.h @@ -11,11 +11,6 @@ class GURL; -namespace chromeos { - -// The success code specified by the HTTP spec. -extern const int kHttpSuccess; - class AuthResponseHandler { public: AuthResponseHandler() {} @@ -38,6 +33,4 @@ class AuthResponseHandler { static const char kTokenAuthUrl[]; }; -} // namespace chromeos - #endif // CHROME_BROWSER_CHROMEOS_LOGIN_AUTH_RESPONSE_HANDLER_H_ diff --git a/chrome/browser/chromeos/login/authenticator.h b/chrome/browser/chromeos/login/authenticator.h index cf6531e..d335127 100644 --- a/chrome/browser/chromeos/login/authenticator.h +++ b/chrome/browser/chromeos/login/authenticator.h @@ -8,19 +8,14 @@ #include <vector> #include "base/logging.h" -#include "base/ref_counted.h" -#include "chrome/browser/chrome_thread.h" #include "chrome/browser/chromeos/login/login_status_consumer.h" -class Profile; - -namespace chromeos { - // An interface for objects that will authenticate a Chromium OS user. // When authentication successfully completes, will call -// consumer_->OnLoginSuccess(|username|) on the UI thread. -// On failure, will call consumer_->OnLoginFailure() on the UI thread. -class Authenticator : public base::RefCountedThreadSafe<Authenticator> { +// consumer_->OnLoginSuccess(|username|). +// On failure, will call consumer_->OnLoginFailure(). + +class Authenticator { public: explicit Authenticator(LoginStatusConsumer* consumer) : consumer_(consumer) { @@ -29,16 +24,9 @@ class Authenticator : public base::RefCountedThreadSafe<Authenticator> { // Given a |username| and |password|, this method attempts to authenticate // Returns true if we kick off the attempt successfully and false if we can't. - // Must be called on the FILE thread. - virtual bool Authenticate(Profile* profile, - const std::string& username, + virtual bool Authenticate(const std::string& username, const std::string& password) = 0; - // These methods must be called on the UI thread, as they make DBus calls - // and also call back to the login UI. - virtual void OnLoginSuccess(const std::string& credentials) = 0; - virtual void OnLoginFailure(const std::string& data) = 0; - protected: LoginStatusConsumer* consumer_; @@ -54,29 +42,14 @@ class StubAuthenticator : public Authenticator { virtual ~StubAuthenticator() {} // Returns true after calling OnLoginSuccess(). - virtual bool Authenticate(Profile* profile, - const std::string& username, + virtual bool Authenticate(const std::string& username, const std::string& password) { - username_ = username; - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, - &StubAuthenticator::OnLoginSuccess, - std::string())); + consumer_->OnLoginSuccess(username, std::vector<std::string>()); return true; } - void OnLoginSuccess(const std::string& credentials) { - consumer_->OnLoginSuccess(username_, credentials); - } - - void OnLoginFailure(const std::string& data) {} - private: - std::string username_; DISALLOW_COPY_AND_ASSIGN(StubAuthenticator); }; -} // namespace chromeos - #endif // CHROME_BROWSER_CHROMEOS_LOGIN_AUTHENTICATOR_H_ diff --git a/chrome/browser/chromeos/login/client_login_response_handler.cc b/chrome/browser/chromeos/login/client_login_response_handler.cc index 611662f..97a2edc 100644 --- a/chrome/browser/chromeos/login/client_login_response_handler.cc +++ b/chrome/browser/chromeos/login/client_login_response_handler.cc @@ -12,8 +12,6 @@ #include "chrome/browser/net/url_fetcher.h" #include "net/base/load_flags.h" -namespace chromeos { - // By setting "service=gaia", we get an uber-auth-token back. const char ClientLoginResponseHandler::kService[] = "service=gaia"; @@ -39,11 +37,9 @@ URLFetcher* ClientLoginResponseHandler::Handle( fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES); fetcher->set_upload_data("application/x-www-form-urlencoded", payload_); if (getter_) { - LOG(INFO) << "Fetching"; + LOG(INFO) << "Fetching " << fetcher->url().spec(); fetcher->set_request_context(getter_); fetcher->Start(); } return fetcher; } - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/client_login_response_handler.h b/chrome/browser/chromeos/login/client_login_response_handler.h index c0f1227..2650261 100644 --- a/chrome/browser/chromeos/login/client_login_response_handler.h +++ b/chrome/browser/chromeos/login/client_login_response_handler.h @@ -12,12 +12,6 @@ class URLRequestContextGetter; -namespace chromeos { - -// Handles responses to a fetch executed upon the Google Accounts ClientLogin -// endpoint. The cookies that are sent back in the response body are -// reformatted into a request for an time-limited authorization token, which -// is then sent to the IssueAuthToken endpoint. class ClientLoginResponseHandler : public AuthResponseHandler { public: explicit ClientLoginResponseHandler(URLRequestContextGetter* getter) @@ -43,10 +37,6 @@ class ClientLoginResponseHandler : public AuthResponseHandler { private: std::string payload_; URLRequestContextGetter* getter_; - - DISALLOW_COPY_AND_ASSIGN(ClientLoginResponseHandler); }; -} // namespace chromeos - #endif // CHROME_BROWSER_CHROMEOS_LOGIN_CLIENT_LOGIN_RESPONSE_HANDLER_H_ diff --git a/chrome/browser/chromeos/login/cookie_fetcher.cc b/chrome/browser/chromeos/login/cookie_fetcher.cc deleted file mode 100644 index d27dfed..0000000 --- a/chrome/browser/chromeos/login/cookie_fetcher.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/login/cookie_fetcher.h" - -#include "base/command_line.h" -#include "base/file_path.h" -#include "base/path_service.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/login/client_login_response_handler.h" -#include "chrome/browser/chromeos/login/issue_response_handler.h" -#include "chrome/browser/chromeos/login/login_utils.h" -#include "chrome/browser/net/chrome_url_request_context.h" -#include "chrome/browser/net/url_fetcher.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/profile_manager.h" -#include "chrome/common/chrome_paths.h" -#include "net/url_request/url_request_status.h" - -namespace chromeos { - -CookieFetcher::CookieFetcher(Profile* profile) : profile_(profile) { - CHECK(profile_); - client_login_handler_.reset( - new ClientLoginResponseHandler(profile_->GetRequestContext())); - issue_handler_.reset( - new IssueResponseHandler(profile_->GetRequestContext())); - launcher_.reset(new DelegateImpl); -} - -void CookieFetcher::AttemptFetch(const std::string& credentials) { - LOG(INFO) << "getting auth token..."; - fetcher_.reset(client_login_handler_->Handle(credentials, this)); -} - -void CookieFetcher::OnURLFetchComplete(const URLFetcher* source, - const GURL& url, - const URLRequestStatus& status, - int response_code, - const ResponseCookies& cookies, - const std::string& data) { - if (status.is_success() && response_code == kHttpSuccess) { - if (issue_handler_->CanHandle(url)) { - LOG(INFO) << "Handling auth token"; - fetcher_.reset(issue_handler_->Handle(data, this)); - return; - } - } - LOG(INFO) << "Calling DoLaunch"; - launcher_->DoLaunch(profile_); - delete this; -} - -void CookieFetcher::DelegateImpl::DoLaunch(Profile* profile) { - FilePath user_data_dir; - PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); - ProfileManager* profile_manager = g_browser_process->profile_manager(); - if (profile == profile_manager->GetDefaultProfile(user_data_dir)) { - LoginUtils::DoBrowserLaunch(profile); - } else { - LOG(ERROR) << - "Profile has changed since we started populating it with cookies"; - } -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/cookie_fetcher.h b/chrome/browser/chromeos/login/cookie_fetcher.h deleted file mode 100644 index 434da44..0000000 --- a/chrome/browser/chromeos/login/cookie_fetcher.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_COOKIE_FETCHER_H_ -#define CHROME_BROWSER_CHROMEOS_LOGIN_COOKIE_FETCHER_H_ - -#include <string> -#include "base/scoped_ptr.h" -#include "chrome/browser/chromeos/login/auth_response_handler.h" -#include "chrome/browser/chromeos/login/client_login_response_handler.h" -#include "chrome/browser/chromeos/login/issue_response_handler.h" -#include "chrome/browser/net/url_fetcher.h" -#include "chrome/browser/profile.h" - -namespace chromeos { - -// Given a SID/LSID pair, this class will attempt to turn them into a -// full-fledged set of Google AuthN cookies. -// -// A CookieFetcher manages its own lifecycle. It deletes itself once it's -// done attempting to fetch URLs. -class CookieFetcher : public URLFetcher::Delegate { - public: - // This class is a very thin wrapper around posting a task to the UI thread - // to call LoginUtils::DoBrowserLaunch(). It's here to allow mocking. - // - // In normal usage, instances of this class are owned by a CookieFetcher. - class Delegate { - public: - Delegate() {} - virtual ~Delegate() {} - virtual void DoLaunch(Profile* profile) = 0; - }; - - // |profile| is the Profile whose cookie jar you want the cookies in. - explicit CookieFetcher(Profile* profile); - - // |profile| is the Profile whose cookie jar you want the cookies in. - // Takes ownership of |cl_handler|, |i_handler|, and |launcher|. - CookieFetcher(Profile* profile, - AuthResponseHandler* cl_handler, - AuthResponseHandler* i_handler, - Delegate* launcher) - : profile_(profile), - client_login_handler_(cl_handler), - issue_handler_(i_handler), - launcher_(launcher) { - } - - // Given a newline-delineated SID/LSID pair of Google cookies (like - // those that come back from ClientLogin), try to use them to fetch - // a full-fledged set of Google AuthN cookies. These cookies will wind up - // stored in the cookie jar associated with |profile_|, if we get them. - // Either way, we end up by calling launcher_->DoLaunch() - void AttemptFetch(const std::string& credentials); - - // Overloaded from URLFetcher::Delegate. - virtual void OnURLFetchComplete(const URLFetcher* source, - const GURL& url, - const URLRequestStatus& status, - int response_code, - const ResponseCookies& cookies, - const std::string& data); - - private: - class DelegateImpl : public Delegate { - public: - DelegateImpl() {} - ~DelegateImpl() {} - void DoLaunch(Profile* profile); - private: - DISALLOW_COPY_AND_ASSIGN(DelegateImpl); - }; - - virtual ~CookieFetcher() {} - - scoped_ptr<URLFetcher> fetcher_; - Profile* profile_; - scoped_ptr<AuthResponseHandler> client_login_handler_; - scoped_ptr<AuthResponseHandler> issue_handler_; - scoped_ptr<Delegate> launcher_; - - DISALLOW_COPY_AND_ASSIGN(CookieFetcher); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_LOGIN_COOKIE_FETCHER_H_ diff --git a/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc b/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc deleted file mode 100644 index ecb7d36..0000000 --- a/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <errno.h> -#include <string> -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/login/cookie_fetcher.h" -#include "chrome/browser/chromeos/login/client_login_response_handler.h" -#include "chrome/browser/chromeos/login/issue_response_handler.h" -#include "chrome/browser/chromeos/login/mock_auth_response_handler.h" -#include "chrome/test/testing_profile.h" -#include "chrome/browser/net/url_fetcher.h" -#include "googleurl/src/gurl.h" -#include "net/url_request/url_request_status.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace chromeos { -using ::testing::Return; -using ::testing::Invoke; -using ::testing::Unused; -using ::testing::_; - -class MockDelegate : public CookieFetcher::Delegate { - public: - MockDelegate() {} - virtual ~MockDelegate() {} - MOCK_METHOD1(DoLaunch, void(Profile* profile)); -}; - -class CookieFetcherTest : public ::testing::Test { - public: - CookieFetcherTest() - : iat_url_(AuthResponseHandler::kIssueAuthTokenUrl), - ta_url_(AuthResponseHandler::kTokenAuthUrl), - client_login_data_("SID n' LSID"), - token_("auth token") { - } - - const GURL iat_url_; - const GURL ta_url_; - const std::string client_login_data_; - const std::string token_; - TestingProfile profile_; -}; - -// Check that successful HTTP responses from both end points results in -// the browser window getting put up. -TEST_F(CookieFetcherTest, SuccessfulFetchTest) { - URLRequestStatus status(URLRequestStatus::SUCCESS, 0); - - MockAuthResponseHandler* cl_handler = - new MockAuthResponseHandler(iat_url_, status, kHttpSuccess, token_); - MockAuthResponseHandler* i_handler = - new MockAuthResponseHandler(ta_url_, status, kHttpSuccess, std::string()); - MockDelegate* delegate = new MockDelegate; - - CookieFetcher* cf = new CookieFetcher(NULL, cl_handler, i_handler, delegate); - - EXPECT_CALL(*cl_handler, Handle(client_login_data_, cf)) - .Times(1); - - EXPECT_CALL(*i_handler, CanHandle(iat_url_)) - .WillOnce(Return(true)); - EXPECT_CALL(*i_handler, CanHandle(ta_url_)) - .WillOnce(Return(false)); - EXPECT_CALL(*i_handler, Handle(token_, cf)) - .Times(1); - - EXPECT_CALL(*delegate, DoLaunch(_)) - .Times(1); - - cf->AttemptFetch(client_login_data_); -} - -// Check that a network failure when trying IssueAuthToken results in us bailing -// and putting up the browser window. -TEST_F(CookieFetcherTest, IssueAuthTokenNetworkFailureTest) { - URLRequestStatus failed(URLRequestStatus::FAILED, ECONNRESET); - - MockAuthResponseHandler* cl_handler = - new MockAuthResponseHandler(iat_url_, failed, kHttpSuccess, token_); - MockDelegate* delegate = new MockDelegate; - // I expect nothing in i_handler to get called anyway - MockAuthResponseHandler* i_handler = - new MockAuthResponseHandler(ta_url_, failed, kHttpSuccess, std::string()); - - CookieFetcher* cf = new CookieFetcher(&profile_, - cl_handler, - i_handler, - delegate); - - EXPECT_CALL(*cl_handler, Handle(client_login_data_, cf)) - .Times(1); - EXPECT_CALL(*delegate, DoLaunch(_)) - .Times(1); - - cf->AttemptFetch(client_login_data_); -} - -// Check that a network failure when trying TokenAuth results in us bailing -// and putting up the browser window. -TEST_F(CookieFetcherTest, TokenAuthNetworkFailureTest) { - URLRequestStatus success; - URLRequestStatus failed(URLRequestStatus::FAILED, ECONNRESET); - - MockAuthResponseHandler* cl_handler = - new MockAuthResponseHandler(iat_url_, success, kHttpSuccess, token_); - MockAuthResponseHandler* i_handler = - new MockAuthResponseHandler(ta_url_, failed, 0, std::string()); - MockDelegate* delegate = new MockDelegate; - - CookieFetcher* cf = new CookieFetcher(&profile_, - cl_handler, - i_handler, - delegate); - - EXPECT_CALL(*cl_handler, Handle(client_login_data_, cf)) - .Times(1); - - EXPECT_CALL(*i_handler, CanHandle(iat_url_)) - .WillOnce(Return(true)); - EXPECT_CALL(*i_handler, Handle(token_, cf)) - .Times(1); - - EXPECT_CALL(*delegate, DoLaunch(_)) - .Times(1); - - cf->AttemptFetch(client_login_data_); -} - -// Check that an unsuccessful HTTP response when trying IssueAuthToken results -// in us bailing and putting up the browser window. -TEST_F(CookieFetcherTest, IssueAuthTokenDeniedTest) { - URLRequestStatus success; - - MockAuthResponseHandler* cl_handler = - new MockAuthResponseHandler(iat_url_, success, 403, std::string()); - MockDelegate* delegate = new MockDelegate; - // I expect nothing in i_handler to get called anyway. - MockAuthResponseHandler* i_handler = - new MockAuthResponseHandler(ta_url_, success, 0, std::string()); - - CookieFetcher* cf = new CookieFetcher(&profile_, - cl_handler, - i_handler, - delegate); - - EXPECT_CALL(*cl_handler, Handle(client_login_data_, cf)) - .Times(1); - EXPECT_CALL(*delegate, DoLaunch(_)) - .Times(1); - - cf->AttemptFetch(client_login_data_); -} - -// Check that an unsuccessful HTTP response when trying TokenAuth results -// in us bailing and putting up the browser window. -TEST_F(CookieFetcherTest, TokenAuthDeniedTest) { - URLRequestStatus success; - - MockAuthResponseHandler* cl_handler = - new MockAuthResponseHandler(iat_url_, - success, - kHttpSuccess, - token_); - MockAuthResponseHandler* i_handler = - new MockAuthResponseHandler(ta_url_, success, 403, std::string()); - MockDelegate* delegate = new MockDelegate; - - CookieFetcher* cf = new CookieFetcher(&profile_, - cl_handler, - i_handler, - delegate); - - EXPECT_CALL(*cl_handler, Handle(client_login_data_, cf)) - .Times(1); - - EXPECT_CALL(*i_handler, CanHandle(iat_url_)) - .WillOnce(Return(true)); - EXPECT_CALL(*i_handler, Handle(token_, cf)) - .Times(1); - - EXPECT_CALL(*delegate, DoLaunch(_)) - .Times(1); - - cf->AttemptFetch(client_login_data_); -} - -TEST_F(CookieFetcherTest, ClientLoginResponseHandlerTest) { - ClientLoginResponseHandler handler(NULL); - std::string input("a\nb\n"); - std::string expected("a&b&"); - expected.append(ClientLoginResponseHandler::kService); - - scoped_ptr<URLFetcher> fetcher(handler.Handle(input, NULL)); - EXPECT_EQ(expected, handler.payload()); -} - -TEST_F(CookieFetcherTest, IssueResponseHandlerTest) { - IssueResponseHandler handler(NULL); - std::string input("a\n"); - std::string expected(IssueResponseHandler::kTokenAuthUrl); - expected.append(input); - - scoped_ptr<URLFetcher> fetcher(handler.Handle(input, NULL)); - EXPECT_EQ(expected, handler.token_url()); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index ee29b0f..66a7978 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -10,8 +10,6 @@ #include "base/message_loop.h" #include "base/stl_util-inl.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_thread.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/login_library.h" #include "chrome/browser/chromeos/login/authenticator.h" @@ -19,8 +17,6 @@ #include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/wm_ipc.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/profile_manager.h" #include "views/screen.h" #include "views/widget/widget.h" @@ -122,15 +118,10 @@ void ExistingUserController::Login(UserController* source, DCHECK(i != controllers_.end()); index_of_view_logging_in_ = i - controllers_.begin(); - authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); - Profile* profile = g_browser_process->profile_manager()->GetWizardProfile(); - ChromeThread::PostTask( - ChromeThread::FILE, FROM_HERE, - NewRunnableMethod(authenticator_.get(), - &Authenticator::Authenticate, - profile, - controllers_[index_of_view_logging_in_]->user().email(), - UTF16ToUTF8(password))); + authenticator_.reset(LoginUtils::Get()->CreateAuthenticator(this)); + authenticator_->Authenticate( + controllers_[index_of_view_logging_in_]->user().email(), + UTF16ToUTF8(password)); // Disable clicking on other windows. chromeos::WmIpc::Message message( @@ -139,7 +130,7 @@ void ExistingUserController::Login(UserController* source, chromeos::WmIpc::instance()->SendMessage(message); } -void ExistingUserController::OnLoginFailure(const std::string& error) { +void ExistingUserController::OnLoginFailure(const std::string error) { LOG(INFO) << "OnLoginFailure"; // TODO(sky): alert the user in some way to the failure. @@ -153,14 +144,14 @@ void ExistingUserController::OnLoginFailure(const std::string& error) { chromeos::WmIpc::instance()->SendMessage(message); } -void ExistingUserController::OnLoginSuccess(const std::string& username, - const std::string& credentials) { +void ExistingUserController::OnLoginSuccess(const std::string username, + std::vector<std::string> cookies) { // Hide the login windows now. STLDeleteElements(&controllers_); background_window_->Close(); - chromeos::LoginUtils::Get()->CompleteLogin(username, credentials); + chromeos::LoginUtils::Get()->CompleteLogin(username, cookies); // Delay deletion as we're on the stack. MessageLoop::current()->DeleteSoon(FROM_HERE, this); diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h index 1f4c903..9e587fd 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.h +++ b/chrome/browser/chromeos/login/existing_user_controller.h @@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "base/ref_counted.h" #include "base/task.h" #include "base/timer.h" #include "chrome/browser/chromeos/login/login_status_consumer.h" @@ -17,13 +16,14 @@ #include "chrome/browser/chromeos/wm_message_listener.h" #include "gfx/size.h" +class Authenticator; + namespace views { class Wiget; } namespace chromeos { -class Authenticator; class BackgroundView; // ExistingUserController is used to handle login when someone has already @@ -64,9 +64,9 @@ class ExistingUserController : public WmMessageListener::Observer, virtual void Login(UserController* source, const string16& password); // LoginStatusConsumer: - virtual void OnLoginFailure(const std::string& error); - virtual void OnLoginSuccess(const std::string& username, - const std::string& credentials); + virtual void OnLoginFailure(const std::string error); + virtual void OnLoginSuccess(const std::string username, + std::vector<std::string> cookies); // Bounds of the background window. const gfx::Rect background_bounds_; @@ -79,7 +79,7 @@ class ExistingUserController : public WmMessageListener::Observer, std::vector<UserController*> controllers_; // Used for logging in. - scoped_refptr<Authenticator> authenticator_; + scoped_ptr<Authenticator> authenticator_; // Index of view loggin in. size_t index_of_view_logging_in_; diff --git a/chrome/browser/chromeos/login/google_authenticator.cc b/chrome/browser/chromeos/login/google_authenticator.cc index 15d95c4f..409d382 100644 --- a/chrome/browser/chromeos/login/google_authenticator.cc +++ b/chrome/browser/chromeos/login/google_authenticator.cc @@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/login/google_authenticator.h" - #include <errno.h> #include <string> #include <vector> +#include <time.h> -#include "base/condition_variable.h" -#include "base/lock.h" #include "base/logging.h" #include "base/file_path.h" #include "base/file_util.h" @@ -18,10 +15,13 @@ #include "base/string_util.h" #include "base/third_party/nss/blapi.h" #include "base/third_party/nss/sha256.h" +#include "base/time.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/chromeos/cros/cryptohome_library.h" -#include "chrome/browser/chromeos/login/auth_response_handler.h" +#include "chrome/browser/chromeos/login/client_login_response_handler.h" +#include "chrome/browser/chromeos/login/issue_response_handler.h" +#include "chrome/browser/chromeos/login/google_authenticator.h" #include "chrome/browser/chromeos/login/login_status_consumer.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/url_fetcher.h" @@ -34,56 +34,37 @@ using base::Time; using base::TimeDelta; +using namespace chromeos; using namespace file_util; -namespace chromeos { - -// static -const char GoogleAuthenticator::kCookiePersistence[] = "true"; -// static -const char GoogleAuthenticator::kAccountType[] = "HOSTED_OR_GOOGLE"; -// static -const char GoogleAuthenticator::kSource[] = "chromeos"; -// static const char GoogleAuthenticator::kFormat[] = "Email=%s&" "Passwd=%s&" "PersistentCookie=%s&" "accountType=%s&" "source=%s&"; - -// static -const char GoogleAuthenticator::kSystemSalt[] = "/home/.shadow/salt"; -// static -const char GoogleAuthenticator::kOpenSSLMagic[] = "Salted__"; -// static -const char GoogleAuthenticator::kLocalaccountFile[] = "localaccount"; -// static -const char GoogleAuthenticator::kTmpfsTrigger[] = "incognito"; - +const char GoogleAuthenticator::kCookiePersistence[] = "true"; +const char GoogleAuthenticator::kAccountType[] = "HOSTED_OR_GOOGLE"; +const char GoogleAuthenticator::kSource[] = "chromeos"; +const int GoogleAuthenticator::kHttpSuccess = 200; const int kPassHashLen = 32; -GoogleAuthenticator::GoogleAuthenticator(LoginStatusConsumer* consumer) - : Authenticator(consumer), - fetcher_(NULL), - getter_(NULL), - checked_for_localaccount_(false) { - CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); -} +// Chromium OS system salt stored here +const char GoogleAuthenticator::kSystemSalt[] = "/home/.shadow/salt"; -GoogleAuthenticator::~GoogleAuthenticator() { - ChromeThread::DeleteSoon(ChromeThread::FILE, FROM_HERE, fetcher_); -} +// String that appears at the start of OpenSSL cipher text with embedded salt +const char GoogleAuthenticator::kOpenSSLMagic[] = "Salted__"; -bool GoogleAuthenticator::Authenticate(Profile* profile, - const std::string& username, +bool GoogleAuthenticator::Authenticate(const std::string& username, const std::string& password) { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); + FilePath user_data_dir; + PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); + ProfileManager* profile_manager = g_browser_process->profile_manager(); + Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); getter_ = profile->GetRequestContext(); - fetcher_ = URLFetcher::Create(0, - GURL(AuthResponseHandler::kClientLoginUrl), + fetcher_.reset(new URLFetcher(GURL(AuthResponseHandler::kClientLoginUrl), URLFetcher::POST, - this); + this)); fetcher_->set_request_context(getter_); fetcher_->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES); // TODO(cmasone): be more careful about zeroing memory that stores @@ -95,9 +76,13 @@ bool GoogleAuthenticator::Authenticate(Profile* profile, kAccountType, kSource); fetcher_->set_upload_data("application/x-www-form-urlencoded", body); + fetcher_->Start(); + if (!client_login_handler_.get()) + client_login_handler_.reset(new ClientLoginResponseHandler(getter_)); + if (!issue_handler_.get()) + issue_handler_.reset(new IssueResponseHandler(getter_)); username_.assign(username); StoreHashedPassword(password); - fetcher_->Start(); return true; } @@ -107,70 +92,93 @@ void GoogleAuthenticator::OnURLFetchComplete(const URLFetcher* source, int response_code, const ResponseCookies& cookies, const std::string& data) { - if (status.is_success() && response_code == kHttpSuccess) { - LOG(INFO) << "Online login successful!"; - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, &GoogleAuthenticator::OnLoginSuccess, data)); + if (status.is_success() && response_code == 200) { + if (client_login_handler_->CanHandle(url)) { + fetcher_.reset(client_login_handler_->Handle(data, this)); + } else if (issue_handler_->CanHandle(url)) { + fetcher_.reset(issue_handler_->Handle(data, this)); + } else { + LOG(INFO) << "Online login successful!"; + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableFunction(GoogleAuthenticator::OnLoginSuccess, + consumer_, + username_, + ascii_hash_, + cookies)); + } } else if (!status.is_success()) { LOG(INFO) << "Network fail"; // The fetch failed for network reasons, try offline login. - LoadLocalaccount(kLocalaccountFile); ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, &GoogleAuthenticator::CheckOffline, status)); + NewRunnableFunction(GoogleAuthenticator::CheckOffline, + consumer_, + username_, + ascii_hash_, + status)); } else { - // The fetch succeeded, but ClientLogin said no. - LoadLocalaccount(kLocalaccountFile); + std::string error; + if (status.is_success()) { + // The fetch succeeded, but ClientLogin said no. + error.assign(data); + } else { + // We couldn't hit the network, and offline login failed. + error.assign(strerror(status.os_error())); + } ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, &GoogleAuthenticator::CheckLocalaccount, data)); + NewRunnableFunction( + GoogleAuthenticator::OnLoginFailure, consumer_, error)); } } -void GoogleAuthenticator::OnLoginSuccess(const std::string& data) { - if (CrosLibrary::Get()->GetCryptohomeLibrary()->Mount(username_.c_str(), - ascii_hash_.c_str())) { - consumer_->OnLoginSuccess(username_, data); - } else { - OnLoginFailure("Could not mount cryptohome"); - } +// static +void GoogleAuthenticator::OnLoginSuccess(LoginStatusConsumer* consumer, + const std::string& username, + const std::string& passhash, + const ResponseCookies& cookies) { + if (CrosLibrary::Get()->GetCryptohomeLibrary()->Mount(username.c_str(), + passhash.c_str())) + consumer->OnLoginSuccess(username, cookies); + else + GoogleAuthenticator::OnLoginFailure(consumer, "Could not mount cryptohome"); } -void GoogleAuthenticator::CheckOffline(const URLRequestStatus& status) { - if (CrosLibrary::Get()->GetCryptohomeLibrary()->CheckKey( - username_.c_str(), - ascii_hash_.c_str())) { +// static +void GoogleAuthenticator::CheckOffline(LoginStatusConsumer* consumer, + const std::string& username, + const std::string& passhash, + const URLRequestStatus& status) { + if (CrosLibrary::Get()->GetCryptohomeLibrary()->CheckKey(username.c_str(), + passhash.c_str())) { // The fetch didn't succeed, but offline login did. LOG(INFO) << "Offline login successful!"; - OnLoginSuccess(std::string()); + ResponseCookies cookies; + GoogleAuthenticator::OnLoginSuccess(consumer, + username, + passhash, + cookies); } else { // We couldn't hit the network, and offline login failed. - GoogleAuthenticator::CheckLocalaccount(strerror(status.os_error())); + GoogleAuthenticator::OnLoginFailure(consumer, strerror(status.os_error())); } } -void GoogleAuthenticator::CheckLocalaccount(const std::string& error) { - if (!localaccount_.empty() && localaccount_ == username_ && - CrosLibrary::Get()->GetCryptohomeLibrary()->Mount(kTmpfsTrigger, "")) { - LOG(WARNING) << "Logging in with localaccount: " << localaccount_; - consumer_->OnLoginSuccess(username_, std::string()); - } else { - OnLoginFailure(error); - } -} - -void GoogleAuthenticator::OnLoginFailure(const std::string& data) { - LOG(WARNING) << "Login failed: " << data; +// static +void GoogleAuthenticator::OnLoginFailure(LoginStatusConsumer* consumer, + const std::string& data) { // TODO(cmasone): what can we do to expose these OS/server-side error strings // in an internationalizable way? - consumer_->OnLoginFailure(data); + consumer->OnLoginFailure(data); } -void GoogleAuthenticator::LoadSystemSalt(const FilePath& path) { +void GoogleAuthenticator::LoadSystemSalt(FilePath& path) { if (!system_salt_.empty()) return; + CHECK(PathExists(path)) << path.value() << " does not exist!"; + int64 file_size; CHECK(GetFileSize(path, &file_size)) << "Could not get size of " << path.value(); @@ -182,22 +190,19 @@ void GoogleAuthenticator::LoadSystemSalt(const FilePath& path) { system_salt_.assign(salt, salt + data_read); } -void GoogleAuthenticator::LoadLocalaccount(const std::string& filename) { - if (checked_for_localaccount_) - return; - FilePath localaccount_file; - std::string localaccount; - if (PathService::Get(base::DIR_EXE, &localaccount_file)) { - localaccount_file = localaccount_file.Append(filename); - LOG(INFO) << "looking for localaccount in " << localaccount_file.value(); - - ReadFileToString(localaccount_file, &localaccount); - TrimWhitespaceASCII(localaccount, TRIM_TRAILING, &localaccount); - LOG(INFO) << "Loading localaccount: " << localaccount; +std::string GoogleAuthenticator::SaltAsAscii() { + FilePath salt_path(kSystemSalt); + LoadSystemSalt(salt_path); + unsigned int salt_len = system_salt_.size(); + char ascii_salt[2 * salt_len + 1]; + if (GoogleAuthenticator::BinaryToHex(system_salt_, + salt_len, + ascii_salt, + sizeof(ascii_salt))) { + return std::string(ascii_salt, sizeof(ascii_salt) - 1); } else { - LOG(INFO) << "Assuming no localaccount"; + return std::string(); } - set_localaccount(localaccount); } void GoogleAuthenticator::StoreHashedPassword(const std::string& password) { @@ -230,20 +235,6 @@ void GoogleAuthenticator::StoreHashedPassword(const std::string& password) { ascii_hash_.assign(ascii_buf, sizeof(ascii_buf) - 1); } -std::string GoogleAuthenticator::SaltAsAscii() { - LoadSystemSalt(FilePath(kSystemSalt)); // no-op if it's already loaded. - unsigned int salt_len = system_salt_.size(); - char ascii_salt[2 * salt_len + 1]; - if (GoogleAuthenticator::BinaryToHex(system_salt_, - salt_len, - ascii_salt, - sizeof(ascii_salt))) { - return std::string(ascii_salt, sizeof(ascii_salt) - 1); - } else { - return std::string(); - } -} - // static bool GoogleAuthenticator::BinaryToHex(const std::vector<unsigned char>& binary, const unsigned int binary_len, @@ -256,5 +247,3 @@ bool GoogleAuthenticator::BinaryToHex(const std::vector<unsigned char>& binary, snprintf(hex_string + j, len - j, "%02x", binary[i]); return true; } - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/google_authenticator.h b/chrome/browser/chromeos/login/google_authenticator.h index c89b7f0..f00ae8d 100644 --- a/chrome/browser/chromeos/login/google_authenticator.h +++ b/chrome/browser/chromeos/login/google_authenticator.h @@ -10,38 +10,53 @@ #include "base/basictypes.h" #include "base/file_path.h" #include "base/ref_counted.h" +#include "base/scoped_ptr.h" #include "base/sha2.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/cryptohome_library.h" #include "chrome/browser/chromeos/login/authenticator.h" +#include "chrome/browser/chromeos/login/auth_response_handler.h" #include "chrome/browser/net/url_fetcher.h" -#include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST -// Authenticates a Chromium OS user against the Google Accounts ClientLogin API. - -class Profile; - -namespace chromeos { - -class GoogleAuthenticatorTest; class LoginStatusConsumer; +// Authenticates a Chromium OS user against the Google Accounts ClientLogin API. + class GoogleAuthenticator : public Authenticator, public URLFetcher::Delegate { public: - explicit GoogleAuthenticator(LoginStatusConsumer* consumer); - virtual ~GoogleAuthenticator(); + GoogleAuthenticator(LoginStatusConsumer* consumer, + AuthResponseHandler* cl_handler, + AuthResponseHandler* i_handler) + : Authenticator(consumer), + fetcher_(NULL), + getter_(NULL), + client_login_handler_(cl_handler), + issue_handler_(i_handler) { + CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); + library_ = chromeos::CrosLibrary::Get()->GetCryptohomeLibrary(); + } + + explicit GoogleAuthenticator(LoginStatusConsumer* consumer) + : Authenticator(consumer), + fetcher_(NULL), + getter_(NULL), + client_login_handler_(NULL), + issue_handler_(NULL) { + CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); + library_ = chromeos::CrosLibrary::Get()->GetCryptohomeLibrary(); + } + + virtual ~GoogleAuthenticator() {} // Given a |username| and |password|, this method attempts to authenticate to // the Google accounts servers. The ultimate result is either a callback to // consumer_->OnLoginSuccess() with the |username| and a vector of // authentication cookies or a callback to consumer_->OnLoginFailure() with - // an error message. Uses |profile| when doing URL fetches. - // Should be called on the FILE thread! + // an error message. // // Returns true if the attempt gets sent successfully and false if not. - bool Authenticate(Profile* profile, - const std::string& username, + bool Authenticate(const std::string& username, const std::string& password); // Overridden from URLFetcher::Delegate @@ -55,51 +70,58 @@ class GoogleAuthenticator : public Authenticator, const ResponseCookies& cookies, const std::string& data); + // Returns the ascii encoding of the system salt. + std::string SaltAsAscii(); - - // Public for testing. - void set_system_salt(const std::vector<unsigned char>& new_salt) { - system_salt_ = new_salt; - } - void set_localaccount(const std::string& new_name) { - localaccount_ = new_name; - checked_for_localaccount_ = true; + // I need these static methods so I can PostTasks that use methods + // of sublcasses of LoginStatusConsumer. I can't seem to make + // RunnableMethods out of methods belonging to subclasses without referring + // to the subclasses specifically, and I want to allow mocked out + // LoginStatusConsumers to be used here as well. + static void OnLoginSuccess(LoginStatusConsumer* consumer, + const std::string& username, + const std::string& passhash, + const ResponseCookies& cookies); + static void CheckOffline(LoginStatusConsumer* consumer, + const std::string& username, + const std::string& passhash, + const URLRequestStatus& status); + static void OnLoginFailure(LoginStatusConsumer* consumer, + const std::string& data); + + // Meant for testing. + void set_system_salt(const std::vector<unsigned char>& fake_salt) { + system_salt_ = fake_salt; } void set_username(const std::string& fake_user) { username_ = fake_user; } void set_password_hash(const std::string& fake_hash) { ascii_hash_ = fake_hash; } - // These methods must be called on the UI thread, as they make DBus calls - // and also call back to the login UI. - void OnLoginSuccess(const std::string& credentials); - void CheckOffline(const URLRequestStatus& status); - void CheckLocalaccount(const std::string& error); - void OnLoginFailure(const std::string& data); + private: + static const char kCookiePersistence[]; + static const char kAccountType[]; + static const char kSource[]; + static const char kFormat[]; + static const int kHttpSuccess; + static const char kSystemSalt[]; + static const char kOpenSSLMagic[]; - // The signal to cryptohomed that we want a tmpfs. - // TODO(cmasone): revisit this after cryptohome re-impl - static const char kTmpfsTrigger[]; + chromeos::CryptohomeLibrary* library_; + scoped_ptr<URLFetcher> fetcher_; + URLRequestContextGetter* getter_; + scoped_ptr<AuthResponseHandler> client_login_handler_; + scoped_ptr<AuthResponseHandler> issue_handler_; + std::vector<unsigned char> system_salt_; + std::string username_; + std::string ascii_hash_; - private: // If we don't have the system salt yet, loads it from |path|. - // Should only be called on the FILE thread. - void LoadSystemSalt(const FilePath& path); - - // If we haven't already, looks in a file called |filename| next to - // the browser executable for a "localaccount" name, and retrieves it - // if one is present. If someone attempts to authenticate with this - // username, we will mount a tmpfs for them and let them use the - // browser. - // Should only be called on the FILE thread. - void LoadLocalaccount(const std::string& filename); + void LoadSystemSalt(FilePath& path); // Stores a hash of |password|, salted with the ascii of |system_salt_|. void StoreHashedPassword(const std::string& password); - // Returns the ascii encoding of the system salt. - std::string SaltAsAscii(); - // Converts the binary data |binary| into an ascii hex string and stores // it in |hex_string|. Not guaranteed to be NULL-terminated. // Returns false if |hex_string| is too small, true otherwise. @@ -108,42 +130,7 @@ class GoogleAuthenticator : public Authenticator, char* hex_string, const unsigned int len); - // Constants to use in the ClientLogin request POST body. - static const char kCookiePersistence[]; - static const char kAccountType[]; - static const char kSource[]; - - // The format of said POST body. - static const char kFormat[]; - - // Chromium OS system salt stored here. - static const char kSystemSalt[]; - // String that appears at the start of OpenSSL cipher text with embedded salt. - static const char kOpenSSLMagic[]; - - // Name of a file, next to chrome, that contains a local account username. - static const char kLocalaccountFile[]; - - URLFetcher* fetcher_; - URLRequestContextGetter* getter_; - std::string username_; - std::string ascii_hash_; - std::vector<unsigned char> system_salt_; - std::string localaccount_; - bool checked_for_localaccount_; // needed becasuse empty localaccount_ is ok. - - friend class GoogleAuthenticatorTest; - FRIEND_TEST(GoogleAuthenticatorTest, SaltToAsciiTest); - FRIEND_TEST(GoogleAuthenticatorTest, ReadSaltTest); - FRIEND_TEST(GoogleAuthenticatorTest, ReadLocalaccountTest); - FRIEND_TEST(GoogleAuthenticatorTest, ReadLocalaccountTrailingWSTest); - FRIEND_TEST(GoogleAuthenticatorTest, ReadNoLocalaccountTest); - FRIEND_TEST(GoogleAuthenticatorTest, LoginNetFailureTest); - FRIEND_TEST(GoogleAuthenticatorTest, LoginDeniedTest); - DISALLOW_COPY_AND_ASSIGN(GoogleAuthenticator); }; -} // namespace chromeos - #endif // CHROME_BROWSER_CHROMEOS_LOGIN_GOOGLE_AUTHENTICATOR_H_ diff --git a/chrome/browser/chromeos/login/google_authenticator_unittest.cc b/chrome/browser/chromeos/login/google_authenticator_unittest.cc index a41ebe6..8139abd 100644 --- a/chrome/browser/chromeos/login/google_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/google_authenticator_unittest.cc @@ -2,62 +2,50 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/chromeos/login/google_authenticator.h" +#include "chrome/browser/chromeos/login/client_login_response_handler.h" +#include "chrome/browser/chromeos/login/issue_response_handler.h" + #include <errno.h> #include <string> #include <vector> -#include "base/file_path.h" -#include "base/file_util.h" #include "base/message_loop.h" -#include "base/path_service.h" -#include "base/ref_counted.h" #include "base/scoped_ptr.h" -#include "base/string_util.h" #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" #include "chrome/browser/chromeos/cros/mock_library_loader.h" -#include "chrome/browser/chromeos/login/client_login_response_handler.h" -#include "chrome/browser/chromeos/login/google_authenticator.h" -#include "chrome/browser/chromeos/login/issue_response_handler.h" #include "chrome/browser/chromeos/login/mock_auth_response_handler.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/net/url_fetcher.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/test/testing_profile.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_status.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gmock/include/gmock/gmock.h" -using namespace file_util; +namespace chromeos { using ::testing::AnyNumber; using ::testing::InvokeWithoutArgs; using ::testing::Return; using ::testing::_; -namespace chromeos { - class MockConsumer : public LoginStatusConsumer { public: MockConsumer() {} ~MockConsumer() {} - MOCK_METHOD1(OnLoginFailure, void(const std::string& error)); - MOCK_METHOD2(OnLoginSuccess, void(const std::string& username, - const std::string& data)); + MOCK_METHOD1(OnLoginFailure, void(const std::string error)); + MOCK_METHOD2(OnLoginSuccess, void(const std::string username, + const std::vector<std::string> cookies)); }; class GoogleAuthenticatorTest : public ::testing::Test { public: - GoogleAuthenticatorTest() - : username_("me@nowhere.org"), - bytes_as_ascii_("ffff") { + GoogleAuthenticatorTest() : username_("me@nowhere.org") { memset(fake_hash_, 0, sizeof(fake_hash_)); fake_hash_[0] = 10; fake_hash_[1] = 1; fake_hash_[7] = 10 << 4; hash_ascii_.assign("0a010000000000a0"); - hash_ascii_.append(std::string(16, '0')); - - memset(raw_bytes_, 0xff, sizeof(raw_bytes_)); + hash_ascii_.append(std::string(16,'0')); } ~GoogleAuthenticatorTest() {} @@ -86,39 +74,13 @@ class GoogleAuthenticatorTest : public ::testing::Test { test_api->SetCryptohomeLibrary(NULL); } - FilePath PopulateTempFile(const char* data, int data_len) { - FilePath out; - FILE* tmp_file = CreateAndOpenTemporaryFile(&out); - EXPECT_NE(tmp_file, reinterpret_cast<FILE*>(NULL)); - EXPECT_EQ(WriteFile(out, data, data_len), data_len); - EXPECT_TRUE(CloseFile(tmp_file)); - return out; - } - - FilePath FakeLocalaccountFile(const std::string& ascii) { - FilePath exe_dir; - FilePath local_account_file; - PathService::Get(base::DIR_EXE, &exe_dir); - FILE* tmp_file = CreateAndOpenTemporaryFileInDir(exe_dir, - &local_account_file); - int ascii_len = ascii.length(); - EXPECT_NE(tmp_file, reinterpret_cast<FILE*>(NULL)); - EXPECT_EQ(WriteFile(local_account_file, ascii.c_str(), ascii_len), - ascii_len); - EXPECT_TRUE(CloseFile(tmp_file)); - return local_account_file; - } - unsigned char fake_hash_[32]; std::string hash_ascii_; std::string username_; - std::string data_; ResponseCookies cookies_; // Mocks, destroyed by CrosLibrary class. MockCryptohomeLibrary* mock_library_; MockLibraryLoader* loader_; - char raw_bytes_[2]; - std::string bytes_as_ascii_; }; TEST_F(GoogleAuthenticatorTest, SaltToAsciiTest) { @@ -128,47 +90,30 @@ TEST_F(GoogleAuthenticatorTest, SaltToAsciiTest) { fake_salt[7] = 10 << 4; std::vector<unsigned char> salt_v(fake_salt, fake_salt + sizeof(fake_salt)); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); - auth->set_system_salt(salt_v); + GoogleAuthenticator auth(NULL, NULL, NULL); + auth.set_system_salt(salt_v); - EXPECT_EQ("0a010000000000a0", auth->SaltAsAscii()); + EXPECT_EQ("0a010000000000a0", auth.SaltAsAscii()); } -TEST_F(GoogleAuthenticatorTest, ReadSaltTest) { - FilePath tmp_file_path = PopulateTempFile(raw_bytes_, sizeof(raw_bytes_)); +TEST_F(GoogleAuthenticatorTest, ClientLoginResponseHandlerTest) { + ClientLoginResponseHandler handler(NULL); + std::string input("a\nb\n"); + std::string expected("a&b&"); + expected.append(ClientLoginResponseHandler::kService); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); - auth->LoadSystemSalt(tmp_file_path); - EXPECT_EQ(auth->SaltAsAscii(), bytes_as_ascii_); - Delete(tmp_file_path, false); + scoped_ptr<URLFetcher> fetcher(handler.Handle(input, NULL)); + EXPECT_EQ(expected, handler.payload()); } -TEST_F(GoogleAuthenticatorTest, ReadLocalaccountTest) { - FilePath tmp_file_path = FakeLocalaccountFile(bytes_as_ascii_); +TEST_F(GoogleAuthenticatorTest, IssueResponseHandlerTest) { + IssueResponseHandler handler(NULL); + std::string input("a\n"); + std::string expected(IssueResponseHandler::kTokenAuthUrl); + expected.append(input); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); - auth->LoadLocalaccount(tmp_file_path.BaseName().value()); - EXPECT_EQ(auth->localaccount_, bytes_as_ascii_); - Delete(tmp_file_path, false); -} - -TEST_F(GoogleAuthenticatorTest, ReadLocalaccountTrailingWSTest) { - FilePath tmp_file_path = - FakeLocalaccountFile(StringPrintf("%s\n", bytes_as_ascii_.c_str())); - - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); - auth->LoadLocalaccount(tmp_file_path.BaseName().value()); - EXPECT_EQ(auth->localaccount_, bytes_as_ascii_); - Delete(tmp_file_path, false); -} - -TEST_F(GoogleAuthenticatorTest, ReadNoLocalaccountTest) { - FilePath tmp_file_path = FakeLocalaccountFile(bytes_as_ascii_); - EXPECT_TRUE(Delete(tmp_file_path, false)); // Ensure non-existent file. - - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); - auth->LoadLocalaccount(tmp_file_path.BaseName().value()); - EXPECT_EQ(auth->localaccount_, std::string()); + scoped_ptr<URLFetcher> fetcher(handler.Handle(input, NULL)); + EXPECT_EQ(expected, handler.token_url()); } TEST_F(GoogleAuthenticatorTest, OnLoginSuccessTest) { @@ -178,10 +123,9 @@ TEST_F(GoogleAuthenticatorTest, OnLoginSuccessTest) { EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_)) .WillOnce(Return(true)); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_password_hash(hash_ascii_); - auth->set_username(username_); - auth->OnLoginSuccess(data_); + GoogleAuthenticator auth(&consumer, NULL, NULL); + auth.OnLoginSuccess(&consumer, username_, hash_ascii_, + cookies_); } TEST_F(GoogleAuthenticatorTest, MountFailureTest) { @@ -191,12 +135,12 @@ TEST_F(GoogleAuthenticatorTest, MountFailureTest) { EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_)) .WillOnce(Return(false)); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_password_hash(hash_ascii_); - auth->set_username(username_); - auth->OnLoginSuccess(data_); + GoogleAuthenticator auth(&consumer, NULL, NULL); + auth.OnLoginSuccess(&consumer, username_, hash_ascii_, + cookies_); } +static void Quit() { MessageLoop::current()->Quit(); } TEST_F(GoogleAuthenticatorTest, LoginNetFailureTest) { MessageLoopForUI message_loop; ChromeThread ui_thread(ChromeThread::UI, &message_loop); @@ -209,15 +153,15 @@ TEST_F(GoogleAuthenticatorTest, LoginNetFailureTest) { MockConsumer consumer; EXPECT_CALL(consumer, OnLoginFailure(data)) - .Times(1); + .WillOnce(InvokeWithoutArgs(Quit)); EXPECT_CALL(*mock_library_, CheckKey(username_, hash_ascii_)) .WillOnce(Return(false)); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_password_hash(hash_ascii_); - auth->set_username(username_); - auth->OnURLFetchComplete(NULL, source, status, 0, cookies_, data); - message_loop.RunAllPending(); + GoogleAuthenticator auth(&consumer, NULL, NULL); + auth.set_password_hash(hash_ascii_); + auth.set_username(username_); + auth.OnURLFetchComplete(NULL, source, status, 0, cookies_, data); + MessageLoop::current()->Run(); // So tasks can be posted. } TEST_F(GoogleAuthenticatorTest, LoginDeniedTest) { @@ -231,13 +175,11 @@ TEST_F(GoogleAuthenticatorTest, LoginDeniedTest) { MockConsumer consumer; EXPECT_CALL(consumer, OnLoginFailure(data)) - .Times(1); + .WillOnce(InvokeWithoutArgs(Quit)); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_password_hash(hash_ascii_); - auth->set_username(username_); - auth->OnURLFetchComplete(NULL, source, status, 403, cookies_, data); - message_loop.RunAllPending(); + GoogleAuthenticator auth(&consumer, NULL, NULL); + auth.OnURLFetchComplete(NULL, source, status, 403, cookies_, data); + MessageLoop::current()->Run(); // So tasks can be posted. } TEST_F(GoogleAuthenticatorTest, OfflineLoginTest) { @@ -251,135 +193,77 @@ TEST_F(GoogleAuthenticatorTest, OfflineLoginTest) { URLRequestStatus status(URLRequestStatus::FAILED, error_no); MockConsumer consumer; - EXPECT_CALL(consumer, OnLoginSuccess(username_, data_)) - .Times(1); + EXPECT_CALL(consumer, OnLoginSuccess(username_, cookies_)) + .WillOnce(InvokeWithoutArgs(Quit)); EXPECT_CALL(*mock_library_, CheckKey(username_, hash_ascii_)) .WillOnce(Return(true)); EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_)) .WillOnce(Return(true)); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_password_hash(hash_ascii_); - auth->set_username(username_); - auth->OnURLFetchComplete(NULL, source, status, 0, cookies_, data); - message_loop.RunAllPending(); + GoogleAuthenticator auth(&consumer, NULL, NULL); + auth.set_password_hash(hash_ascii_); + auth.set_username(username_); + auth.OnURLFetchComplete(NULL, source, status, 0, cookies_, data); + MessageLoop::current()->Run(); // So tasks can be posted. } -TEST_F(GoogleAuthenticatorTest, OnlineLoginTest) { +TEST_F(GoogleAuthenticatorTest, ClientLoginPassIssueAuthTokenFailTest) { MessageLoopForUI message_loop; ChromeThread ui_thread(ChromeThread::UI, &message_loop); - GURL source(AuthResponseHandler::kTokenAuthUrl); + std::string data("Error: NO!"); + GURL cl_source(AuthResponseHandler::kClientLoginUrl); + GURL iat_source(AuthResponseHandler::kIssueAuthTokenUrl); URLRequestStatus status(URLRequestStatus::SUCCESS, 0); MockConsumer consumer; - EXPECT_CALL(consumer, OnLoginSuccess(username_, data_)) - .Times(1); - EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_)) + EXPECT_CALL(consumer, OnLoginFailure(data)) + .WillOnce(InvokeWithoutArgs(Quit)); + MockAuthResponseHandler* cl_handler = new MockAuthResponseHandler; + EXPECT_CALL(*cl_handler, CanHandle(cl_source)) .WillOnce(Return(true)); - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_password_hash(hash_ascii_); - auth->set_username(username_); - auth->OnURLFetchComplete(NULL, - source, + GoogleAuthenticator auth(&consumer, + cl_handler, // takes ownership. + new IssueResponseHandler(NULL)); + auth.set_password_hash(hash_ascii_); + auth.set_username(username_); + + EXPECT_CALL(*cl_handler, Handle(_, &auth)) + .WillOnce(Return(new URLFetcher(GURL(""), + URLFetcher::POST, + &auth))); + + auth.OnURLFetchComplete(NULL, + cl_source, status, - kHttpSuccess, + 200, cookies_, std::string()); - message_loop.RunAllPending(); + auth.OnURLFetchComplete(NULL, iat_source, status, 403, cookies_, data); + MessageLoop::current()->Run(); // So tasks can be posted. } -TEST_F(GoogleAuthenticatorTest, LocalaccountLoginTest) { - GURL source(AuthResponseHandler::kTokenAuthUrl); - URLRequestStatus status(URLRequestStatus::SUCCESS, 0); - - std::string trigger(GoogleAuthenticator::kTmpfsTrigger); - - MockConsumer consumer; - EXPECT_CALL(consumer, OnLoginSuccess(username_, _)) - .Times(1); - EXPECT_CALL(*mock_library_, Mount(trigger, _)) - .WillOnce(Return(true)); - - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_password_hash(hash_ascii_); - auth->set_username(username_); - auth->set_localaccount(username_); - - auth->CheckLocalaccount(std::string()); -} - -// Responds as though ClientLogin was successful. -class MockFetcher : public URLFetcher { - public: - MockFetcher(const GURL& url, - URLFetcher::RequestType request_type, - URLFetcher::Delegate* d) - : URLFetcher(url, request_type, d) { - } - ~MockFetcher() {} - void Start() { - GURL source(AuthResponseHandler::kClientLoginUrl); - URLRequestStatus status(URLRequestStatus::SUCCESS, 0); - delegate()->OnURLFetchComplete(NULL, - source, - status, - kHttpSuccess, - ResponseCookies(), - std::string()); - } - private: - DISALLOW_COPY_AND_ASSIGN(MockFetcher); -}; - -class MockFactory : public URLFetcher::Factory { - public: - MockFactory() {} - ~MockFactory() {} - URLFetcher* CreateURLFetcher(int id, - const GURL& url, - URLFetcher::RequestType request_type, - URLFetcher::Delegate* d) { - return new MockFetcher(url, request_type, d); - } - private: - DISALLOW_COPY_AND_ASSIGN(MockFactory); -}; - -TEST_F(GoogleAuthenticatorTest, FullLoginTest) { +TEST_F(GoogleAuthenticatorTest, OnlineLoginTest) { MessageLoopForUI message_loop; ChromeThread ui_thread(ChromeThread::UI, &message_loop); - ChromeThread file_thread(ChromeThread::FILE); - file_thread.Start(); GURL source(AuthResponseHandler::kTokenAuthUrl); URLRequestStatus status(URLRequestStatus::SUCCESS, 0); MockConsumer consumer; - EXPECT_CALL(consumer, OnLoginSuccess(username_, data_)) - .Times(1); - EXPECT_CALL(*mock_library_, Mount(username_, _)) + EXPECT_CALL(consumer, OnLoginSuccess(username_, cookies_)) + .WillOnce(InvokeWithoutArgs(Quit)); + EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_)) .WillOnce(Return(true)); - TestingProfile profile; - - MockFactory factory; - URLFetcher::set_factory(&factory); - std::vector<unsigned char> salt_v(fake_hash_, - fake_hash_ + sizeof(fake_hash_)); - - scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); - auth->set_system_salt(salt_v); - - ChromeThread::PostTask( - ChromeThread::FILE, FROM_HERE, - NewRunnableMethod(auth.get(), - &Authenticator::Authenticate, - &profile, username_, hash_ascii_)); - file_thread.Stop(); - message_loop.RunAllPending(); - URLFetcher::set_factory(NULL); + GoogleAuthenticator auth(&consumer, + new ClientLoginResponseHandler(NULL), + new IssueResponseHandler(NULL)); + auth.set_password_hash(hash_ascii_); + auth.set_username(username_); + auth.OnURLFetchComplete(NULL, source, status, 200, cookies_, std::string()); + MessageLoop::current()->Run(); // So tasks can be posted. } } // namespace chromeos diff --git a/chrome/browser/chromeos/login/issue_response_handler.cc b/chrome/browser/chromeos/login/issue_response_handler.cc index 20fa619..7c0850a 100644 --- a/chrome/browser/chromeos/login/issue_response_handler.cc +++ b/chrome/browser/chromeos/login/issue_response_handler.cc @@ -10,7 +10,8 @@ #include "chrome/browser/net/url_fetcher.h" #include "net/base/load_flags.h" -namespace chromeos { +const int kMaxRedirs = 2; +const int kTimeout = 2; // Overridden from AuthResponseHandler. bool IssueResponseHandler::CanHandle(const GURL& url) { @@ -30,11 +31,8 @@ URLFetcher* IssueResponseHandler::Handle( new URLFetcher(GURL(token_url_), URLFetcher::GET, catcher); fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES); if (getter_) { - LOG(INFO) << "Fetching"; fetcher->set_request_context(getter_); fetcher->Start(); } return fetcher; } - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/issue_response_handler.h b/chrome/browser/chromeos/login/issue_response_handler.h index 4741c80..3153b97 100644 --- a/chrome/browser/chromeos/login/issue_response_handler.h +++ b/chrome/browser/chromeos/login/issue_response_handler.h @@ -12,13 +12,6 @@ class URLRequestContextGetter; -namespace chromeos { - -// Handles responses to a fetch executed upon the Google Accounts IssueAuthToken -// endpoint. The token that's sent back in the response body is used as an -// URL query parameter in a request that, ultimately, results in a full set -// of authorization cookies for Google services being left in the cookie jar -// associated with |getter_|. class IssueResponseHandler : public AuthResponseHandler { public: explicit IssueResponseHandler(URLRequestContextGetter* getter) @@ -31,20 +24,15 @@ class IssueResponseHandler : public AuthResponseHandler { // Overridden from AuthResponseHandler. // Takes in a response from IssueAuthToken, formats into an appropriate query // to sent to TokenAuth, and issues said query. |catcher| will receive - // the response to the fetch. This fetch will follow redirects, which is - // necesary to support GAFYD and corp accounts. + // the response to the fetch. virtual URLFetcher* Handle(const std::string& to_process, URLFetcher::Delegate* catcher); // exposed for testing std::string token_url() { return token_url_; } - private: std::string token_url_; URLRequestContextGetter* getter_; - DISALLOW_COPY_AND_ASSIGN(IssueResponseHandler); }; -} // namespace chromeos - #endif // CHROME_BROWSER_CHROMEOS_LOGIN_ISSUE_RESPONSE_HANDLER_H_ diff --git a/chrome/browser/chromeos/login/login_manager_view.cc b/chrome/browser/chromeos/login/login_manager_view.cc index f89b6b9..c3c3be1 100644 --- a/chrome/browser/chromeos/login/login_manager_view.cc +++ b/chrome/browser/chromeos/login/login_manager_view.cc @@ -18,8 +18,6 @@ #include "base/logging.h" #include "base/process_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_thread.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/login/authentication_notification_details.h" @@ -27,8 +25,6 @@ #include "chrome/browser/chromeos/login/rounded_rect_painter.h" #include "chrome/browser/chromeos/login/screen_observer.h" #include "chrome/browser/chromeos/login/user_manager.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/profile_manager.h" #include "chrome/common/notification_service.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -82,9 +78,9 @@ LoginManagerView::LoginManagerView(ScreenObserver* observer) ALLOW_THIS_IN_INITIALIZER_LIST(focus_grabber_factory_(this)), focus_delayed_(false) { if (kStubOutLogin) - authenticator_ = new StubAuthenticator(this); + authenticator_.reset(new StubAuthenticator(this)); else - authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); + authenticator_.reset(LoginUtils::Get()->CreateAuthenticator(this)); } LoginManagerView::~LoginManagerView() { @@ -324,12 +320,7 @@ void LoginManagerView::Login() { username_field_->SetText(UTF8ToUTF16(username)); } - Profile* profile = g_browser_process->profile_manager()->GetWizardProfile(); - ChromeThread::PostTask( - ChromeThread::FILE, FROM_HERE, - NewRunnableMethod(authenticator_.get(), - &Authenticator::Authenticate, - profile, username, password)); + authenticator_->Authenticate(username, password); } // Sign in button causes a login attempt. @@ -342,7 +333,7 @@ void LoginManagerView::ButtonPressed( } } -void LoginManagerView::OnLoginFailure(const std::string& error) { +void LoginManagerView::OnLoginFailure(const std::string error) { LOG(INFO) << "LoginManagerView: OnLoginFailure() " << error; NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary(); @@ -366,14 +357,13 @@ void LoginManagerView::OnLoginFailure(const std::string& error) { password_field_->RequestFocus(); } -void LoginManagerView::OnLoginSuccess(const std::string& username, - const std::string& credentials) { +void LoginManagerView::OnLoginSuccess(const std::string username, + std::vector<std::string> cookies) { // TODO(cmasone): something sensible if errors occur. if (observer_) { observer_->OnExit(ScreenObserver::LOGIN_SIGN_IN_SELECTED); } - - LoginUtils::Get()->CompleteLogin(username, credentials); + LoginUtils::Get()->CompleteLogin(username, cookies); } void LoginManagerView::ShowError(int error_id) { diff --git a/chrome/browser/chromeos/login/login_manager_view.h b/chrome/browser/chromeos/login/login_manager_view.h index a76196f..53082fd 100644 --- a/chrome/browser/chromeos/login/login_manager_view.h +++ b/chrome/browser/chromeos/login/login_manager_view.h @@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "chrome/browser/chromeos/login/authenticator.h" #include "chrome/browser/chromeos/login/login_status_consumer.h" @@ -72,9 +71,9 @@ class LoginManagerView : public views::View, virtual bool AcceleratorPressed(const views::Accelerator& accelerator); // Overriden from LoginStatusConsumer. - virtual void OnLoginFailure(const std::string& error); - virtual void OnLoginSuccess(const std::string& username, - const std::string& credentials); + virtual void OnLoginFailure(const std::string error); + virtual void OnLoginSuccess(const std::string username, + std::vector<std::string> cookies); protected: // views::View overrides: @@ -134,7 +133,7 @@ class LoginManagerView : public views::View, // (on the hidden tab, for example). bool focus_delayed_; - scoped_refptr<Authenticator> authenticator_; + scoped_ptr<Authenticator> authenticator_; DISALLOW_COPY_AND_ASSIGN(LoginManagerView); }; diff --git a/chrome/browser/chromeos/login/login_manager_view_browsertest.cc b/chrome/browser/chromeos/login/login_manager_view_browsertest.cc index 679051474..b5cb691 100644 --- a/chrome/browser/chromeos/login/login_manager_view_browsertest.cc +++ b/chrome/browser/chromeos/login/login_manager_view_browsertest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/message_loop.h" -#include "chrome/browser/chrome_thread.h" #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" #include "chrome/browser/chromeos/cros/mock_login_library.h" #include "chrome/browser/chromeos/login/login_manager_view.h" @@ -15,12 +14,9 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -class Profile; - namespace chromeos { using ::testing::AnyNumber; -using ::testing::InvokeWithoutArgs; using ::testing::Return; const char kUsername[] = "test_user@gmail.com"; @@ -36,25 +32,15 @@ class MockAuthenticator : public Authenticator { expected_password_(expected_password) { } - // Returns true after posting task to UI thread to call OnLoginSuccess(). - // This is called on the FILE thread now, so we need to do this. - virtual bool Authenticate(Profile* profile, - const std::string& username, + // Returns true after calling OnLoginSuccess(). + virtual bool Authenticate(const std::string& username, const std::string& password) { EXPECT_EQ(expected_username_, username); EXPECT_EQ(expected_password_, password); - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, &MockAuthenticator::OnLoginSuccess, username)); + consumer_->OnLoginSuccess(username, std::vector<std::string>()); return true; } - void OnLoginSuccess(const std::string& username) { - consumer_->OnLoginSuccess(username, std::string()); - } - - void OnLoginFailure(const std::string& data) {} - private: std::string expected_username_; std::string expected_password_; @@ -71,7 +57,7 @@ class MockLoginUtils : public LoginUtils { } virtual void CompleteLogin(const std::string& username, - const std::string& cookies) { + std::vector<std::string> cookies) { EXPECT_EQ(expected_username_, username); } @@ -125,11 +111,6 @@ class LoginManagerViewTest : public WizardInProcessBrowserTest { DISALLOW_COPY_AND_ASSIGN(LoginManagerViewTest); }; -static void Quit() { - LOG(INFO) << "Posting a QuitTask to UI thread"; - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, new MessageLoop::QuitTask); -} IN_PROC_BROWSER_TEST_F(LoginManagerViewTest, TestBasic) { ASSERT_TRUE(controller() != NULL); ASSERT_EQ(controller()->current_screen(), controller()->GetLoginScreen()); @@ -138,19 +119,13 @@ IN_PROC_BROWSER_TEST_F(LoginManagerViewTest, TestBasic) { new MockScreenObserver()); EXPECT_CALL(*mock_screen_observer, OnExit(ScreenObserver::LOGIN_SIGN_IN_SELECTED)) - .WillOnce(InvokeWithoutArgs(Quit)); + .Times(1); LoginManagerView* login = controller()->GetLoginScreen()->view(); login->set_observer(mock_screen_observer.get()); login->SetUsername(kUsername); login->SetPassword(kPassword); - - bool old_state = MessageLoop::current()->NestableTasksAllowed(); - MessageLoop::current()->SetNestableTasksAllowed(true); login->Login(); - MessageLoop::current()->Run(); - MessageLoop::current()->SetNestableTasksAllowed(old_state); - login->set_observer(NULL); } diff --git a/chrome/browser/chromeos/login/login_status_consumer.h b/chrome/browser/chromeos/login/login_status_consumer.h index 5c28c62..bf8f7e3 100644 --- a/chrome/browser/chromeos/login/login_status_consumer.h +++ b/chrome/browser/chromeos/login/login_status_consumer.h @@ -7,19 +7,18 @@ #include <string> -namespace chromeos { - // An interface that defines the callbacks for objects that the // Authenticator class will call to report the success/failure of // authentication for Chromium OS. class LoginStatusConsumer { public: virtual ~LoginStatusConsumer() {} - virtual void OnLoginFailure(const std::string& error) = 0; - virtual void OnLoginSuccess(const std::string& username, - const std::string& credentials) = 0; + // These copy data in, so as to avoid potential object lifetime problems. + virtual void OnLoginFailure(const std::string error) = 0; + virtual void OnLoginSuccess(const std::string username, + std::vector<std::string> cookies) = 0; }; -} // namespace chromeos + #endif // CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_STATUS_CONSUMER_H_ diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index 006f2bb..bc970f6 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -14,7 +14,6 @@ #include "chrome/browser/chromeos/cros/login_library.h" #include "chrome/browser/chromeos/external_cookie_handler.h" #include "chrome/browser/chromeos/login/authentication_notification_details.h" -#include "chrome/browser/chromeos/login/cookie_fetcher.h" #include "chrome/browser/chromeos/login/google_authenticator.h" #include "chrome/browser/chromeos/login/pam_google_authenticator.h" #include "chrome/browser/chromeos/login/user_manager.h" @@ -38,7 +37,7 @@ class LoginUtilsImpl : public LoginUtils { // Invoked after the user has successfully logged in. This launches a browser // and does other bookkeeping after logging in. virtual void CompleteLogin(const std::string& username, - const std::string& credentials); + std::vector<std::string> cookies); // Creates and returns the authenticator to use. The caller owns the returned // Authenticator and must delete it when done. @@ -48,9 +47,9 @@ class LoginUtilsImpl : public LoginUtils { DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl); }; -class LoginUtilsWrapper { +class LoginUtilsWraper { public: - LoginUtilsWrapper() : ptr_(new LoginUtilsImpl) { + LoginUtilsWraper() : ptr_(new LoginUtilsImpl) { } LoginUtils* get() { @@ -64,12 +63,12 @@ class LoginUtilsWrapper { private: scoped_ptr<LoginUtils> ptr_; - DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper); + DISALLOW_COPY_AND_ASSIGN(LoginUtilsWraper); }; void LoginUtilsImpl::CompleteLogin(const std::string& username, - const std::string& credentials) { - LOG(INFO) << "Completing login for " << username; + std::vector<std::string> cookies) { + LOG(INFO) << "LoginManagerView: OnLoginSuccess()"; if (CrosLibrary::Get()->EnsureLoaded()) CrosLibrary::Get()->GetLoginLibrary()->StartSession(username, ""); @@ -84,6 +83,7 @@ void LoginUtilsImpl::CompleteLogin(const std::string& username, Details<AuthenticationNotificationDetails>(&details)); // Now launch the initial browser window. + BrowserInit browser_init; const CommandLine& command_line = *CommandLine::ForCurrentProcess(); FilePath user_data_dir; PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); @@ -91,20 +91,19 @@ void LoginUtilsImpl::CompleteLogin(const std::string& username, // The default profile will have been changed because the ProfileManager // will process the notification that the UserManager sends out. Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); + int return_code; if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kInChromeAuth)) { ExternalCookieHandler::GetCookies(command_line, profile); - DoBrowserLaunch(profile); } else { - // Take the credentials passed in and try to exchange them for - // full-fledged Google authentication cookies. This is - // best-effort; it's possible that we'll fail due to network - // troubles or some such. Either way, |cf| will call - // DoBrowserLaunch on the UI thread when it's done, and then - // delete itself. - CookieFetcher* cf = new CookieFetcher(profile); - cf->AttemptFetch(credentials); + GURL url(ExternalCookieHandler::kGoogleAccountsUrl); + net::CookieOptions options; + options.set_include_httponly(); + profile->GetRequestContext()->GetCookieStore()->SetCookiesWithOptions( + url, cookies, options); } + browser_init.LaunchBrowser(command_line, profile, std::wstring(), true, + &return_code); } Authenticator* LoginUtilsImpl::CreateAuthenticator( @@ -115,22 +114,11 @@ Authenticator* LoginUtilsImpl::CreateAuthenticator( } LoginUtils* LoginUtils::Get() { - return Singleton<LoginUtilsWrapper>::get()->get(); + return Singleton<LoginUtilsWraper>::get()->get(); } void LoginUtils::Set(LoginUtils* mock) { - Singleton<LoginUtilsWrapper>::get()->reset(mock); -} - -void LoginUtils::DoBrowserLaunch(Profile* profile) { - LOG(INFO) << "Launching browser..."; - BrowserInit browser_init; - int return_code; - browser_init.LaunchBrowser(*CommandLine::ForCurrentProcess(), - profile, - std::wstring(), - true, - &return_code); + Singleton<LoginUtilsWraper>::get()->reset(mock); } } // namespace chromeos diff --git a/chrome/browser/chromeos/login/login_utils.h b/chrome/browser/chromeos/login/login_utils.h index 6d7791c..bb1b1d3 100644 --- a/chrome/browser/chromeos/login/login_utils.h +++ b/chrome/browser/chromeos/login/login_utils.h @@ -8,13 +8,15 @@ #include <string> #include <vector> -class Profile; - -namespace chromeos { - class Authenticator; class LoginStatusConsumer; +namespace views { +class Widget; +} + +namespace chromeos { + class LoginUtils { public: // Get LoginUtils singleton object. If it was not set before, new default @@ -24,16 +26,12 @@ class LoginUtils { // Set LoginUtils singleton object for test purpose only! static void Set(LoginUtils* ptr); - // Thin wrapper around BrowserInit::LaunchBrowser(). Meant to be used in a - // Task posted to the UI thread. - static void DoBrowserLaunch(Profile* profile); - virtual ~LoginUtils() {} // Invoked after the user has successfully logged in. This launches a browser // and does other bookkeeping after logging in. virtual void CompleteLogin(const std::string& username, - const std::string& credentials) = 0; + std::vector<std::string> cookies) = 0; // Creates and returns the authenticator to use. The caller owns the returned // Authenticator and must delete it when done. diff --git a/chrome/browser/chromeos/login/mock_auth_response_handler.cc b/chrome/browser/chromeos/login/mock_auth_response_handler.cc deleted file mode 100644 index 8148fc2..0000000 --- a/chrome/browser/chromeos/login/mock_auth_response_handler.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/login/mock_auth_response_handler.h" - -#include <string> - -#include "chrome/browser/net/url_fetcher.h" -#include "googleurl/src/gurl.h" -#include "net/url_request/url_request_status.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace chromeos { - -using ::testing::_; -using ::testing::Invoke; - -MockAuthResponseHandler::MockAuthResponseHandler(const GURL& url, - const URLRequestStatus& status, - const int code, - const std::string& data) - : remote_(url), - status_(status), - http_response_code_(code), - data_(data) { - // Take the args sent to Handle() and pass them to MockNetwork(), which will - // use the data passed to the constructor here to fill out the call to - // OnURLFetchComplete(). - ON_CALL(*this, Handle(_,_)) - .WillByDefault(Invoke(this, &MockAuthResponseHandler::MockNetwork)); -} - -URLFetcher* MockAuthResponseHandler::MockNetwork( - std::string data, - URLFetcher::Delegate* delegate) { - delegate->OnURLFetchComplete(NULL, - remote_, - status_, - http_response_code_, - ResponseCookies(), - data_); - return new URLFetcher(GURL(), URLFetcher::GET, delegate); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/mock_auth_response_handler.h b/chrome/browser/chromeos/login/mock_auth_response_handler.h index dc8a2b8..394dc7c 100644 --- a/chrome/browser/chromeos/login/mock_auth_response_handler.h +++ b/chrome/browser/chromeos/login/mock_auth_response_handler.h @@ -9,44 +9,20 @@ #include <string> -#include "googleurl/src/gurl.h" -#include "net/url_request/url_request_status.h" +#include "base/logging.h" #include "testing/gmock/include/gmock/gmock.h" +class GURL; class URLFetcher; -namespace chromeos { - -// In real AuthResponseHandler subclasses, Handle(data, delegate) -// initiates an HTTP fetch. To mock this, we would like to set up -// appropriate state and then call the OnURLFetchComplete method of -// |delegate| directly. Rather than using some kind of global state, we -// allow a MockAuthResponseHandler to be instantiated with the state we -// want to send to OnURLFetchComplete, and then have Handle() Invoke a helper -// method that will do this work. class MockAuthResponseHandler : public AuthResponseHandler { public: - MockAuthResponseHandler(const GURL& url, - const URLRequestStatus& status, - const int code, - const std::string& data); + MockAuthResponseHandler() {} virtual ~MockAuthResponseHandler() {} MOCK_METHOD1(CanHandle, bool(const GURL& url)); MOCK_METHOD2(Handle, URLFetcher*(const std::string& to_process, URLFetcher::Delegate* catcher)); - - URLFetcher* MockNetwork(std::string data, URLFetcher::Delegate* delegate); - - private: - const GURL remote_; - const URLRequestStatus status_; - const int http_response_code_; - const std::string data_; - - DISALLOW_COPY_AND_ASSIGN(MockAuthResponseHandler); }; -} // namespace chromeos - #endif // CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTH_RESPONSE_HANDLER_H_ diff --git a/chrome/browser/chromeos/login/pam_google_authenticator.cc b/chrome/browser/chromeos/login/pam_google_authenticator.cc index ef344cb..689fde3 100644 --- a/chrome/browser/chromeos/login/pam_google_authenticator.cc +++ b/chrome/browser/chromeos/login/pam_google_authenticator.cc @@ -10,12 +10,8 @@ #include "base/process_util.h" #include "chrome/browser/chromeos/login/pam_google_authenticator.h" #include "chrome/browser/chromeos/login/login_status_consumer.h" -#include "chrome/browser/profile.h" -namespace chromeos { - -bool PamGoogleAuthenticator::Authenticate(Profile* profile, - const std::string& username, +bool PamGoogleAuthenticator::Authenticate(const std::string& username, const std::string& password) { base::ProcessHandle handle; std::vector<std::string> argv; @@ -31,21 +27,9 @@ bool PamGoogleAuthenticator::Authenticate(Profile* profile, bool ret = (base::WaitForExitCode(handle, &child_exit_code) && child_exit_code == 0); - if (ret) { - username_ = username; - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, - &PamGoogleAuthenticator::OnLoginSuccess, - std::string())); - } else { - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(this, - &PamGoogleAuthenticator::OnLoginFailure, - std::string())); - } + if (ret) + consumer_->OnLoginSuccess(username, std::vector<std::string>()); + else + consumer_->OnLoginFailure(""); return ret; } - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/pam_google_authenticator.h b/chrome/browser/chromeos/login/pam_google_authenticator.h index bb5bd79..688f0c3 100644 --- a/chrome/browser/chromeos/login/pam_google_authenticator.h +++ b/chrome/browser/chromeos/login/pam_google_authenticator.h @@ -8,14 +8,9 @@ #include <string> #include "chrome/browser/chromeos/login/authenticator.h" -class Profile; - -namespace chromeos { - class LoginStatusConsumer; -// Authenticates a Chromium OS user against the Google Accounts ClientLogin API -// using a setuid helper binary and a pre-installed pam module. +// Authenticates a Chromium OS user against the Google Accounts ClientLogin API. class PamGoogleAuthenticator : public Authenticator { public: @@ -27,23 +22,11 @@ class PamGoogleAuthenticator : public Authenticator { // Given a |username| and |password|, this method attempts to authenticate to // the Google accounts servers. // Returns true if the attempt gets sent successfully and false if not. - bool Authenticate(Profile* profile, - const std::string& username, + bool Authenticate(const std::string& username, const std::string& password); - void OnLoginSuccess(const std::string& credentials) { - consumer_->OnLoginSuccess(username_, credentials); - } - - void OnLoginFailure(const std::string& data) { - consumer_->OnLoginFailure(data); - } - private: - std::string username_; DISALLOW_COPY_AND_ASSIGN(PamGoogleAuthenticator); }; -} // namespace chromeos - #endif // CHROME_BROWSER_CHROMEOS_LOGIN_PAM_GOOGLE_AUTHENTICATOR_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index fae8a3a..e2e8de1 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -368,14 +368,12 @@ 'browser/chromeos/login/account_screen.cc', 'browser/chromeos/login/account_screen.h', 'browser/chromeos/login/authenticator.h', - 'browser/chromeos/login/auth_response_handler.cc', - 'browser/chromeos/login/auth_response_handler.h', 'browser/chromeos/login/background_view.cc', 'browser/chromeos/login/background_view.h', + 'browser/chromeos/login/auth_response_handler.cc', + 'browser/chromeos/login/auth_response_handler.h', 'browser/chromeos/login/client_login_response_handler.cc', 'browser/chromeos/login/client_login_response_handler.h', - 'browser/chromeos/login/cookie_fetcher.cc', - 'browser/chromeos/login/cookie_fetcher.h', 'browser/chromeos/login/existing_user_controller.cc', 'browser/chromeos/login/existing_user_controller.h', 'browser/chromeos/login/issue_response_handler.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index a51d76e..85eedb7 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -588,9 +588,7 @@ 'browser/chromeos/external_cookie_handler_unittest.cc', 'browser/chromeos/external_metrics_unittest.cc', 'browser/chromeos/gview_request_interceptor_unittest.cc', - 'browser/chromeos/login/cookie_fetcher_unittest.cc', 'browser/chromeos/login/google_authenticator_unittest.cc', - 'browser/chromeos/login/mock_auth_response_handler.cc', 'browser/chromeos/options/language_config_view_test.cc', 'browser/chromeos/pipe_reader_unittest.cc', 'browser/chromeos/status/language_menu_l10n_util_unittest.cc', |