Commit 09248296 authored by Ioana Pandele's avatar Ioana Pandele Committed by Commit Bot

[PwdCheckAndroid] Add basic functionality to PasswordCheckManager

This CL adds
- the ability to start/stop the check
- check status update
- compromised credentials change message to the UI
- saved passwords fetched call for the UI (this is used by safety check)

The list of compromised credentials as well as check progress updates
will be added in the next CLs.

Bug: 1102025, 1092444
Change-Id: I3ad9af201d2158f956479a76b9ca8c184a05d397
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2333845
Commit-Queue: Ioana Pandele <ioanap@chromium.org>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795413}
parent 0076e46e
...@@ -2780,6 +2780,8 @@ static_library("browser") { ...@@ -2780,6 +2780,8 @@ static_library("browser") {
"page_load_metrics/observers/android_page_load_metrics_observer.h", "page_load_metrics/observers/android_page_load_metrics_observer.h",
"password_check/android/password_check_bridge.cc", "password_check/android/password_check_bridge.cc",
"password_check/android/password_check_bridge.h", "password_check/android/password_check_bridge.h",
"password_check/android/password_check_manager.cc",
"password_check/android/password_check_manager.h",
"password_manager/android/account_chooser_dialog_android.cc", "password_manager/android/account_chooser_dialog_android.cc",
"password_manager/android/account_chooser_dialog_android.h", "password_manager/android/account_chooser_dialog_android.h",
"password_manager/android/all_passwords_bottom_sheet_controller.cc", "password_manager/android/all_passwords_bottom_sheet_controller.cc",
......
...@@ -25,9 +25,19 @@ android_library("password_check_java_enums") { ...@@ -25,9 +25,19 @@ android_library("password_check_java_enums") {
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
sources = [ "bulk_leak_check_controller_android_unittest.cc" ] sources = [
"bulk_leak_check_controller_android_unittest.cc",
"password_check_manager_unittest.cc",
]
deps = [ deps = [
":android", ":android",
":password_check_enums_srcjar",
"//base/test:test_support",
"//chrome/browser",
"//chrome/test:test_support",
"//components/password_manager/core/browser",
"//components/signin/public/identity_manager",
"//components/signin/public/identity_manager:test_support",
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
] ]
......
...@@ -62,12 +62,12 @@ class PasswordCheckBridge { ...@@ -62,12 +62,12 @@ class PasswordCheckBridge {
originUrl, username, password, hasScript); originUrl, username, password, hasScript);
} }
// TODO(crbug.com/1102025): Add call from native. @CalledByNative
void onCompromisedCredentialsFetched(int count) { void onCompromisedCredentialsFetched(int count) {
mPasswordCheckObserver.onCompromisedCredentialsFetched(count); mPasswordCheckObserver.onCompromisedCredentialsFetched(count);
} }
// TODO(crbug.com/1102025): Add call from native. @CalledByNative
void onSavedPasswordsFetched(int count) { void onSavedPasswordsFetched(int count) {
mPasswordCheckObserver.onSavedPasswordsFetched(count); mPasswordCheckObserver.onSavedPasswordsFetched(count);
} }
......
...@@ -17,24 +17,23 @@ static jlong JNI_PasswordCheckBridge_Create( ...@@ -17,24 +17,23 @@ static jlong JNI_PasswordCheckBridge_Create(
PasswordCheckBridge::PasswordCheckBridge( PasswordCheckBridge::PasswordCheckBridge(
const base::android::JavaParamRef<jobject>& java_bridge) const base::android::JavaParamRef<jobject>& java_bridge)
: java_bridge_(java_bridge) {} : java_bridge_(java_bridge) {}
PasswordCheckBridge::~PasswordCheckBridge() = default; PasswordCheckBridge::~PasswordCheckBridge() = default;
void PasswordCheckBridge::StartCheck(JNIEnv* env) { void PasswordCheckBridge::StartCheck(JNIEnv* env) {
// TODO(crbug.com/1102025): implement this. check_manager_.StartCheck();
} }
void PasswordCheckBridge::StopCheck(JNIEnv* env) { void PasswordCheckBridge::StopCheck(JNIEnv* env) {
// TODO(crbug.com/1102025): implement this. check_manager_.StopCheck();
} }
jint PasswordCheckBridge::GetCompromisedCredentialsCount(JNIEnv* env) { jint PasswordCheckBridge::GetCompromisedCredentialsCount(JNIEnv* env) {
// TODO(crbug.com/1102025): implement this. return check_manager_.GetCompromisedCredentialsCount();
return 0;
} }
jint PasswordCheckBridge::GetSavedPasswordsCount(JNIEnv* env) { jint PasswordCheckBridge::GetSavedPasswordsCount(JNIEnv* env) {
// TODO(crbug.com/1102025): implement this. return check_manager_.GetSavedPasswordsCount();
return 0;
} }
void PasswordCheckBridge::GetCompromisedCredentials( void PasswordCheckBridge::GetCompromisedCredentials(
...@@ -50,9 +49,20 @@ void PasswordCheckBridge::RemoveCredential( ...@@ -50,9 +49,20 @@ void PasswordCheckBridge::RemoveCredential(
} }
void PasswordCheckBridge::Destroy(JNIEnv* env) { void PasswordCheckBridge::Destroy(JNIEnv* env) {
check_manager_.StopCheck();
delete this; delete this;
} }
void PasswordCheckBridge::OnSavedPasswordsFetched(int count) {
Java_PasswordCheckBridge_onSavedPasswordsFetched(
base::android::AttachCurrentThread(), java_bridge_, count);
}
void PasswordCheckBridge::OnCompromisedCredentialsChanged(int count) {
Java_PasswordCheckBridge_onCompromisedCredentialsFetched(
base::android::AttachCurrentThread(), java_bridge_, count);
}
void PasswordCheckBridge::OnPasswordCheckStatusChanged( void PasswordCheckBridge::OnPasswordCheckStatusChanged(
password_manager::PasswordCheckUIStatus status) { password_manager::PasswordCheckUIStatus status) {
Java_PasswordCheckBridge_onPasswordCheckStatusChanged( Java_PasswordCheckBridge_onPasswordCheckStatusChanged(
......
...@@ -7,14 +7,18 @@ ...@@ -7,14 +7,18 @@
#include <jni.h> #include <jni.h>
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "chrome/browser/password_check/android/password_check_manager.h"
#include "chrome/browser/password_check/android/password_check_ui_status.h" #include "chrome/browser/password_check/android/password_check_ui_status.h"
#include "chrome/browser/profiles/profile_manager.h"
// C++ counterpart of |PasswordCheckBridge.java|. Used to mediate the // C++ counterpart of |PasswordCheckBridge.java|. Used to mediate the
// communication between the UI and the password check logic. // communication between the UI and the password check logic.
class PasswordCheckBridge { class PasswordCheckBridge : public PasswordCheckManager::Observer {
public: public:
explicit PasswordCheckBridge( explicit PasswordCheckBridge(
const base::android::JavaParamRef<jobject>& java_bridge); const base::android::JavaParamRef<jobject>& java_bridge);
~PasswordCheckBridge() override;
PasswordCheckBridge(const PasswordCheckBridge&) = delete; PasswordCheckBridge(const PasswordCheckBridge&) = delete;
PasswordCheckBridge& operator=(const PasswordCheckBridge&) = delete; PasswordCheckBridge& operator=(const PasswordCheckBridge&) = delete;
...@@ -44,15 +48,26 @@ class PasswordCheckBridge { ...@@ -44,15 +48,26 @@ class PasswordCheckBridge {
// Called by Java when the bridge is no longer needed. Destructs itself. // Called by Java when the bridge is no longer needed. Destructs itself.
void Destroy(JNIEnv* env); void Destroy(JNIEnv* env);
// Called by the check manager when the saved passwords have been first loaded
// in memory. `count` is the number of saved passwords.
void OnSavedPasswordsFetched(int count) override;
// Called by the check manager whenever the stored compromised credentials
// change. `count` is the number of compromised credentials.
void OnCompromisedCredentialsChanged(int count) override;
// Called by the check manager when the status of the check changes. // Called by the check manager when the status of the check changes.
void OnPasswordCheckStatusChanged( void OnPasswordCheckStatusChanged(
password_manager::PasswordCheckUIStatus status); password_manager::PasswordCheckUIStatus status) override;
private: private:
~PasswordCheckBridge();
// The corresponding java object. // The corresponding java object.
base::android::ScopedJavaGlobalRef<jobject> java_bridge_; base::android::ScopedJavaGlobalRef<jobject> java_bridge_;
// Manager handling the communication with the check service, owning and
// observing a `CompromisedCredentialManager` and a `SavedPasswordsPresenter`.
PasswordCheckManager check_manager_{ProfileManager::GetLastUsedProfile(),
this};
}; };
#endif // CHROME_BROWSER_PASSWORD_CHECK_ANDROID_PASSWORD_CHECK_BRIDGE_H_ #endif // CHROME_BROWSER_PASSWORD_CHECK_ANDROID_PASSWORD_CHECK_BRIDGE_H_
// Copyright 2020 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/password_check/android/password_check_manager.h"
#include "chrome/browser/password_check/android/password_check_bridge.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/sync/driver/profile_sync_service.h"
using PasswordCheckUIStatus = password_manager::PasswordCheckUIStatus;
using State = password_manager::BulkLeakCheckService::State;
using SyncState = password_manager::SyncState;
PasswordCheckManager::PasswordCheckManager(Profile* profile, Observer* observer)
: observer_(observer), profile_(profile) {
observed_saved_passwords_presenter_.Add(&saved_passwords_presenter_);
observed_compromised_credentials_manager_.Add(
&compromised_credentials_manager_);
observed_bulk_leak_check_service_.Add(
BulkLeakCheckServiceFactory::GetForProfile(profile));
// Instructs the presenter and provider to initialize and built their caches.
// This will soon after invoke OnCompromisedCredentialsChanged(). Calls to
// GetCompromisedCredentials() that might happen until then will return an
// empty list.
saved_passwords_presenter_.Init();
compromised_credentials_manager_.Init();
}
PasswordCheckManager::~PasswordCheckManager() = default;
void PasswordCheckManager::StartCheck() {
if (!is_initialized_) {
was_start_requested_ = true;
return;
}
// The request is being handled, so reset the boolean.
was_start_requested_ = false;
bulk_leak_check_service_adapter_.StartBulkLeakCheck();
}
void PasswordCheckManager::StopCheck() {
bulk_leak_check_service_adapter_.StopBulkLeakCheck();
}
int PasswordCheckManager::GetCompromisedCredentialsCount() const {
return compromised_credentials_manager_.GetCompromisedCredentials().size();
}
int PasswordCheckManager::GetSavedPasswordsCount() const {
return saved_passwords_presenter_.GetSavedPasswords().size();
}
void PasswordCheckManager::OnSavedPasswordsChanged(
password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords) {
if (!is_initialized_) {
observer_->OnSavedPasswordsFetched(passwords.size());
is_initialized_ = true;
}
if (passwords.empty()) {
observer_->OnPasswordCheckStatusChanged(
PasswordCheckUIStatus::kErrorNoPasswords);
was_start_requested_ = false;
return;
}
if (was_start_requested_) {
StartCheck();
}
}
void PasswordCheckManager::OnCompromisedCredentialsChanged(
password_manager::CompromisedCredentialsManager::CredentialsView
credentials) {
observer_->OnCompromisedCredentialsChanged(credentials.size());
}
void PasswordCheckManager::OnStateChanged(State state) {
observer_->OnPasswordCheckStatusChanged(GetUIStatus(state));
}
void PasswordCheckManager::OnCredentialDone(
const password_manager::LeakCheckCredential& credential,
password_manager::IsLeaked is_leaked) {
// TODO(crbug.com/1102025): implement this.
}
PasswordCheckUIStatus PasswordCheckManager::GetUIStatus(State state) const {
switch (state) {
case State::kIdle:
return PasswordCheckUIStatus::kIdle;
case State::kRunning:
return PasswordCheckUIStatus::kRunning;
case State::kSignedOut:
return PasswordCheckUIStatus::kErrorSignedOut;
case State::kNetworkError:
return PasswordCheckUIStatus::kErrorOffline;
case State::kQuotaLimit:
return CanUseAccountCheck()
? PasswordCheckUIStatus::kErrorQuotaLimitAccountCheck
: PasswordCheckUIStatus::kErrorQuotaLimit;
case State::kCanceled:
return PasswordCheckUIStatus::kCanceled;
case State::kTokenRequestFailure:
case State::kHashingFailure:
case State::kServiceError:
return PasswordCheckUIStatus::kErrorUnknown;
}
NOTREACHED();
return PasswordCheckUIStatus::kIdle;
}
bool PasswordCheckManager::CanUseAccountCheck() const {
SyncState sync_state = password_manager_util::GetPasswordSyncState(
ProfileSyncServiceFactory::GetForProfile(profile_));
return sync_state == SyncState::SYNCING_NORMAL_ENCRYPTION ||
sync_state == SyncState::ACCOUNT_PASSWORDS_ACTIVE_NORMAL_ENCRYPTION;
}
// Copyright 2020 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_PASSWORD_CHECK_ANDROID_PASSWORD_CHECK_MANAGER_H_
#define CHROME_BROWSER_PASSWORD_CHECK_ANDROID_PASSWORD_CHECK_MANAGER_H_
#include "base/memory/scoped_refptr.h"
#include "chrome/browser/password_check/android/password_check_ui_status.h"
#include "chrome/browser/password_manager/bulk_leak_check_service_factory.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "components/password_manager/core/browser/bulk_leak_check_service.h"
#include "components/password_manager/core/browser/bulk_leak_check_service_interface.h"
#include "components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h"
#include "components/password_manager/core/browser/ui/compromised_credentials_manager.h"
#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
class PasswordCheckManager
: public password_manager::SavedPasswordsPresenter::Observer,
public password_manager::CompromisedCredentialsManager::Observer,
public password_manager::BulkLeakCheckServiceInterface::Observer {
public:
class Observer {
public:
virtual ~Observer() = default;
virtual void OnSavedPasswordsFetched(int count) = 0;
virtual void OnCompromisedCredentialsChanged(int count) = 0;
virtual void OnPasswordCheckStatusChanged(
password_manager::PasswordCheckUIStatus status) = 0;
};
// `observer` must outlive `this`.
PasswordCheckManager(Profile* profile, Observer* observer);
~PasswordCheckManager() override;
// Requests to start the password check.
void StartCheck();
// Stops a running check.
void StopCheck();
// Called by java to retrieve the number of compromised credentials. If the
// credentials haven't been fetched yet, this will return 0.
int GetCompromisedCredentialsCount() const;
// Called by java to retrieve the number of saved passwords.
// If the saved passwords haven't been fetched yet, this will return 0.
int GetSavedPasswordsCount() const;
// Not copyable or movable
PasswordCheckManager(const PasswordCheckManager&) = delete;
PasswordCheckManager& operator=(const PasswordCheckManager&) = delete;
PasswordCheckManager(PasswordCheckManager&&) = delete;
PasswordCheckManager& operator=(PasswordCheckManager&&) = delete;
private:
// password_manager::SavedPasswordsPresenter::Observer:
void OnSavedPasswordsChanged(
password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords)
override;
// CompromisedCredentialsManager::Observer
void OnCompromisedCredentialsChanged(
password_manager::CompromisedCredentialsManager::CredentialsView
credentials) override;
// BulkLeakCheckServiceInterface::Observer
void OnStateChanged(
password_manager::BulkLeakCheckServiceInterface::State state) override;
void OnCredentialDone(const password_manager::LeakCheckCredential& credential,
password_manager::IsLeaked is_leaked) override;
// Converts the state retrieved from the check service into a state that
// can be used by the UI to display appropriate messages.
password_manager::PasswordCheckUIStatus GetUIStatus(
password_manager::BulkLeakCheckServiceInterface::State state) const;
// Returns true if the user has their passwords available in their Google
// Account. Used to determine whether the user could use the password check
// in the account if the quota limit was reached.
bool CanUseAccountCheck() const;
// Obsever being notified of UI-relevant events.
// It must outlive `this`.
Observer* observer_ = nullptr;
// The profile for which the passwords are checked.
Profile* profile_ = nullptr;
// Handle to the password store, powering both `saved_passwords_presenter_`
// and `compromised_credentials_manager_`.
scoped_refptr<password_manager::PasswordStore> password_store_ =
PasswordStoreFactory::GetForProfile(profile_,
ServiceAccessType::EXPLICIT_ACCESS);
// Used by `compromised_credentials_manager_` to obtain the list of saved
// passwords.
password_manager::SavedPasswordsPresenter saved_passwords_presenter_{
password_store_};
// Used to obtain the list of compromised credentials.
password_manager::CompromisedCredentialsManager
compromised_credentials_manager_{password_store_,
&saved_passwords_presenter_};
// Adapter used to start, monitor and stop a bulk leak check.
password_manager::BulkLeakCheckServiceAdapter
bulk_leak_check_service_adapter_{
&saved_passwords_presenter_,
BulkLeakCheckServiceFactory::GetForProfile(profile_),
profile_->GetPrefs()};
// This is true when the saved passwords have been fetched from the store.
bool is_initialized_ = false;
// Whether the check start was requested.
bool was_start_requested_ = false;
// A scoped observer for `saved_passwords_presenter_`.
ScopedObserver<password_manager::SavedPasswordsPresenter,
password_manager::SavedPasswordsPresenter::Observer>
observed_saved_passwords_presenter_{this};
// A scoped observer for `compromised_credentials_manager_`.
ScopedObserver<password_manager::CompromisedCredentialsManager,
password_manager::CompromisedCredentialsManager::Observer>
observed_compromised_credentials_manager_{this};
// A scoped observer for the BulkLeakCheckService.
ScopedObserver<password_manager::BulkLeakCheckServiceInterface,
password_manager::BulkLeakCheckServiceInterface::Observer>
observed_bulk_leak_check_service_{this};
};
#endif // CHROME_BROWSER_PASSWORD_CHECK_ANDROID_PASSWORD_CHECK_MANAGER_H_
// Copyright 2020 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/password_check/android/password_check_manager.h"
#include <memory>
#include "base/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "chrome/browser/password_check/android/password_check_ui_status.h"
#include "chrome/browser/password_manager/bulk_leak_check_service_factory.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "components/password_manager/core/browser/bulk_leak_check_service.h"
#include "components/password_manager/core/browser/mock_bulk_leak_check_service.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/test_password_store.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/browser_task_environment.h"
#include "services/network/test/test_shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using autofill::PasswordForm;
using password_manager::BulkLeakCheckService;
using password_manager::CompromisedCredentials;
using password_manager::CompromiseType;
using password_manager::MockBulkLeakCheckService;
using password_manager::PasswordCheckUIStatus;
using password_manager::TestPasswordStore;
using testing::_;
using testing::NiceMock;
namespace {
constexpr char kExampleCom[] = "https://example.com";
constexpr char kUsername1[] = "alice";
constexpr char kUsername2[] = "bob";
constexpr char kPassword1[] = "s3cre3t";
class MockPasswordCheckManagerObserver : public PasswordCheckManager::Observer {
public:
MOCK_METHOD(void, OnSavedPasswordsFetched, (int), (override));
MOCK_METHOD(void, OnCompromisedCredentialsChanged, (int), (override));
MOCK_METHOD(void,
OnPasswordCheckStatusChanged,
(password_manager::PasswordCheckUIStatus),
(override));
};
// TODO(crbug.com/1112804): Extract this into a password manager test utils
// file, since it's used across multiple tests.
scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore(
Profile* profile) {
return base::WrapRefCounted(static_cast<TestPasswordStore*>(
PasswordStoreFactory::GetInstance()
->SetTestingFactoryAndUse(
profile,
base::BindRepeating(&password_manager::BuildPasswordStore<
content::BrowserContext, TestPasswordStore>))
.get()));
}
BulkLeakCheckService* CreateAndUseBulkLeakCheckService(
signin::IdentityManager* identity_manager,
Profile* profile) {
return BulkLeakCheckServiceFactory::GetInstance()
->SetTestingSubclassFactoryAndUse(
profile, base::BindLambdaForTesting([=](content::BrowserContext*) {
return std::make_unique<BulkLeakCheckService>(
identity_manager,
base::MakeRefCounted<network::TestSharedURLLoaderFactory>());
}));
}
PasswordForm MakeSavedPassword(base::StringPiece signon_realm,
base::StringPiece username,
base::StringPiece password = kPassword1,
base::StringPiece username_element = "") {
PasswordForm form;
form.signon_realm = std::string(signon_realm);
form.url = GURL(signon_realm);
form.username_value = base::ASCIIToUTF16(username);
form.password_value = base::ASCIIToUTF16(password);
form.username_element = base::ASCIIToUTF16(username_element);
return form;
}
CompromisedCredentials MakeCompromised(
base::StringPiece signon_realm,
base::StringPiece username,
base::TimeDelta time_since_creation = base::TimeDelta(),
CompromiseType compromise_type = CompromiseType::kLeaked) {
return {
std::string(signon_realm),
base::ASCIIToUTF16(username),
base::Time::Now() - time_since_creation,
compromise_type,
};
}
} // namespace
class PasswordCheckManagerTest : public testing::Test {
public:
void InitializeManager() {
manager_ =
std::make_unique<PasswordCheckManager>(&profile_, &mock_observer_);
}
void RunUntilIdle() { task_env_.RunUntilIdle(); }
TestPasswordStore& store() { return *store_; }
protected:
NiceMock<MockPasswordCheckManagerObserver> mock_observer_;
std::unique_ptr<PasswordCheckManager> manager_;
private:
content::BrowserTaskEnvironment task_env_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
signin::IdentityTestEnvironment identity_test_env_;
TestingProfile profile_;
BulkLeakCheckService* bulk_leak_check_service_ =
CreateAndUseBulkLeakCheckService(identity_test_env_.identity_manager(),
&profile_);
scoped_refptr<TestPasswordStore> store_ =
CreateAndUseTestPasswordStore(&profile_);
};
TEST_F(PasswordCheckManagerTest, SendsNoPasswordsMessageIfNoPasswordsAreSaved) {
EXPECT_CALL(mock_observer_, OnPasswordCheckStatusChanged(
PasswordCheckUIStatus::kErrorNoPasswords));
InitializeManager();
RunUntilIdle();
}
TEST_F(PasswordCheckManagerTest, OnSavedPasswordsFetched) {
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
EXPECT_CALL(mock_observer_, OnSavedPasswordsFetched(1));
InitializeManager();
RunUntilIdle();
// Verify that OnSavedPasswordsFetched is not called after the initial fetch
// even if the saved passwords change.
EXPECT_CALL(mock_observer_, OnSavedPasswordsFetched(_)).Times(0);
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2));
RunUntilIdle();
}
TEST_F(PasswordCheckManagerTest, OnCompromisedCredentialsChanged) {
// This is called on multiple events: once for saved passwords retrieval,
// once for compromised credentials retrieval and once when the saved password
// is added.
EXPECT_CALL(mock_observer_, OnCompromisedCredentialsChanged(0)).Times(3);
InitializeManager();
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
RunUntilIdle();
EXPECT_CALL(mock_observer_, OnCompromisedCredentialsChanged(1));
store().AddCompromisedCredentials(
MakeCompromised(kExampleCom, kUsername1, base::TimeDelta::FromMinutes(1),
CompromiseType::kLeaked));
RunUntilIdle();
}
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