// Copyright (c) 2011 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/parallel_authenticator.h"
#include <string>
#include <vector>
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
#include "chrome/browser/chromeos/cros/mock_library_loader.h"
#include "chrome/browser/chromeos/login/mock_auth_response_handler.h"
#include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
#include "chrome/browser/chromeos/login/mock_url_fetchers.h"
#include "chrome/browser/chromeos/login/test_attempt_state.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h"
#include "chrome/common/net/url_fetcher.h"
#include "chrome/test/testing_profile.h"
#include "chrome/test/thread_test_helper.h"
#include "content/browser/browser_thread.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using namespace file_util;
using ::testing::AnyNumber;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::_;
namespace chromeos {
class ResolveChecker : public ThreadTestHelper {
public:
ResolveChecker(TestAttemptState* state,
ParallelAuthenticator* auth,
ParallelAuthenticator::AuthState expected)
: ThreadTestHelper(BrowserThread::IO),
state_(state),
auth_(auth),
expected_(expected) {
}
~ResolveChecker() {}
virtual void RunTest() {
auth_->set_attempt_state(state_);
set_test_result(expected_ == auth_->ResolveState());
}
private:
TestAttemptState* state_;
ParallelAuthenticator* auth_;
ParallelAuthenticator::AuthState expected_;
};
class ParallelAuthenticatorTest : public ::testing::Test {
public:
ParallelAuthenticatorTest()
: message_loop_(MessageLoop::TYPE_UI),
ui_thread_(BrowserThread::UI, &message_loop_),
file_thread_(BrowserThread::FILE),
io_thread_(BrowserThread::IO),
username_("me@nowhere.org"),
password_("fakepass") {
hash_ascii_.assign("0a010000000000a0");
hash_ascii_.append(std::string(16, '0'));
}
~ParallelAuthenticatorTest() {}
virtual void SetUp() {
chromeos::CrosLibrary::TestApi* test_api =
chromeos::CrosLibrary::Get()->GetTestApi();
loader_ = new MockLibraryLoader();
ON_CALL(*loader_, Load(_))
.WillByDefault(Return(true));
EXPECT_CALL(*loader_, Load(_))
.Times(AnyNumber());
test_api->SetLibraryLoader(loader_, true);
mock_library_ = new MockCryptohomeLibrary();
test_api->SetCryptohomeLibrary(mock_library_, true);
file_thread_.Start();
io_thread_.Start();
auth_ = new ParallelAuthenticator(&consumer_);
state_.reset(new TestAttemptState(username_,
password_,
hash_ascii_,
"",
"",
false));
}
// Tears down the test fixture.
virtual void TearDown() {
// Prevent bogus gMock leak check from firing.
chromeos::CrosLibrary::TestApi* test_api =
chromeos::CrosLibrary::Get()->GetTestApi();
test_api->SetLibraryLoader(NULL, false);
test_api->SetCryptohomeLibrary(NULL, false);
}
FilePath PopulateTempFile(const char* data, int data_len) {
FilePath out;
FILE* tmp_file = CreateAndOpenTemporaryFile(&out);
EXPECT_NE(tmp_file, static_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, static_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;
}
void ReadLocalaccountFile(ParallelAuthenticator* auth,
const std::string& filename) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(auth,
&ParallelAuthenticator::LoadLocalaccount,
filename));
file_thread_.Stop();
file_thread_.Start();
}
// Allow test to fail and exit gracefully, even if OnLoginFailure()
// wasn't supposed to happen.
void FailOnLoginFailure() {
ON_CALL(consumer_, OnLoginFailure(_))
.WillByDefault(Invoke(MockConsumer::OnFailQuitAndFail));
}
// Allow test to fail and exit gracefully, even if OnLoginSuccess()
// wasn't supposed to happen.
void FailOnLoginSuccess() {
ON_CALL(consumer_, OnLoginSuccess(_, _, _, _))
.WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail));
}
// Allow test to fail and exit gracefully, even if
// OnOffTheRecordLoginSuccess() wasn't supposed to happen.
void FailOnGuestLoginSuccess() {
ON_CALL(consumer_, OnOffTheRecordLoginSuccess())
.WillByDefault(Invoke(MockConsumer::OnGuestSuccessQuitAndFail));
}
void ExpectLoginFailure(const LoginFailure& failure) {
EXPECT_CALL(consumer_, OnLoginFailure(failure))
.WillOnce(Invoke(MockConsumer::OnFailQuit))
.RetiresOnSaturation();
}
void ExpectLoginSuccess(const std::string& username,
const std::string& password,
const GaiaAuthConsumer::ClientLoginResult& result,
bool pending) {
EXPECT_CALL(consumer_, OnLoginSuccess(username, password, result, pending))
.WillOnce(Invoke(MockConsumer::OnSuccessQuit))
.RetiresOnSaturation();
}
void ExpectGuestLoginSuccess() {
EXPECT_CALL(consumer_, OnOffTheRecordLoginSuccess())
.WillOnce(Invoke(MockConsumer::OnGuestSuccessQuit))
.RetiresOnSaturation();
}
void ExpectPasswordChange() {
EXPECT_CALL(consumer_, OnPasswordChangeDetected(result_))
.WillOnce(Invoke(MockConsumer::OnMigrateQuit))
.RetiresOnSaturation();
}
void RunResolve(ParallelAuthenticator* auth, MessageLoop* loop) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(auth, &ParallelAuthenticator::Resolve));
loop->Run();
}
void SetAttemptState(ParallelAuthenticator* auth, TestAttemptState* state) {
auth->set_attempt_state(state);
}
MessageLoop message_loop_;
BrowserThread ui_thread_;
BrowserThread file_thread_;
BrowserThread io_thread_;
std::string username_;
std::string password_;
std::string hash_ascii_;
GaiaAuthConsumer::ClientLoginResult result_;
// Mocks, destroyed by CrosLibrary class.
MockCryptohomeLibrary* mock_library_;
MockLibraryLoader* loader_;
MockConsumer consumer_;
scoped_refptr<ParallelAuthenticator> auth_;
scoped_ptr<TestAttemptState> state_;
};
TEST_F(ParallelAuthenticatorTest, SaltToAscii) {
unsigned char fake_salt[8] = { 0 };
fake_salt[0] = 10;
fake_salt[1] = 1;
fake_salt[7] = 10 << 4;
std::vector<unsigned char> salt_v(fake_salt, fake_salt + sizeof(fake_salt));
ON_CALL(*mock_library_, GetSystemSalt())
.WillByDefault(Return(salt_v));
EXPECT_CALL(*mock_library_, GetSystemSalt())
.Times(1)
.RetiresOnSaturation();
EXPECT_EQ("0a010000000000a0", auth_->SaltAsAscii());
}
TEST_F(ParallelAuthenticatorTest, ReadLocalaccount) {
FilePath tmp_file_path = FakeLocalaccountFile(username_);
ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value());
EXPECT_EQ(auth_->localaccount_, username_);
Delete(tmp_file_path, false);
}
TEST_F(ParallelAuthenticatorTest, ReadLocalaccountTrailingWS) {
FilePath tmp_file_path =
FakeLocalaccountFile(base::StringPrintf("%s\n", username_.c_str()));
ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value());
EXPECT_EQ(auth_->localaccount_, username_);
Delete(tmp_file_path, false);
}
TEST_F(ParallelAuthenticatorTest, ReadNoLocalaccount) {
FilePath tmp_file_path = FakeLocalaccountFile(username_);
EXPECT_TRUE(Delete(tmp_file_path, false)); // Ensure non-existent file.
ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value());
EXPECT_EQ(auth_->localaccount_, std::string());
}
TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) {
EXPECT_CALL(consumer_, OnLoginSuccess(username_, password_, result_, false))
.Times(1)
.RetiresOnSaturation();
SetAttemptState(auth_, state_.release());
auth_->OnLoginSuccess(result_, false);
}
TEST_F(ParallelAuthenticatorTest, OnPasswordChangeDetected) {
EXPECT_CALL(consumer_, OnPasswordChangeDetected(result_))
.Times(1)
.RetiresOnSaturation();
SetAttemptState(auth_, state_.release());
auth_->OnPasswordChangeDetected(result_);
}
TEST_F(ParallelAuthenticatorTest, ResolveNothingDone) {
scoped_refptr<ResolveChecker> checker(
new ResolveChecker(state_.release(),
auth_.get(),
ParallelAuthenticator::CONTINUE));
EXPECT_TRUE(checker->Run());
}
TEST_F(ParallelAuthenticatorTest, ResolvePossiblePwChange) {
// Set up state as though a cryptohome mount attempt has occurred
// and been rejected.
state_->PresetCryptohomeStatus(false,
chromeos::kCryptohomeMountErrorKeyFailure);
scoped_refptr<ResolveChecker> checker(
new ResolveChecker(state_.release(),
auth_.get(),
ParallelAuthenticator::POSSIBLE_PW_CHANGE));
EXPECT_TRUE(checker->Run());
}
TEST_F(ParallelAuthenticatorTest, DriveFailedMount) {
FailOnLoginSuccess();
ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME));
// Set up state as though a cryptohome mount attempt has occurred
// and failed.
state_->PresetCryptohomeStatus(false, 0);
SetAttemptState(auth_, state_.release());
RunResolve(auth_.get(), &message_loop_);
}
TEST_F(ParallelAuthenticatorTest, DriveGuestLogin) {
ExpectGuestLoginSuccess();
FailOnLoginFailure();
// Set up mock cryptohome library to respond as though a tmpfs mount
// attempt has occurred and succeeded.
mock_library_->SetUp(true, 0);
EXPECT_CALL(*mock_library_, AsyncMountForBwsi(_))
.Times(1)
.RetiresOnSaturation();
auth_->LoginOffTheRecord();
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveGuestLoginButFail) {
FailOnGuestLoginSuccess();
ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS));
// Set up mock cryptohome library to respond as though a tmpfs mount
// attempt has occurred and failed.
mock_library_->SetUp(false, 0);
EXPECT_CALL(*mock_library_, AsyncMountForBwsi(_))
.Times(1)
.RetiresOnSaturation();
auth_->LoginOffTheRecord();
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveDataResync) {
ExpectLoginSuccess(username_, password_, result_, false);
FailOnLoginFailure();
// Set up mock cryptohome library to respond successfully to a cryptohome
// remove attempt and a cryptohome create attempt (specified by the |true|
// argument to AsyncMount).
mock_library_->SetUp(true, 0);
EXPECT_CALL(*mock_library_, AsyncRemove(username_, _))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, AsyncMount(username_, hash_ascii_, true, _))
.Times(1)
.RetiresOnSaturation();
state_->PresetOnlineLoginStatus(result_, LoginFailure::None());
SetAttemptState(auth_, state_.release());
auth_->ResyncEncryptedData(result_);
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveResyncFail) {
FailOnLoginSuccess();
ExpectLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED));
// Set up mock cryptohome library to fail a cryptohome remove attempt.
mock_library_->SetUp(false, 0);
EXPECT_CALL(*mock_library_, AsyncRemove(username_, _))
.Times(1)
.RetiresOnSaturation();
SetAttemptState(auth_, state_.release());
auth_->ResyncEncryptedData(result_);
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveRequestOldPassword) {
FailOnLoginSuccess();
ExpectPasswordChange();
state_->PresetCryptohomeStatus(false,
chromeos::kCryptohomeMountErrorKeyFailure);
state_->PresetOnlineLoginStatus(result_, LoginFailure::None());
SetAttemptState(auth_, state_.release());
RunResolve(auth_.get(), &message_loop_);
}
TEST_F(ParallelAuthenticatorTest, DriveDataRecover) {
ExpectLoginSuccess(username_, password_, result_, false);
FailOnLoginFailure();
// Set up mock cryptohome library to respond successfully to a key migration.
mock_library_->SetUp(true, 0);
EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_, _, hash_ascii_, _))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, AsyncMount(username_, hash_ascii_, false, _))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, GetSystemSalt())
.WillOnce(Return(CryptohomeBlob(2, 0)))
.RetiresOnSaturation();
state_->PresetOnlineLoginStatus(result_, LoginFailure::None());
SetAttemptState(auth_, state_.release());
auth_->RecoverEncryptedData(std::string(), result_);
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveDataRecoverButFail) {
FailOnLoginSuccess();
ExpectPasswordChange();
// Set up mock cryptohome library to fail a key migration attempt,
// asserting that the wrong password was used.
mock_library_->SetUp(false, chromeos::kCryptohomeMountErrorKeyFailure);
EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_, _, hash_ascii_, _))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, GetSystemSalt())
.WillOnce(Return(CryptohomeBlob(2, 0)))
.RetiresOnSaturation();
SetAttemptState(auth_, state_.release());
auth_->RecoverEncryptedData(std::string(), result_);
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, ResolveNoMount) {
// Set up state as though a cryptohome mount attempt has occurred
// and been rejected because the user doesn't exist.
state_->PresetCryptohomeStatus(
false,
chromeos::kCryptohomeMountErrorUserDoesNotExist);
scoped_refptr<ResolveChecker> checker(
new ResolveChecker(state_.release(),
auth_.get(),
ParallelAuthenticator::NO_MOUNT));
EXPECT_TRUE(checker->Run());
}
TEST_F(ParallelAuthenticatorTest, ResolveCreateNew) {
// Set up state as though a cryptohome mount attempt has occurred
// and been rejected because the user doesn't exist; additionally,
// an online auth attempt has completed successfully.
state_->PresetCryptohomeStatus(
false,
chromeos::kCryptohomeMountErrorUserDoesNotExist);
state_->PresetOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(),
LoginFailure::None());
scoped_refptr<ResolveChecker> checker(
new ResolveChecker(state_.release(),
auth_.get(),
ParallelAuthenticator::CREATE_NEW));
EXPECT_TRUE(checker->Run());
}
TEST_F(ParallelAuthenticatorTest, DriveCreateForNewUser) {
ExpectLoginSuccess(username_, password_, result_, false);
FailOnLoginFailure();
// Set up mock cryptohome library to respond successfully to a cryptohome
// create attempt (specified by the |true| argument to AsyncMount).
mock_library_->SetUp(true, 0);
EXPECT_CALL(*mock_library_, AsyncMount(username_, hash_ascii_, true, _))
.Times(1)
.RetiresOnSaturation();
// Set up state as though a cryptohome mount attempt has occurred
// and been rejected because the user doesn't exist; additionally,
// an online auth attempt has completed successfully.
state_->PresetCryptohomeStatus(
false,
chromeos::kCryptohomeMountErrorUserDoesNotExist);
state_->PresetOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(),
LoginFailure::None());
SetAttemptState(auth_, state_.release());
RunResolve(auth_.get(), &message_loop_);
}
TEST_F(ParallelAuthenticatorTest, DriveOfflineLogin) {
ExpectLoginSuccess(username_, password_, result_, false);
FailOnLoginFailure();
// Set up state as though a cryptohome mount attempt has occurred and
// succeeded.
state_->PresetCryptohomeStatus(true, 0);
GoogleServiceAuthError error =
GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET);
state_->PresetOnlineLoginStatus(result_,
LoginFailure::FromNetworkAuthFailure(error));
SetAttemptState(auth_, state_.release());
RunResolve(auth_.get(), &message_loop_);
}
TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginDelayedOnline) {
ExpectLoginSuccess(username_, password_, result_, true);
FailOnLoginFailure();
// Set up state as though a cryptohome mount attempt has occurred and
// succeeded.
state_->PresetCryptohomeStatus(true, 0);
// state_ is released further down.
SetAttemptState(auth_, state_.get());
RunResolve(auth_.get(), &message_loop_);
// Offline login has completed, so now we "complete" the online request.
GoogleServiceAuthError error(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error);
state_.release()->PresetOnlineLoginStatus(result_, failure);
ExpectLoginFailure(failure);
RunResolve(auth_.get(), &message_loop_);
}
TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetNewPassword) {
ExpectLoginSuccess(username_, password_, result_, true);
FailOnLoginFailure();
// Set up mock cryptohome library to respond successfully to a key migration.
mock_library_->SetUp(true, 0);
EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_,
state_->ascii_hash,
_,
_))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, GetSystemSalt())
.WillOnce(Return(CryptohomeBlob(2, 0)))
.RetiresOnSaturation();
// Set up state as though a cryptohome mount attempt has occurred and
// succeeded; also, an online request that never made it.
state_->PresetCryptohomeStatus(true, 0);
// state_ is released further down.
SetAttemptState(auth_, state_.get());
RunResolve(auth_.get(), &message_loop_);
// Offline login has completed, so now we "complete" the online request.
GoogleServiceAuthError error(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error);
state_.release()->PresetOnlineLoginStatus(result_, failure);
ExpectLoginFailure(failure);
RunResolve(auth_.get(), &message_loop_);
// After the request below completes, OnLoginSuccess gets called again.
ExpectLoginSuccess(username_, password_, result_, false);
MockFactory<SuccessFetcher> factory;
URLFetcher::set_factory(&factory);
TestingProfile profile;
auth_->RetryAuth(&profile,
username_,
std::string(),
std::string(),
std::string());
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetCaptchad) {
ExpectLoginSuccess(username_, password_, result_, true);
FailOnLoginFailure();
EXPECT_CALL(*mock_library_, GetSystemSalt())
.WillOnce(Return(CryptohomeBlob(2, 0)))
.RetiresOnSaturation();
// Set up state as though a cryptohome mount attempt has occurred and
// succeeded; also, an online request that never made it.
state_->PresetCryptohomeStatus(true, 0);
// state_ is released further down.
SetAttemptState(auth_, state_.get());
RunResolve(auth_.get(), &message_loop_);
// Offline login has completed, so now we "complete" the online request.
GoogleServiceAuthError error(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error);
state_.release()->PresetOnlineLoginStatus(result_, failure);
ExpectLoginFailure(failure);
RunResolve(auth_.get(), &message_loop_);
// After the request below completes, OnLoginSuccess gets called again.
failure = LoginFailure::FromNetworkAuthFailure(
GoogleServiceAuthError::FromCaptchaChallenge(
CaptchaFetcher::GetCaptchaToken(),
GURL(CaptchaFetcher::GetCaptchaUrl()),
GURL(CaptchaFetcher::GetUnlockUrl())));
ExpectLoginFailure(failure);
MockFactory<CaptchaFetcher> factory;
URLFetcher::set_factory(&factory);
TestingProfile profile;
auth_->RetryAuth(&profile,
username_,
std::string(),
std::string(),
std::string());
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveOnlineLogin) {
GaiaAuthConsumer::ClientLoginResult success("sid", "lsid", "", "");
ExpectLoginSuccess(username_, password_, success, false);
FailOnLoginFailure();
// Set up state as though a cryptohome mount attempt has occurred and
// succeeded.
state_->PresetCryptohomeStatus(true, 0);
state_->PresetOnlineLoginStatus(success, LoginFailure::None());
SetAttemptState(auth_, state_.release());
RunResolve(auth_.get(), &message_loop_);
}
TEST_F(ParallelAuthenticatorTest, DriveNeedNewPassword) {
FailOnLoginSuccess(); // Set failing on success as the default...
// ...but expect ONE successful login first.
ExpectLoginSuccess(username_, password_, result_, true);
GoogleServiceAuthError error(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error);
ExpectLoginFailure(failure);
// Set up state as though a cryptohome mount attempt has occurred and
// succeeded.
state_->PresetCryptohomeStatus(true, 0);
state_->PresetOnlineLoginStatus(result_, failure);
SetAttemptState(auth_, state_.release());
RunResolve(auth_.get(), &message_loop_);
}
TEST_F(ParallelAuthenticatorTest, DriveLocalLogin) {
ExpectGuestLoginSuccess();
FailOnLoginFailure();
// Set up mock cryptohome library to respond as though a tmpfs mount
// attempt has occurred and succeeded.
mock_library_->SetUp(true, 0);
EXPECT_CALL(*mock_library_, AsyncMountForBwsi(_))
.Times(1)
.RetiresOnSaturation();
// Pre-set test state as though an online login attempt failed to complete,
// and that a cryptohome mount attempt failed because the user doesn't exist.
GoogleServiceAuthError error =
GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET);
LoginFailure failure =
LoginFailure::FromNetworkAuthFailure(error);
state_->PresetOnlineLoginStatus(result_, failure);
state_->PresetCryptohomeStatus(
false,
chromeos::kCryptohomeMountErrorUserDoesNotExist);
SetAttemptState(auth_, state_.release());
// Deal with getting the localaccount file
FilePath tmp_file_path = FakeLocalaccountFile(username_);
ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value());
RunResolve(auth_.get(), &message_loop_);
Delete(tmp_file_path, false);
}
TEST_F(ParallelAuthenticatorTest, DriveUnlock) {
ExpectLoginSuccess(username_, std::string(), result_, false);
FailOnLoginFailure();
// Set up mock cryptohome library to respond successfully to a cryptohome
// key-check attempt.
mock_library_->SetUp(true, 0);
EXPECT_CALL(*mock_library_, AsyncCheckKey(username_, _, _))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, GetSystemSalt())
.WillOnce(Return(CryptohomeBlob(2, 0)))
.RetiresOnSaturation();
auth_->AuthenticateToUnlock(username_, "");
message_loop_.Run();
}
TEST_F(ParallelAuthenticatorTest, DriveLocalUnlock) {
ExpectLoginSuccess(username_, std::string(), result_, false);
FailOnLoginFailure();
// Set up mock cryptohome library to fail a cryptohome key-check
// attempt.
mock_library_->SetUp(false, 0);
EXPECT_CALL(*mock_library_, AsyncCheckKey(username_, _, _))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, GetSystemSalt())
.WillOnce(Return(CryptohomeBlob(2, 0)))
.RetiresOnSaturation();
// Deal with getting the localaccount file
FilePath tmp_file_path = FakeLocalaccountFile(username_);
ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value());
auth_->AuthenticateToUnlock(username_, "");
message_loop_.Run();
Delete(tmp_file_path, false);
}
} // namespace chromeos