Commit d8324cdb authored by Bettina's avatar Bettina Committed by Commit Bot

Create a listener for all gaia password changes.

Previously the listener only listened on changes to
kPasswordHashDataList. This is only good if the account
that has changed has already been given us. For all
content area account password changes, the username is
needed in order to find the appropriate account to report
the password change event to enterprise.

Bug: 914410
Change-Id: Iadf2753ddfc17570dbeb85a4936b72f12a166980
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1719975
Commit-Queue: Bettina Dea <bdea@chromium.org>
Reviewed-by: default avatarMustafa Emre Acer <meacer@chromium.org>
Reviewed-by: default avatarVarun Khaneja <vakh@chromium.org>
Reviewed-by: default avatarVadym Doroshenko <dvadym@chromium.org>
Cr-Commit-Position: refs/heads/master@{#684172}
parent bf7b2761
......@@ -18,7 +18,6 @@
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
......@@ -35,9 +34,6 @@
#include "chrome/common/url_constants.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/google/core/common/google_util.h"
#include "components/password_manager/core/browser/hash_password_manager.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
......@@ -223,10 +219,19 @@ ChromePasswordProtectionService::ChromePasswordProtectionService(
pref_change_registrar_(new PrefChangeRegistrar),
cache_manager_(sb_service->GetVerdictCacheManager(profile)) {
pref_change_registrar_->Init(profile_->GetPrefs());
pref_change_registrar_->Add(
password_manager::prefs::kPasswordHashDataList,
base::Bind(&ChromePasswordProtectionService::CheckGaiaPasswordChange,
base::Unretained(this)));
scoped_refptr<password_manager::PasswordStore> password_store =
PasswordStoreFactory::GetForProfile(profile_,
ServiceAccessType::EXPLICIT_ACCESS)
.get();
// Password store can be null in tests.
if (password_store) {
// Subscribe to gaia hash password changes change notifications.
hash_password_manager_subscription_ =
password_store->RegisterStateCallbackOnHashPasswordManager(
base::Bind(&ChromePasswordProtectionService::
CheckGaiaPasswordChangeForAllSignedInUsers,
base::Unretained(this)));
}
pref_change_registrar_->Add(
prefs::kPasswordProtectionWarningTrigger,
base::BindRepeating(
......@@ -333,15 +338,6 @@ bool ChromePasswordProtectionService::ShouldShowPasswordReusePageInfoBubble(
: false;
}
// static
bool ChromePasswordProtectionService::IsPasswordReuseProtectionConfigured(
Profile* profile) {
ChromePasswordProtectionService* service =
ChromePasswordProtectionService::GetPasswordProtectionService(profile);
return service &&
service->GetPasswordProtectionWarningTriggerPref() == PASSWORD_REUSE;
}
const policy::BrowserPolicyConnector*
ChromePasswordProtectionService::GetBrowserPolicyConnector() const {
return g_browser_process->browser_policy_connector();
......@@ -964,26 +960,44 @@ void ChromePasswordProtectionService::
}
}
void ChromePasswordProtectionService::CheckGaiaPasswordChange() {
// TODO(bdea): Check non-sync accounts.
void ChromePasswordProtectionService::
CheckGaiaPasswordChangeForAllSignedInUsers(const std::string& username) {
// If the sync password has changed, report the change.
std::string new_sync_password_hash = GetSyncPasswordHashFromPrefs();
if (sync_password_hash_ != new_sync_password_hash) {
sync_password_hash_ = new_sync_password_hash;
OnGaiaPasswordChanged();
OnGaiaPasswordChanged(username, /*is_other_gaia_password=*/false);
return;
}
// For non sync password changes, we have to loop through all the password
// hashes and find the hash associated with the username. Right now this
// double counts when a password is first saved which is inaccurate.
password_manager::HashPasswordManager hash_password_manager;
hash_password_manager.set_prefs(profile_->GetPrefs());
for (const auto& hash_data :
hash_password_manager.RetrieveAllPasswordHashes()) {
if (hash_data.username == username) {
OnGaiaPasswordChanged(username, /*is_other_gaia_password=*/true);
break;
}
}
}
void ChromePasswordProtectionService::OnGaiaPasswordChanged() {
DictionaryPrefUpdate unhandled_sync_password_reuses(
void ChromePasswordProtectionService::OnGaiaPasswordChanged(
const std::string& username,
bool is_other_gaia_password) {
DictionaryPrefUpdate unhandled_gaia_password_reuses(
profile_->GetPrefs(), prefs::kSafeBrowsingUnhandledSyncPasswordReuses);
LogNumberOfReuseBeforeSyncPasswordChange(
unhandled_sync_password_reuses->size());
unhandled_sync_password_reuses->Clear();
unhandled_gaia_password_reuses->size());
unhandled_gaia_password_reuses->Clear();
MaybeLogPasswordCapture(/*did_log_in=*/true);
for (auto& observer : observer_list_)
observer.OnGaiaPasswordChanged();
if (!IsPrimaryAccountGmail())
// TODO(bdea): Take into account other gaia password.
if ((!is_other_gaia_password && !IsPrimaryAccountGmail()))
ReportPasswordChanged();
}
......@@ -1363,14 +1377,17 @@ int ChromePasswordProtectionService::GetStoredVerdictCount(
}
void ChromePasswordProtectionService::OnWarningTriggerChanged() {
if (GetPasswordProtectionWarningTriggerPref() != PASSWORD_PROTECTION_OFF)
const base::Value* pref_value = pref_change_registrar_->prefs()->Get(
prefs::kPasswordProtectionWarningTrigger);
// If password protection is not turned off, do nothing.
if (pref_value->GetInt() != 0) {
return;
}
// Clears captured enterprise password hashes or GSuite sync password hashes.
scoped_refptr<password_manager::PasswordStore> password_store =
PasswordStoreFactory::GetForProfile(profile_,
ServiceAccessType::EXPLICIT_ACCESS);
if (!IsPrimaryAccountGmail())
password_store->ClearGaiaPasswordHash(GetAccountInfo().email);
password_store->ClearAllEnterprisePasswordHash();
......
......@@ -7,10 +7,16 @@
#include <map>
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/observer_list.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "components/password_manager/core/browser/hash_password_manager.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/safe_browsing/password_protection/password_protection_service.h"
#include "components/safe_browsing/triggers/trigger_manager.h"
#include "components/sessions/core/session_id.h"
......@@ -66,7 +72,7 @@ class ChromePasswordProtectionService : public PasswordProtectionService {
// change password card, etc) in reaction to user events.
class Observer {
public:
// Called when user completes the Gaia password reset.
// Called when user completes the GAIA password reset.
virtual void OnGaiaPasswordChanged() = 0;
// Called when user marks the site as legitimate.
......@@ -98,10 +104,6 @@ class ChromePasswordProtectionService : public PasswordProtectionService {
content::WebContents* web_contents,
PasswordType password_type);
// Called by ChromeWebUIControllerFactory class to determine if Chrome should
// show chrome://reset-password page.
static bool IsPasswordReuseProtectionConfigured(Profile* profile);
void ShowModalWarning(content::WebContents* web_contents,
const std::string& verdict_token,
PasswordType password_type) override;
......@@ -132,11 +134,17 @@ class ChromePasswordProtectionService : public PasswordProtectionService {
void MaybeFinishCollectingThreatDetails(content::WebContents* web_contents,
bool did_proceed);
// Check if Gaia password hash is changed.
void CheckGaiaPasswordChange();
// Check if Gaia password hash has changed. If it is changed, it will call
// |OnGaiaPasswordChanged|. |username| is used to get the appropriate account
// to check if the account is a Gmail account as no reporting is done for
// those accounts.
void CheckGaiaPasswordChangeForAllSignedInUsers(const std::string& username);
// Called when sync user's Gaia password changed.
void OnGaiaPasswordChanged();
// Called when user's GAIA password changed. |username| is used to get
// the account the password is associated with. |is_other_gaia_password|
// specifies whether the account is syncing or not syncing (content area).
void OnGaiaPasswordChanged(const std::string& username,
bool is_other_gaia_password);
// If user has clicked through any Safe Browsing interstitial on this given
// |web_contents|.
......@@ -433,6 +441,12 @@ class ChromePasswordProtectionService : public PasswordProtectionService {
std::set<content::WebContents*>
web_contents_with_unhandled_enterprise_reuses_;
// Subscription for state changes. When this subscription is notified, it
// means HashPasswordManager password data list has changed.
std::unique_ptr<
base::CallbackList<void(const std::string& username)>::Subscription>
hash_password_manager_subscription_;
// Reference to the current profile's VerdictCacheManager. This is unowned.
VerdictCacheManager* cache_manager_;
......
......@@ -69,14 +69,20 @@ class ChromePasswordProtectionServiceBrowserTest : public InProcessBrowserTest {
}
void SimulateGaiaPasswordChange(const std::string& new_password) {
password_manager::HashPasswordManager hash_manager;
hash_manager.set_prefs(browser()->profile()->GetPrefs());
hash_manager.SavePasswordHash(user_manager::kStubUserEmail,
base::UTF8ToUTF16(new_password));
scoped_refptr<password_manager::PasswordStore> password_store =
PasswordStoreFactory::GetForProfile(browser()->profile(),
ServiceAccessType::EXPLICIT_ACCESS)
.get();
password_store->SaveGaiaPasswordHash(
user_manager::kStubUserEmail, base::UTF8ToUTF16(new_password),
password_manager::metrics_util::SyncPasswordHashChange::
CHANGED_IN_CONTENT_AREA);
}
void SimulateGaiaPasswordChanged(ChromePasswordProtectionService* service) {
service->OnGaiaPasswordChanged();
void SimulateGaiaPasswordChanged(ChromePasswordProtectionService* service,
const std::string& username,
bool is_other_gaia_password) {
service->OnGaiaPasswordChanged(username, is_other_gaia_password);
}
security_state::SecurityLevel GetSecurityLevel(
......@@ -203,7 +209,8 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
.DomainIs("google.com"));
// Simulates user finished changing password.
SimulateGaiaPasswordChanged(service);
SimulateGaiaPasswordChanged(service, user_manager::kStubUserEmail,
/*is_other_gaia_password=*/true);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(
ChromePasswordProtectionService::ShouldShowChangePasswordSettingUI(
......@@ -392,7 +399,8 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
profile));
// Simulates a Gaia password change.
SimulateGaiaPasswordChange("new_password");
SimulateGaiaPasswordChanged(service, user_manager::kStubUserEmail,
/*is_other_password=*/true);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u,
profile->GetPrefs()
......@@ -411,11 +419,14 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
Profile* profile = browser()->profile();
ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
// Configures initial password to "password_1";
password_manager::PasswordHashData hash_data(
user_manager::kStubUserEmail, base::UTF8ToUTF16("password_1"), true);
password_manager::HashPasswordManager hash_manager;
hash_manager.set_prefs(profile->GetPrefs());
hash_manager.SavePasswordHash(hash_data);
scoped_refptr<password_manager::PasswordStore> password_store =
PasswordStoreFactory::GetForProfile(browser()->profile(),
ServiceAccessType::EXPLICIT_ACCESS)
.get();
password_store->SaveGaiaPasswordHash(
user_manager::kStubUserEmail, base::UTF8ToUTF16("password_1"),
password_manager::metrics_util::SyncPasswordHashChange::
CHANGED_IN_CONTENT_AREA);
ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/"));
// Shows modal dialog on current web_contents.
......@@ -464,7 +475,8 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
profile));
// Simulates a Gaia password change.
SimulateGaiaPasswordChanged(GetService(/*is_incognito=*/false));
SimulateGaiaPasswordChanged(GetService(/*is_incognito=*/false), "username",
/*is_other_gaia_password=*/true);
EXPECT_FALSE(
ChromePasswordProtectionService::ShouldShowChangePasswordSettingUI(
profile));
......@@ -474,45 +486,6 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
->empty());
}
IN_PROC_BROWSER_TEST_F(
ChromePasswordProtectionServiceBrowserTest,
VerifyIsPasswordReuseProtectionConfiguredForNonDomainUser) {
Profile* profile = browser()->profile();
ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
// If prefs::kPasswordProtectionWarningTrigger isn't set to PASSWORD_REUSE,
// |IsPasswordReuseProtectionConfigured(..)| returns false.
EXPECT_EQ(PHISHING_REUSE, service->GetPasswordProtectionWarningTriggerPref());
EXPECT_FALSE(
ChromePasswordProtectionService::IsPasswordReuseProtectionConfigured(
profile));
SetUpPrimaryAccountWithHostedDomain(kNoHostedDomainFound);
profile->GetPrefs()->SetInteger(prefs::kPasswordProtectionWarningTrigger,
PasswordProtectionTrigger::PASSWORD_REUSE);
// Otherwise, |IsPasswordReuseProtectionConfigured(..)| returns false for
// GMAIL users.
EXPECT_FALSE(
ChromePasswordProtectionService::IsPasswordReuseProtectionConfigured(
profile));
}
IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
VerifyIsPasswordReuseProtectionConfiguredForDomainUser) {
Profile* profile = browser()->profile();
ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
SetUpPrimaryAccountWithHostedDomain("domain.com");
EXPECT_EQ(PHISHING_REUSE, service->GetPasswordProtectionWarningTriggerPref());
EXPECT_FALSE(
ChromePasswordProtectionService::IsPasswordReuseProtectionConfigured(
profile));
profile->GetPrefs()->SetInteger(prefs::kPasswordProtectionWarningTrigger,
PasswordProtectionTrigger::PASSWORD_REUSE);
EXPECT_TRUE(
ChromePasswordProtectionService::IsPasswordReuseProtectionConfigured(
profile));
}
IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
ChromeEnterprisePasswordAlertMode) {
ConfigureEnterprisePasswordProtection(
......@@ -687,24 +660,20 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
ConfigureEnterprisePasswordProtection(
/*is_gsuite=*/true, PasswordProtectionTrigger::PHISHING_REUSE);
Profile* profile = browser()->profile();
ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
password_manager::HashPasswordManager hash_password_manager;
hash_password_manager.set_prefs(profile->GetPrefs());
hash_password_manager.SavePasswordHash(service->GetAccountInfo().email,
base::UTF8ToUTF16("password"),
/*is_gaia_password=*/true);
SimulateGaiaPasswordChange("password");
ASSERT_EQ(1u, profile->GetPrefs()
->GetList(password_manager::prefs::kPasswordHashDataList)
->GetList()
.size());
// Turn off trigger
profile->GetPrefs()->SetInteger(
prefs::kPasswordProtectionWarningTrigger,
PasswordProtectionTrigger::PASSWORD_PROTECTION_OFF);
base::RunLoop().RunUntilIdle();
password_manager::HashPasswordManager hash_password_manager;
hash_password_manager.set_prefs(profile->GetPrefs());
EXPECT_FALSE(hash_password_manager.HasPasswordHash(
service->GetAccountInfo().email, /*is_gaia_password=*/true));
user_manager::kStubUserEmail, /*is_gaia_password=*/true));
EXPECT_EQ(0u, profile->GetPrefs()
->GetList(password_manager::prefs::kPasswordHashDataList)
->GetList()
......@@ -716,13 +685,22 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
ConfigureEnterprisePasswordProtection(
/*is_gsuite=*/false, PasswordProtectionTrigger::PHISHING_REUSE);
Profile* profile = browser()->profile();
password_manager::HashPasswordManager hash_password_manager;
hash_password_manager.set_prefs(profile->GetPrefs());
hash_password_manager.SavePasswordHash(
"username", base::UTF8ToUTF16("password"), /*is_gaia_password=*/false);
hash_password_manager.SavePasswordHash("foo@gmail.com",
base::UTF8ToUTF16("password"),
/*is_gaia_password=*/true);
ASSERT_EQ(0u, profile->GetPrefs()
->GetList(password_manager::prefs::kPasswordHashDataList)
->GetList()
.size());
// Configures initial password to "password_1";
scoped_refptr<password_manager::PasswordStore> password_store =
PasswordStoreFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS)
.get();
password_store->SaveEnterprisePasswordHash("username@domain.com",
base::UTF8ToUTF16("password_1"));
password_store->SaveGaiaPasswordHash(
user_manager::kStubUserEmail, base::UTF8ToUTF16("password_2"),
password_manager::metrics_util::SyncPasswordHashChange::
CHANGED_IN_CONTENT_AREA);
ASSERT_EQ(2u, profile->GetPrefs()
->GetList(password_manager::prefs::kPasswordHashDataList)
->GetList()
......@@ -732,11 +710,14 @@ IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
profile->GetPrefs()->SetInteger(
prefs::kPasswordProtectionWarningTrigger,
PasswordProtectionTrigger::PASSWORD_PROTECTION_OFF);
base::RunLoop().RunUntilIdle();
password_manager::HashPasswordManager hash_password_manager;
hash_password_manager.set_prefs(profile->GetPrefs());
EXPECT_FALSE(hash_password_manager.HasPasswordHash(
"username", /*is_gaia_password=*/false));
EXPECT_TRUE(hash_password_manager.HasPasswordHash("foo@gmail.com",
/*is_gaia_password=*/true));
"username@domain.com", /*is_gaia_password=*/false));
EXPECT_TRUE(
hash_password_manager.HasPasswordHash(user_manager::kStubUserEmail,
/*is_gaia_password=*/true));
EXPECT_EQ(1u, profile->GetPrefs()
->GetList(password_manager::prefs::kPasswordHashDataList)
->GetList()
......
......@@ -12,6 +12,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/safe_browsing/test_extension_event_observer.h"
#include "chrome/browser/safe_browsing/ui_manager.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
......@@ -25,6 +26,8 @@
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/password_manager/core/browser/hash_password_manager.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/test_password_store.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/safe_browsing/common/utils.h"
......@@ -148,6 +151,18 @@ class ChromePasswordProtectionServiceTest
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
// Use TestPasswordStore to remove a possible race. Normally the
// PasswordStore does its database manipulation on the DB thread, which
// creates a possible race during navigation. Specifically the
// PasswordManager will ignore any forms in a page if the load from the
// PasswordStore has not completed.
PasswordStoreFactory::GetInstance()->SetTestingFactory(
profile(),
base::BindRepeating(
&password_manager::BuildPasswordStore<
content::BrowserContext, password_manager::TestPasswordStore>));
profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled, true);
profile()->GetPrefs()->SetInteger(
prefs::kPasswordProtectionWarningTrigger,
......@@ -966,7 +981,7 @@ TEST_F(ChromePasswordProtectionServiceTest,
SetUpSyncAccount("example.com", account_info);
// Simulates change password.
service_->OnGaiaPasswordChanged();
service_->OnGaiaPasswordChanged("foo@example.com", false);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(1, test_event_router_->GetEventCount(
......@@ -977,7 +992,7 @@ TEST_F(ChromePasswordProtectionServiceTest,
// If user is in incognito mode, no event should be sent.
service_->ConfigService(true /*incognito*/, false /*SBER*/);
service_->OnGaiaPasswordChanged();
service_->OnGaiaPasswordChanged("foo@example.com", false);
base::RunLoop().RunUntilIdle();
// Event count should be unchanged.
EXPECT_EQ(1, test_event_router_->GetEventCount(
......
......@@ -1066,7 +1066,7 @@ IN_PROC_BROWSER_TEST_F(
// Simulates a Gaia password change, then malicious content status will
// change to MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING.
service->OnGaiaPasswordChanged();
service->OnGaiaPasswordChanged(/*username=*/"", false);
base::RunLoop().RunUntilIdle();
visible_security_state = helper->GetVisibleSecurityState();
EXPECT_EQ(security_state::DANGEROUS, helper->GetSecurityLevel());
......
......@@ -143,6 +143,8 @@ base::Optional<PasswordHashData> ConvertToPasswordHashData(
} // namespace
HashPasswordManager::HashPasswordManager(PrefService* prefs) : prefs_(prefs) {}
HashPasswordManager::HashPasswordManager() = default;
HashPasswordManager::~HashPasswordManager() = default;
bool HashPasswordManager::SavePasswordHash(const std::string username,
const base::string16& password,
......@@ -168,9 +170,10 @@ bool HashPasswordManager::SavePasswordHash(const std::string username,
}
}
}
return SavePasswordHash(
bool is_saved = SavePasswordHash(
PasswordHashData(username, password, true, is_gaia_password));
state_callback_list_.Notify(username);
return is_saved;
}
bool HashPasswordManager::SavePasswordHash(
......@@ -270,6 +273,11 @@ bool HashPasswordManager::HasPasswordHash(const std::string& username,
return false;
}
std::unique_ptr<StateSubscription> HashPasswordManager::RegisterStateCallback(
const base::Callback<void(const std::string& username)>& callback) {
return state_callback_list_.Add(callback);
}
bool HashPasswordManager::EncryptAndSaveToPrefs(const std::string& pref_name,
const std::string& s) {
std::string encrypted_base64_text = EncryptString(s);
......
......@@ -5,6 +5,8 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HASH_PASSWORD_MANAGER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HASH_PASSWORD_MANAGER_H_
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
......@@ -12,6 +14,9 @@
class PrefService;
using StateSubscription =
base::CallbackList<void(const std::string& username)>::Subscription;
namespace password_manager {
// Responsible for saving, clearing, retrieving and encryption of a password
......@@ -19,9 +24,9 @@ namespace password_manager {
// All methods should be called on UI thread.
class HashPasswordManager {
public:
HashPasswordManager() = default;
HashPasswordManager();
explicit HashPasswordManager(PrefService* prefs);
~HashPasswordManager() = default;
~HashPasswordManager();
bool SavePasswordHash(const std::string username,
const base::string16& password,
......@@ -48,6 +53,11 @@ class HashPasswordManager {
void set_prefs(PrefService* prefs) { prefs_ = prefs; }
// Adds a listener for when |kPasswordHashDataList| list might have changed.
// Should only be called on the UI thread.
virtual std::unique_ptr<StateSubscription> RegisterStateCallback(
const base::Callback<void(const std::string& username)>& callback);
private:
// Saves encrypted string |s| in a preference |pref_name|. Returns true on
// success.
......@@ -63,6 +73,10 @@ class HashPasswordManager {
PrefService* prefs_ = nullptr;
// Callbacks when |kPasswordHashDataList| might have changed.
// Should only be accessed on the UI thread.
base::CallbackList<void(const std::string& username)> state_callback_list_;
DISALLOW_COPY_AND_ASSIGN(HashPasswordManager);
};
......
......@@ -459,6 +459,12 @@ void PasswordStore::ClearAllEnterprisePasswordHash() {
&PasswordStore::ClearAllEnterprisePasswordHashImpl, this));
}
std::unique_ptr<StateSubscription>
PasswordStore::RegisterStateCallbackOnHashPasswordManager(
const base::Callback<void(const std::string& username)>& callback) {
return hash_password_manager_.RegisterStateCallback(callback);
}
void PasswordStore::SetPasswordStoreSigninNotifier(
std::unique_ptr<PasswordStoreSigninNotifier> notifier) {
DCHECK(!notifier_);
......
......@@ -11,6 +11,7 @@
#include <vector>
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/observer_list_threadsafe.h"
......@@ -43,6 +44,9 @@ class ProxyModelTypeControllerDelegate;
class SyncableService;
}
using StateSubscription =
base::CallbackList<void(const std::string& username)>::Subscription;
namespace password_manager {
class AffiliatedMatchHelper;
......@@ -284,6 +288,12 @@ class PasswordStore : protected PasswordStoreSync,
// Clears all (non-Gaia) enterprise password hash.
virtual void ClearAllEnterprisePasswordHash();
// Adds a listener on |hash_password_manager_| for when |kHashPasswordData|
// list might have changed. Should only be called on the UI thread.
virtual std::unique_ptr<StateSubscription>
RegisterStateCallbackOnHashPasswordManager(
const base::Callback<void(const std::string& username)>& callback);
// Shouldn't be called more than once, |notifier| must be not nullptr.
void SetPasswordStoreSigninNotifier(
std::unique_ptr<PasswordStoreSigninNotifier> notifier);
......
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