Commit ab0dd766 authored by dvadym's avatar dvadym Committed by Commit bot

Integration of PasswordReuseDetector into PasswordStore.

This CL includes:
 1.Creating, initializing and updating PasswordReuseDetector instance as a member of PasswordStore.
 2.Introducing all flows for checking password reuse with CheckReuse() of ChromePasswordManagerClient and receiving response.

ChromePasswordManagerClient.CheckReuse() is not called now, it will be implemented in next CLs.

BUG=657041

Review-Url: https://codereview.chromium.org/2585253002
Cr-Commit-Position: refs/heads/master@{#440865}
parent 9bb17e2c
...@@ -116,6 +116,16 @@ class ManagePasswordsBubbleModelTest : public ::testing::Test { ...@@ -116,6 +116,16 @@ class ManagePasswordsBubbleModelTest : public ::testing::Test {
password_manager::BuildPasswordStore< password_manager::BuildPasswordStore<
content::BrowserContext, content::BrowserContext,
testing::StrictMock<password_manager::MockPasswordStore>>); testing::StrictMock<password_manager::MockPasswordStore>>);
#if !defined(OS_MACOSX)
// TODO(crbug.com/668155): Remove conditional compilation when
// PasswordReuseDetector initialization will be implemented for Mac.
// The call of FillAutofillableLogins is caused by a posted task for an
// initialization of PasswordReuseDetector in the call of
// BuildPasswordStore() in the previous code. There is no thread race since
// unit tests run in one thread, and any post task will be executed after
// finishing the current function.
EXPECT_CALL(*GetStore(), FillAutofillableLogins(_));
#endif
} }
void TearDown() override { void TearDown() override {
......
...@@ -99,6 +99,8 @@ static_library("browser") { ...@@ -99,6 +99,8 @@ static_library("browser") {
"password_reuse_detection_manager.h", "password_reuse_detection_manager.h",
"password_reuse_detector.cc", "password_reuse_detector.cc",
"password_reuse_detector.h", "password_reuse_detector.h",
"password_reuse_detector_consumer.cc",
"password_reuse_detector_consumer.h",
"password_store.cc", "password_store.cc",
"password_store.h", "password_store.h",
"password_store_change.cc", "password_store_change.cc",
......
...@@ -104,4 +104,8 @@ MockPasswordStoreObserver::MockPasswordStoreObserver() {} ...@@ -104,4 +104,8 @@ MockPasswordStoreObserver::MockPasswordStoreObserver() {}
MockPasswordStoreObserver::~MockPasswordStoreObserver() {} MockPasswordStoreObserver::~MockPasswordStoreObserver() {}
MockPasswordReuseDetectorConsumer::MockPasswordReuseDetectorConsumer() {}
MockPasswordReuseDetectorConsumer::~MockPasswordReuseDetectorConsumer() {}
} // namespace password_manager } // namespace password_manager
...@@ -83,6 +83,14 @@ class MockPasswordStoreObserver : public PasswordStore::Observer { ...@@ -83,6 +83,14 @@ class MockPasswordStoreObserver : public PasswordStore::Observer {
MOCK_METHOD1(OnLoginsChanged, void(const PasswordStoreChangeList& changes)); MOCK_METHOD1(OnLoginsChanged, void(const PasswordStoreChangeList& changes));
}; };
class MockPasswordReuseDetectorConsumer : public PasswordReuseDetectorConsumer {
public:
MockPasswordReuseDetectorConsumer();
~MockPasswordReuseDetectorConsumer() override;
MOCK_METHOD2(OnReuseFound, void(const base::string16&, const std::string&));
};
} // namespace password_manager } // namespace password_manager
#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_TEST_UTILS_H_ #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_TEST_UTILS_H_
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "components/password_manager/core/browser/password_reuse_detector.h" #include "components/password_manager/core/browser/password_reuse_detector.h"
#include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/password_reuse_detector_consumer.h"
#include "components/password_manager/core/browser/psl_matching_helper.h" #include "components/password_manager/core/browser/psl_matching_helper.h"
namespace password_manager { namespace password_manager {
...@@ -22,14 +23,16 @@ PasswordReuseDetector::~PasswordReuseDetector() {} ...@@ -22,14 +23,16 @@ PasswordReuseDetector::~PasswordReuseDetector() {}
void PasswordReuseDetector::OnGetPasswordStoreResults( void PasswordReuseDetector::OnGetPasswordStoreResults(
std::vector<std::unique_ptr<autofill::PasswordForm>> results) { std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
passwords_.clear(); for (const auto& form : results)
for (const auto& form : results) { AddPassword(*form);
const base::string16& password = form->password_value; }
if (password.size() < kMinPasswordLengthToCheck)
continue; void PasswordReuseDetector::OnLoginsChanged(
GURL signon_realm(form->signon_realm); const PasswordStoreChangeList& changes) {
const std::string domain = GetRegistryControlledDomain(signon_realm); for (const auto& change : changes) {
passwords_[password].insert(domain); if (change.type() == PasswordStoreChange::ADD ||
change.type() == PasswordStoreChange::UPDATE)
AddPassword(change.form());
} }
} }
...@@ -59,4 +62,13 @@ void PasswordReuseDetector::CheckReuse( ...@@ -59,4 +62,13 @@ void PasswordReuseDetector::CheckReuse(
} }
} }
void PasswordReuseDetector::AddPassword(const autofill::PasswordForm& form) {
const base::string16& password = form.password_value;
if (password.size() < kMinPasswordLengthToCheck)
return;
GURL signon_realm(form.signon_realm);
const std::string domain = GetRegistryControlledDomain(signon_realm);
passwords_[password].insert(domain);
}
} // namespace password_manager } // namespace password_manager
...@@ -13,18 +13,12 @@ ...@@ -13,18 +13,12 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "components/password_manager/core/browser/password_store_change.h"
#include "components/password_manager/core/browser/password_store_consumer.h" #include "components/password_manager/core/browser/password_store_consumer.h"
namespace password_manager { namespace password_manager {
// Callback interface for receiving a password reuse event. class PasswordReuseDetectorConsumer;
class PasswordReuseDetectorConsumer {
public:
// Called when a password reuse is found.
// |saved_domain| is the domain on which |password| is saved.
virtual void OnReuseFound(const base::string16& password,
const std::string& saved_domain) = 0;
};
// Per-profile class responsible for detection of password reuse, i.e. that the // Per-profile class responsible for detection of password reuse, i.e. that the
// user input on some site contains the password saved on another site. // user input on some site contains the password saved on another site.
...@@ -40,6 +34,9 @@ class PasswordReuseDetector : public PasswordStoreConsumer { ...@@ -40,6 +34,9 @@ class PasswordReuseDetector : public PasswordStoreConsumer {
void OnGetPasswordStoreResults( void OnGetPasswordStoreResults(
std::vector<std::unique_ptr<autofill::PasswordForm>> results) override; std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
// Add new or updated passwords from |changes| to internal password index.
void OnLoginsChanged(const PasswordStoreChangeList& changes);
// Checks that some suffix of |input| equals to a password saved on another // Checks that some suffix of |input| equals to a password saved on another
// registry controlled domain than |domain|. // registry controlled domain than |domain|.
// If such suffix is found, |consumer|->OnReuseFound() is called on the same // If such suffix is found, |consumer|->OnReuseFound() is called on the same
...@@ -50,6 +47,9 @@ class PasswordReuseDetector : public PasswordStoreConsumer { ...@@ -50,6 +47,9 @@ class PasswordReuseDetector : public PasswordStoreConsumer {
PasswordReuseDetectorConsumer* consumer); PasswordReuseDetectorConsumer* consumer);
private: private:
// Add password from |form| to |passwords_|.
void AddPassword(const autofill::PasswordForm& form);
// Contains all passwords. // Contains all passwords.
// A key is a password. // A key is a password.
// A value is a set of registry controlled domains on which the password // A value is a set of registry controlled domains on which the password
......
// Copyright 2016 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 "components/password_manager/core/browser/password_reuse_detector_consumer.h"
namespace password_manager {
PasswordReuseDetectorConsumer::PasswordReuseDetectorConsumer() {}
PasswordReuseDetectorConsumer::~PasswordReuseDetectorConsumer() {}
} // namespace password_manager
// Copyright 2016 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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_REUSE_DETECTOR_CONSUMER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_REUSE_DETECTOR_CONSUMER_H_
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
namespace password_manager {
// Callback interface for receiving a password reuse event.
class PasswordReuseDetectorConsumer
: public base::SupportsWeakPtr<PasswordReuseDetectorConsumer> {
public:
PasswordReuseDetectorConsumer();
virtual ~PasswordReuseDetectorConsumer();
// Called when a password reuse is found.
// |saved_domain| is the domain on which |password| is saved.
virtual void OnReuseFound(const base::string16& password,
const std::string& saved_domain) = 0;
};
} // namespace password_manager
#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_REUSE_DETECTOR_CONSUMER_H_
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -21,11 +22,6 @@ namespace password_manager { ...@@ -21,11 +22,6 @@ namespace password_manager {
namespace { namespace {
class MockPasswordReuseDetectorConsumer : public PasswordReuseDetectorConsumer {
public:
MOCK_METHOD2(OnReuseFound, void(const base::string16&, const std::string&));
};
std::vector<std::unique_ptr<PasswordForm>> GetSavedForms() { std::vector<std::unique_ptr<PasswordForm>> GetSavedForms() {
std::vector<std::unique_ptr<PasswordForm>> result; std::vector<std::unique_ptr<PasswordForm>> result;
std::vector<std::pair<std::string, std::string>> domains_passwords = { std::vector<std::pair<std::string, std::string>> domains_passwords = {
...@@ -44,6 +40,16 @@ std::vector<std::unique_ptr<PasswordForm>> GetSavedForms() { ...@@ -44,6 +40,16 @@ std::vector<std::unique_ptr<PasswordForm>> GetSavedForms() {
return result; return result;
} }
PasswordStoreChangeList GetChangeList(
PasswordStoreChange::Type type,
const std::vector<std::unique_ptr<PasswordForm>>& forms) {
PasswordStoreChangeList changes;
for (const auto& form : forms)
changes.push_back(PasswordStoreChange(type, *form));
return changes;
}
TEST(PasswordReuseDetectorTest, TypingPasswordOnDifferentSite) { TEST(PasswordReuseDetectorTest, TypingPasswordOnDifferentSite) {
PasswordReuseDetector reuse_detector; PasswordReuseDetector reuse_detector;
reuse_detector.OnGetPasswordStoreResults(GetSavedForms()); reuse_detector.OnGetPasswordStoreResults(GetSavedForms());
...@@ -106,6 +112,26 @@ TEST(PasswordReuseDetectorTest, PasswordNotInputSuffixNoReuseEvent) { ...@@ -106,6 +112,26 @@ TEST(PasswordReuseDetectorTest, PasswordNotInputSuffixNoReuseEvent) {
&mockConsumer); &mockConsumer);
} }
TEST(PasswordReuseDetectorTest, OnLoginsChanged) {
for (PasswordStoreChange::Type type :
{PasswordStoreChange::ADD, PasswordStoreChange::UPDATE,
PasswordStoreChange::REMOVE}) {
PasswordReuseDetector reuse_detector;
PasswordStoreChangeList changes = GetChangeList(type, GetSavedForms());
reuse_detector.OnLoginsChanged(changes);
MockPasswordReuseDetectorConsumer mockConsumer;
if (type == PasswordStoreChange::REMOVE) {
EXPECT_CALL(mockConsumer, OnReuseFound(_, _)).Times(0);
} else {
EXPECT_CALL(mockConsumer,
OnReuseFound(ASCIIToUTF16("password"), "google.com"));
}
reuse_detector.CheckReuse(ASCIIToUTF16("123password"), "https://evil.com",
&mockConsumer);
}
}
} // namespace } // namespace
} // namespace password_manager } // namespace password_manager
...@@ -59,6 +59,21 @@ void PasswordStore::GetLoginsRequest::NotifyWithSiteStatistics( ...@@ -59,6 +59,21 @@ void PasswordStore::GetLoginsRequest::NotifyWithSiteStatistics(
consumer_weak_, base::Passed(&stats))); consumer_weak_, base::Passed(&stats)));
} }
PasswordStore::CheckReuseRequest::CheckReuseRequest(
PasswordReuseDetectorConsumer* consumer)
: origin_task_runner_(base::ThreadTaskRunnerHandle::Get()),
consumer_weak_(consumer->AsWeakPtr()) {}
PasswordStore::CheckReuseRequest::~CheckReuseRequest() {}
void PasswordStore::CheckReuseRequest::OnReuseFound(
const base::string16& password,
const std::string& saved_domain) {
origin_task_runner_->PostTask(
FROM_HERE, base::Bind(&PasswordReuseDetectorConsumer::OnReuseFound,
consumer_weak_, password, saved_domain));
}
PasswordStore::FormDigest::FormDigest(autofill::PasswordForm::Scheme new_scheme, PasswordStore::FormDigest::FormDigest(autofill::PasswordForm::Scheme new_scheme,
const std::string& new_signon_realm, const std::string& new_signon_realm,
const GURL& new_origin) const GURL& new_origin)
...@@ -91,11 +106,10 @@ PasswordStore::PasswordStore( ...@@ -91,11 +106,10 @@ PasswordStore::PasswordStore(
db_thread_runner_(db_thread_runner), db_thread_runner_(db_thread_runner),
observers_(new base::ObserverListThreadSafe<Observer>()), observers_(new base::ObserverListThreadSafe<Observer>()),
is_propagating_password_changes_to_web_credentials_enabled_(false), is_propagating_password_changes_to_web_credentials_enabled_(false),
shutdown_called_(false) { shutdown_called_(false) {}
}
bool PasswordStore::Init(const syncer::SyncableService::StartSyncFlare& flare) { bool PasswordStore::Init(const syncer::SyncableService::StartSyncFlare& flare) {
ScheduleTask(base::Bind(&PasswordStore::InitSyncableService, this, flare)); ScheduleTask(base::Bind(&PasswordStore::InitOnBackgroundThread, this, flare));
return true; return true;
} }
...@@ -272,7 +286,7 @@ bool PasswordStore::ScheduleTask(const base::Closure& task) { ...@@ -272,7 +286,7 @@ bool PasswordStore::ScheduleTask(const base::Closure& task) {
} }
void PasswordStore::ShutdownOnUIThread() { void PasswordStore::ShutdownOnUIThread() {
ScheduleTask(base::Bind(&PasswordStore::DestroySyncableService, this)); ScheduleTask(base::Bind(&PasswordStore::DestroyOnBackgroundThread, this));
// The AffiliationService must be destroyed from the main thread. // The AffiliationService must be destroyed from the main thread.
affiliated_match_helper_.reset(); affiliated_match_helper_.reset();
shutdown_called_ = true; shutdown_called_ = true;
...@@ -285,6 +299,14 @@ PasswordStore::GetPasswordSyncableService() { ...@@ -285,6 +299,14 @@ PasswordStore::GetPasswordSyncableService() {
return syncable_service_->AsWeakPtr(); return syncable_service_->AsWeakPtr();
} }
void PasswordStore::CheckReuse(const base::string16& input,
const std::string& domain,
PasswordReuseDetectorConsumer* consumer) {
auto check_reuse_request = base::MakeUnique<CheckReuseRequest>(consumer);
ScheduleTask(base::Bind(&PasswordStore::CheckReuseImpl, this,
base::Passed(&check_reuse_request), input, domain));
}
PasswordStore::~PasswordStore() { PasswordStore::~PasswordStore() {
DCHECK(shutdown_called_); DCHECK(shutdown_called_);
} }
...@@ -349,9 +371,18 @@ void PasswordStore::NotifyLoginsChanged( ...@@ -349,9 +371,18 @@ void PasswordStore::NotifyLoginsChanged(
observers_->Notify(FROM_HERE, &Observer::OnLoginsChanged, changes); observers_->Notify(FROM_HERE, &Observer::OnLoginsChanged, changes);
if (syncable_service_) if (syncable_service_)
syncable_service_->ActOnPasswordStoreChanges(changes); syncable_service_->ActOnPasswordStoreChanges(changes);
if (reuse_detector_)
reuse_detector_->OnLoginsChanged(changes);
} }
} }
void PasswordStore::CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request,
const base::string16& input,
const std::string& domain) {
if (reuse_detector_)
reuse_detector_->CheckReuse(input, domain, request.get());
}
void PasswordStore::Schedule( void PasswordStore::Schedule(
void (PasswordStore::*func)(std::unique_ptr<GetLoginsRequest>), void (PasswordStore::*func)(std::unique_ptr<GetLoginsRequest>),
PasswordStoreConsumer* consumer) { PasswordStoreConsumer* consumer) {
...@@ -653,17 +684,25 @@ void PasswordStore::ScheduleUpdateAffiliatedWebLoginsImpl( ...@@ -653,17 +684,25 @@ void PasswordStore::ScheduleUpdateAffiliatedWebLoginsImpl(
updated_android_form, affiliated_web_realms)); updated_android_form, affiliated_web_realms));
} }
void PasswordStore::InitSyncableService( void PasswordStore::InitOnBackgroundThread(
const syncer::SyncableService::StartSyncFlare& flare) { const syncer::SyncableService::StartSyncFlare& flare) {
DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
DCHECK(!syncable_service_); DCHECK(!syncable_service_);
syncable_service_.reset(new PasswordSyncableService(this)); syncable_service_.reset(new PasswordSyncableService(this));
syncable_service_->InjectStartSyncFlare(flare); syncable_service_->InjectStartSyncFlare(flare);
reuse_detector_.reset(new PasswordReuseDetector);
#if !defined(OS_MACOSX)
// TODO(crbug.com/668155): For non-migrated keychain users it can lead to
// hundreds of requests to unlock keychain.
GetAutofillableLoginsImpl(
base::MakeUnique<GetLoginsRequest>(reuse_detector_.get()));
#endif
} }
void PasswordStore::DestroySyncableService() { void PasswordStore::DestroyOnBackgroundThread() {
DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
syncable_service_.reset(); syncable_service_.reset();
reuse_detector_.reset();
} }
std::ostream& operator<<(std::ostream& os, std::ostream& operator<<(std::ostream& os,
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "components/keyed_service/core/refcounted_keyed_service.h" #include "components/keyed_service/core/refcounted_keyed_service.h"
#include "components/password_manager/core/browser/password_reuse_detector.h"
#include "components/password_manager/core/browser/password_reuse_detector_consumer.h"
#include "components/password_manager/core/browser/password_store_change.h" #include "components/password_manager/core/browser/password_store_change.h"
#include "components/password_manager/core/browser/password_store_sync.h" #include "components/password_manager/core/browser/password_store_sync.h"
#include "components/sync/model/syncable_service.h" #include "components/sync/model/syncable_service.h"
...@@ -221,6 +223,15 @@ class PasswordStore : protected PasswordStoreSync, ...@@ -221,6 +223,15 @@ class PasswordStore : protected PasswordStoreSync,
base::WeakPtr<syncer::SyncableService> GetPasswordSyncableService(); base::WeakPtr<syncer::SyncableService> GetPasswordSyncableService();
// Checks that some suffix of |input| equals to a password saved on another
// registry controlled domain than |domain|.
// If such suffix is found, |consumer|->OnReuseFound() is called on the same
// thread on which this method is called.
// |consumer| must not be null.
void CheckReuse(const base::string16& input,
const std::string& domain,
PasswordReuseDetectorConsumer* consumer);
protected: protected:
friend class base::RefCountedThreadSafe<PasswordStore>; friend class base::RefCountedThreadSafe<PasswordStore>;
...@@ -256,6 +267,26 @@ class PasswordStore : protected PasswordStoreSync, ...@@ -256,6 +267,26 @@ class PasswordStore : protected PasswordStoreSync,
DISALLOW_COPY_AND_ASSIGN(GetLoginsRequest); DISALLOW_COPY_AND_ASSIGN(GetLoginsRequest);
}; };
// Represents a single CheckReuse() request. Implements functionality to
// listen to reuse events and propagate them to |consumer| on the thread on
// which CheckReuseRequest is created.
class CheckReuseRequest : public PasswordReuseDetectorConsumer {
public:
// |consumer| must not be null.
explicit CheckReuseRequest(PasswordReuseDetectorConsumer* consumer);
~CheckReuseRequest() override;
// PasswordReuseDetectorConsumer
void OnReuseFound(const base::string16& password,
const std::string& saved_domain) override;
private:
const scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
const base::WeakPtr<PasswordReuseDetectorConsumer> consumer_weak_;
DISALLOW_COPY_AND_ASSIGN(CheckReuseRequest);
};
~PasswordStore() override; ~PasswordStore() override;
// Get the TaskRunner to use for PasswordStore background tasks. // Get the TaskRunner to use for PasswordStore background tasks.
...@@ -348,6 +379,11 @@ class PasswordStore : protected PasswordStoreSync, ...@@ -348,6 +379,11 @@ class PasswordStore : protected PasswordStoreSync,
// may have been changed. // may have been changed.
void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override; void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override;
// Synchronous implementation of CheckReuse().
void CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request,
const base::string16& input,
const std::string& domain);
// TaskRunner for tasks that run on the main thread (usually the UI thread). // TaskRunner for tasks that run on the main thread (usually the UI thread).
scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
...@@ -482,18 +518,20 @@ class PasswordStore : protected PasswordStoreSync, ...@@ -482,18 +518,20 @@ class PasswordStore : protected PasswordStoreSync,
const autofill::PasswordForm& updated_android_form, const autofill::PasswordForm& updated_android_form,
const std::vector<std::string>& affiliated_web_realms); const std::vector<std::string>& affiliated_web_realms);
// Creates PasswordSyncableService instance on the background thread. // Creates PasswordSyncableService and PasswordReuseDetector instances on the
void InitSyncableService( // background thread.
void InitOnBackgroundThread(
const syncer::SyncableService::StartSyncFlare& flare); const syncer::SyncableService::StartSyncFlare& flare);
// Deletes PasswordSyncableService instance on the background thread. // Deletes objest that should be destroyed on the background thread.
void DestroySyncableService(); void DestroyOnBackgroundThread();
// The observers. // The observers.
scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_; scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_;
std::unique_ptr<PasswordSyncableService> syncable_service_; std::unique_ptr<PasswordSyncableService> syncable_service_;
std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper_; std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper_;
std::unique_ptr<PasswordReuseDetector> reuse_detector_;
bool is_propagating_password_changes_to_web_credentials_enabled_; bool is_propagating_password_changes_to_web_credentials_enabled_;
bool shutdown_called_; bool shutdown_called_;
......
...@@ -840,4 +840,56 @@ TEST_F(PasswordStoreTest, GetLoginsWithAffiliatedRealms) { ...@@ -840,4 +840,56 @@ TEST_F(PasswordStoreTest, GetLoginsWithAffiliatedRealms) {
} }
} }
#if !defined(OS_MACOSX)
// TODO(crbug.com/668155): Enable this test after fixing issues with
// initialization PasswordStore with MockKeyChain in tests on MacOS.
TEST_F(PasswordStoreTest, CheckPasswordReuse) {
static constexpr PasswordFormData kTestCredentials[] = {
{PasswordForm::SCHEME_HTML, "https://www.google.com",
"https://www.google.com", "", L"", L"", L"", L"", L"password", true, 1},
{PasswordForm::SCHEME_HTML, "https://facebook.com",
"https://facebook.com", "", L"", L"", L"", L"", L"topsecret", true, 1}};
scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(),
base::MakeUnique<LoginDatabase>(test_login_db_file_path())));
store->Init(syncer::SyncableService::StartSyncFlare());
for (const auto& test_credentials : kTestCredentials) {
auto credentials = CreatePasswordFormFromDataForTesting(test_credentials);
store->AddLogin(*credentials);
base::RunLoop().RunUntilIdle();
}
static constexpr struct {
const wchar_t* input;
const char* domain;
const wchar_t* reused_password; // Set to nullptr if no reuse is expected.
const char* reuse_domain;
} kReuseTestData[] = {
{L"12345password", "https://evil.com", L"password", "google.com"},
{L"1234567890", "https://evil.com", nullptr, nullptr},
{L"topsecret", "https://m.facebook.com", nullptr, nullptr},
};
for (const auto& test_data : kReuseTestData) {
MockPasswordReuseDetectorConsumer mock_consumer;
if (test_data.reused_password) {
EXPECT_CALL(mock_consumer,
OnReuseFound(base::WideToUTF16(test_data.reused_password),
std::string(test_data.reuse_domain)));
} else {
EXPECT_CALL(mock_consumer, OnReuseFound(_, _)).Times(0);
}
store->CheckReuse(base::WideToUTF16(test_data.input), test_data.domain,
&mock_consumer);
base::RunLoop().RunUntilIdle();
}
store->ShutdownOnUIThread();
base::RunLoop().RunUntilIdle();
}
#endif
} // namespace password_manager } // namespace password_manager
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment