Commit 9361b346 authored by Andrey Zaytsev's avatar Andrey Zaytsev Committed by Commit Bot

Safety check: added the retrieval of the actual number of compromised passwords

Bug: 1015841
Change-Id: I5c32614984a2398d83001d5b4e48c7689f7991d4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2087585
Commit-Queue: Andrey Zaytsev <andzaytsev@google.com>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#749664}
parent e423572a
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h"
#include "chrome/browser/password_manager/bulk_leak_check_service_factory.h" #include "chrome/browser/password_manager/bulk_leak_check_service_factory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
...@@ -81,6 +82,7 @@ void SafetyCheckHandler::PerformSafetyCheck() { ...@@ -81,6 +82,7 @@ void SafetyCheckHandler::PerformSafetyCheck() {
if (!version_updater_) { if (!version_updater_) {
version_updater_.reset(VersionUpdater::Create(web_ui()->GetWebContents())); version_updater_.reset(VersionUpdater::Create(web_ui()->GetWebContents()));
} }
DCHECK(version_updater_);
CheckUpdates(); CheckUpdates();
CheckSafeBrowsing(); CheckSafeBrowsing();
...@@ -90,6 +92,12 @@ void SafetyCheckHandler::PerformSafetyCheck() { ...@@ -90,6 +92,12 @@ void SafetyCheckHandler::PerformSafetyCheck() {
Profile::FromWebUI(web_ui())); Profile::FromWebUI(web_ui()));
} }
DCHECK(leak_service_); DCHECK(leak_service_);
if (!passwords_delegate_) {
passwords_delegate_ =
extensions::PasswordsPrivateDelegateFactory::GetForBrowserContext(
Profile::FromWebUI(web_ui()), true);
}
DCHECK(passwords_delegate_);
CheckPasswords(); CheckPasswords();
if (!extension_prefs_) { if (!extension_prefs_) {
...@@ -109,10 +117,12 @@ void SafetyCheckHandler::PerformSafetyCheck() { ...@@ -109,10 +117,12 @@ void SafetyCheckHandler::PerformSafetyCheck() {
SafetyCheckHandler::SafetyCheckHandler( SafetyCheckHandler::SafetyCheckHandler(
std::unique_ptr<VersionUpdater> version_updater, std::unique_ptr<VersionUpdater> version_updater,
password_manager::BulkLeakCheckService* leak_service, password_manager::BulkLeakCheckService* leak_service,
extensions::PasswordsPrivateDelegate* passwords_delegate,
extensions::ExtensionPrefs* extension_prefs, extensions::ExtensionPrefs* extension_prefs,
extensions::ExtensionServiceInterface* extension_service) extensions::ExtensionServiceInterface* extension_service)
: version_updater_(std::move(version_updater)), : version_updater_(std::move(version_updater)),
leak_service_(leak_service), leak_service_(leak_service),
passwords_delegate_(passwords_delegate),
extension_prefs_(extension_prefs), extension_prefs_(extension_prefs),
extension_service_(extension_service) {} extension_service_(extension_service) {}
...@@ -391,13 +401,20 @@ void SafetyCheckHandler::OnStateChanged( ...@@ -391,13 +401,20 @@ void SafetyCheckHandler::OnStateChanged(
using password_manager::BulkLeakCheckService; using password_manager::BulkLeakCheckService;
switch (state) { switch (state) {
case BulkLeakCheckService::State::kIdle: case BulkLeakCheckService::State::kIdle:
case BulkLeakCheckService::State::kCanceled: case BulkLeakCheckService::State::kCanceled: {
// TODO(crbug.com/1015841): Implement retrieving the number size_t num_compromised =
// of leaked passwords (if any) once PasswordsPrivateDelegate provides an passwords_delegate_->GetCompromisedCredentials().size();
// API for that (see crrev.com/c/2072742). if (num_compromised == 0) {
OnPasswordsCheckResult(PasswordsStatus::kSafe, 0);
} else {
OnPasswordsCheckResult(PasswordsStatus::kCompromisedExist,
num_compromised);
}
break; break;
}
case BulkLeakCheckService::State::kRunning: case BulkLeakCheckService::State::kRunning:
OnPasswordsCheckResult(PasswordsStatus::kChecking, 0); OnPasswordsCheckResult(PasswordsStatus::kChecking, 0);
// Non-terminal state, so nothing else needs to be done.
return; return;
case BulkLeakCheckService::State::kSignedOut: case BulkLeakCheckService::State::kSignedOut:
OnPasswordsCheckResult(PasswordsStatus::kSignedOut, 0); OnPasswordsCheckResult(PasswordsStatus::kSignedOut, 0);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "base/util/type_safety/strong_alias.h" #include "base/util/type_safety/strong_alias.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/ui/webui/help/version_updater.h" #include "chrome/browser/ui/webui/help/version_updater.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
...@@ -81,6 +82,7 @@ class SafetyCheckHandler ...@@ -81,6 +82,7 @@ class SafetyCheckHandler
protected: protected:
SafetyCheckHandler(std::unique_ptr<VersionUpdater> version_updater, SafetyCheckHandler(std::unique_ptr<VersionUpdater> version_updater,
password_manager::BulkLeakCheckService* leak_service, password_manager::BulkLeakCheckService* leak_service,
extensions::PasswordsPrivateDelegate* passwords_delegate,
extensions::ExtensionPrefs* extension_prefs, extensions::ExtensionPrefs* extension_prefs,
extensions::ExtensionServiceInterface* extension_service); extensions::ExtensionServiceInterface* extension_service);
...@@ -151,6 +153,7 @@ class SafetyCheckHandler ...@@ -151,6 +153,7 @@ class SafetyCheckHandler
std::unique_ptr<VersionUpdater> version_updater_; std::unique_ptr<VersionUpdater> version_updater_;
password_manager::BulkLeakCheckService* leak_service_ = nullptr; password_manager::BulkLeakCheckService* leak_service_ = nullptr;
extensions::PasswordsPrivateDelegate* passwords_delegate_ = nullptr;
extensions::ExtensionPrefs* extension_prefs_ = nullptr; extensions::ExtensionPrefs* extension_prefs_ = nullptr;
extensions::ExtensionServiceInterface* extension_service_ = nullptr; extensions::ExtensionServiceInterface* extension_service_ = nullptr;
ScopedObserver<password_manager::BulkLeakCheckService, ScopedObserver<password_manager::BulkLeakCheckService,
......
...@@ -9,13 +9,17 @@ ...@@ -9,13 +9,17 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/user_action_tester.h" #include "base/test/metrics/user_action_tester.h"
#include "base/util/type_safety/strong_alias.h" #include "base/util/type_safety/strong_alias.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
#include "chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h"
#include "chrome/browser/extensions/test_extension_service.h" #include "chrome/browser/extensions/test_extension_service.h"
#include "chrome/browser/ui/webui/help/test_version_updater.h" #include "chrome/browser/ui/webui/help/test_version_updater.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/crx_file/id_util.h" #include "components/crx_file/id_util.h"
#include "components/password_manager/core/browser/bulk_leak_check_service.h" #include "components/password_manager/core/browser/bulk_leak_check_service.h"
...@@ -52,14 +56,36 @@ class TestingSafetyCheckHandler : public SafetyCheckHandler { ...@@ -52,14 +56,36 @@ class TestingSafetyCheckHandler : public SafetyCheckHandler {
TestingSafetyCheckHandler( TestingSafetyCheckHandler(
std::unique_ptr<VersionUpdater> version_updater, std::unique_ptr<VersionUpdater> version_updater,
password_manager::BulkLeakCheckService* leak_service, password_manager::BulkLeakCheckService* leak_service,
extensions::PasswordsPrivateDelegate* passwords_delegate,
extensions::ExtensionPrefs* extension_prefs, extensions::ExtensionPrefs* extension_prefs,
extensions::ExtensionServiceInterface* extension_service) extensions::ExtensionServiceInterface* extension_service)
: SafetyCheckHandler(std::move(version_updater), : SafetyCheckHandler(std::move(version_updater),
leak_service, leak_service,
passwords_delegate,
extension_prefs, extension_prefs,
extension_service) {} extension_service) {}
}; };
class TestPasswordsDelegate : public extensions::TestPasswordsPrivateDelegate {
public:
void SetNumCompromisedCredentials(int compromised_password_count) {
compromised_password_count_ = compromised_password_count;
}
std::vector<extensions::api::passwords_private::CompromisedCredential>
GetCompromisedCredentials() override {
std::vector<extensions::api::passwords_private::CompromisedCredential>
compromised(compromised_password_count_);
for (int i = 0; i < compromised_password_count_; ++i) {
compromised[i].username = "test" + base::NumberToString(i);
}
return compromised;
}
private:
int compromised_password_count_ = 0;
};
class TestSafetyCheckExtensionService : public TestExtensionService { class TestSafetyCheckExtensionService : public TestExtensionService {
public: public:
void AddExtensionState(const std::string& extension_id, void AddExtensionState(const std::string& extension_id,
...@@ -118,14 +144,16 @@ class SafetyCheckHandlerTest : public ChromeRenderViewHostTestHarness { ...@@ -118,14 +144,16 @@ class SafetyCheckHandlerTest : public ChromeRenderViewHostTestHarness {
protected: protected:
TestVersionUpdater* version_updater_ = nullptr; TestVersionUpdater* version_updater_ = nullptr;
std::unique_ptr<password_manager::BulkLeakCheckService> test_leak_service_; std::unique_ptr<password_manager::BulkLeakCheckService> test_leak_service_;
TestPasswordsDelegate test_passwords_delegate_;
extensions::ExtensionPrefs* test_extension_prefs_ = nullptr; extensions::ExtensionPrefs* test_extension_prefs_ = nullptr;
TestSafetyCheckExtensionService test_extension_service_; TestSafetyCheckExtensionService test_extension_service_;
content::TestWebUI test_web_ui_; content::TestWebUI test_web_ui_;
std::unique_ptr<TestingSafetyCheckHandler> safety_check_; std::unique_ptr<TestingSafetyCheckHandler> safety_check_;
private: private:
// Replaces any instances of browser name (e.g. Google Chrome, Chromium, etc) // Replaces any instances of browser name (e.g. Google Chrome, Chromium,
// with "browser" to make sure tests work both on Chromium and Google Chrome. // etc) with "browser" to make sure tests work both on Chromium and
// Google Chrome.
void ReplaceBrowserName(base::string16* s); void ReplaceBrowserName(base::string16* s);
}; };
...@@ -143,7 +171,8 @@ void SafetyCheckHandlerTest::SetUp() { ...@@ -143,7 +171,8 @@ void SafetyCheckHandlerTest::SetUp() {
test_extension_prefs_ = extensions::ExtensionPrefs::Get(profile()); test_extension_prefs_ = extensions::ExtensionPrefs::Get(profile());
safety_check_ = std::make_unique<TestingSafetyCheckHandler>( safety_check_ = std::make_unique<TestingSafetyCheckHandler>(
std::move(version_updater), test_leak_service_.get(), std::move(version_updater), test_leak_service_.get(),
test_extension_prefs_, &test_extension_service_); &test_passwords_delegate_, test_extension_prefs_,
&test_extension_service_);
test_web_ui_.ClearTrackedCalls(); test_web_ui_.ClearTrackedCalls();
safety_check_->set_web_ui(&test_web_ui_); safety_check_->set_web_ui(&test_web_ui_);
safety_check_->AllowJavascript(); safety_check_->AllowJavascript();
...@@ -186,9 +215,9 @@ void SafetyCheckHandlerTest::VerifyDisplayString( ...@@ -186,9 +215,9 @@ void SafetyCheckHandlerTest::VerifyDisplayString(
base::string16 display; base::string16 display;
ASSERT_TRUE(event->GetString("displayString", &display)); ASSERT_TRUE(event->GetString("displayString", &display));
ReplaceBrowserName(&display); ReplaceBrowserName(&display);
// Need to also replace any instances of Chrome and Chromium in the expected // Need to also replace any instances of Chrome and Chromium in the
// string due to an edge case on ChromeOS, where a device name is "Chrome", // expected string due to an edge case on ChromeOS, where a device name
// which gets replaced in the display string. // is "Chrome", which gets replaced in the display string.
base::string16 expected_replaced = expected; base::string16 expected_replaced = expected;
ReplaceBrowserName(&expected_replaced); ReplaceBrowserName(&expected_replaced);
EXPECT_EQ(expected_replaced, display); EXPECT_EQ(expected_replaced, display);
...@@ -317,7 +346,8 @@ TEST_F(SafetyCheckHandlerTest, CheckUpdates_Failed) { ...@@ -317,7 +346,8 @@ TEST_F(SafetyCheckHandlerTest, CheckUpdates_Failed) {
VerifyDisplayString( VerifyDisplayString(
event, event,
"Browser didn't update, something went wrong. <a target=\"_blank\" " "Browser didn't update, something went wrong. <a target=\"_blank\" "
"href=\"https://support.google.com/chrome/answer/111996\">Fix Browser " "href=\"https://support.google.com/chrome/answer/111996\">Fix "
"Browser "
"update problems and failed updates.</a>"); "update problems and failed updates.</a>");
} }
...@@ -408,8 +438,8 @@ TEST_F(SafetyCheckHandlerTest, CheckPasswords_ObserverRemovedAfterError) { ...@@ -408,8 +438,8 @@ TEST_F(SafetyCheckHandlerTest, CheckPasswords_ObserverRemovedAfterError) {
VerifyDisplayString(event2, VerifyDisplayString(event2,
"Browser can't check your passwords. Try checking your " "Browser can't check your passwords. Try checking your "
"internet connection."); "internet connection.");
// Another error, but since the previous state is terminal, the handler should // Another error, but since the previous state is terminal, the handler
// no longer be observing the BulkLeakCheckService state. // should no longer be observing the BulkLeakCheckService state.
test_leak_service_->set_state_and_notify( test_leak_service_->set_state_and_notify(
password_manager::BulkLeakCheckService::State::kServiceError); password_manager::BulkLeakCheckService::State::kServiceError);
const base::DictionaryValue* event3 = const base::DictionaryValue* event3 =
...@@ -465,16 +495,59 @@ TEST_F(SafetyCheckHandlerTest, CheckPasswords_StartedTwice) { ...@@ -465,16 +495,59 @@ TEST_F(SafetyCheckHandlerTest, CheckPasswords_StartedTwice) {
kPasswords, kPasswords,
static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)); static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
ASSERT_TRUE(event); ASSERT_TRUE(event);
// Second, an "offline" state. // Then, a network error.
test_leak_service_->set_state_and_notify( test_leak_service_->set_state_and_notify(
password_manager::BulkLeakCheckService::State::kServiceError); password_manager::BulkLeakCheckService::State::kNetworkError);
const base::DictionaryValue* event2 = const base::DictionaryValue* event2 =
GetSafetyCheckStatusChangedWithDataIfExists( GetSafetyCheckStatusChangedWithDataIfExists(
kPasswords, kPasswords,
static_cast<int>(SafetyCheckHandler::PasswordsStatus::kError)); static_cast<int>(SafetyCheckHandler::PasswordsStatus::kOffline));
ASSERT_TRUE(event2); EXPECT_TRUE(event2);
VerifyDisplayString(event2, VerifyDisplayString(event2,
"Browser can't check your passwords. Try again later."); "Browser can't check your passwords. Try checking your "
"internet connection.");
}
TEST_F(SafetyCheckHandlerTest, CheckPasswords_Safe) {
safety_check_->PerformSafetyCheck();
// First, a "running" change of state.
test_leak_service_->set_state_and_notify(
password_manager::BulkLeakCheckService::State::kRunning);
EXPECT_TRUE(GetSafetyCheckStatusChangedWithDataIfExists(
kPasswords,
static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)));
// Second, a "safe" state.
test_leak_service_->set_state_and_notify(
password_manager::BulkLeakCheckService::State::kIdle);
const base::DictionaryValue* event =
GetSafetyCheckStatusChangedWithDataIfExists(
kPasswords,
static_cast<int>(SafetyCheckHandler::PasswordsStatus::kSafe));
EXPECT_TRUE(event);
VerifyDisplayString(event, "No compromised passwords found");
}
TEST_F(SafetyCheckHandlerTest, CheckPasswords_CompromisedExist) {
constexpr int kCompromised = 7;
test_passwords_delegate_.SetNumCompromisedCredentials(kCompromised);
safety_check_->PerformSafetyCheck();
// First, a "running" change of state.
test_leak_service_->set_state_and_notify(
password_manager::BulkLeakCheckService::State::kRunning);
EXPECT_TRUE(GetSafetyCheckStatusChangedWithDataIfExists(
kPasswords,
static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)));
// Compromised passwords found state.
test_leak_service_->set_state_and_notify(
password_manager::BulkLeakCheckService::State::kIdle);
const base::DictionaryValue* event2 =
GetSafetyCheckStatusChangedWithDataIfExists(
kPasswords,
static_cast<int>(
SafetyCheckHandler::PasswordsStatus::kCompromisedExist));
ASSERT_TRUE(event2);
VerifyDisplayString(
event2, base::NumberToString(kCompromised) + " compromised passwords");
} }
TEST_F(SafetyCheckHandlerTest, CheckExtensions_NoExtensions) { TEST_F(SafetyCheckHandlerTest, CheckExtensions_NoExtensions) {
...@@ -564,9 +637,9 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledAllByAdmin) { ...@@ -564,9 +637,9 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledAllByAdmin) {
GetSafetyCheckStatusChangedWithDataIfExists( GetSafetyCheckStatusChangedWithDataIfExists(
kExtensions, static_cast<int>(SafetyCheckHandler::ExtensionsStatus:: kExtensions, static_cast<int>(SafetyCheckHandler::ExtensionsStatus::
kBlocklistedReenabledAllByAdmin)); kBlocklistedReenabledAllByAdmin));
VerifyDisplayString( VerifyDisplayString(event,
event, "Your administrator turned 1 potentially harmful "
"Your administrator turned 1 potentially harmful extension back on"); "extension back on");
} }
TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) { TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) {
...@@ -598,10 +671,10 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) { ...@@ -598,10 +671,10 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) {
kExtensions, static_cast<int>(SafetyCheckHandler::ExtensionsStatus:: kExtensions, static_cast<int>(SafetyCheckHandler::ExtensionsStatus::
kBlocklistedReenabledSomeByUser)); kBlocklistedReenabledSomeByUser));
EXPECT_TRUE(event); EXPECT_TRUE(event);
VerifyDisplayString( VerifyDisplayString(event,
event, "You turned 1 potentially harmful extension back "
"You turned 1 potentially harmful extension back on. Your administrator " "on. Your administrator "
"turned 1 potentially harmful extension back on."); "turned 1 potentially harmful extension back on.");
} }
TEST_F(SafetyCheckHandlerTest, CheckExtensions_Error) { TEST_F(SafetyCheckHandlerTest, CheckExtensions_Error) {
......
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