blob: 10688ff4f1b900cfe2b20aae2697332b34a2b639 [file] [log] [blame]
// Copyright (c) 2015 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 <memory>
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/password_manager/account_password_store_factory.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/sync/test/integration/passwords_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/browsing_data/core/browsing_data_utils.h"
#include "components/browsing_data/core/counters/passwords_counter.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/password_manager/core/browser/password_form.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/password_store_interface.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test.h"
namespace {
using browsing_data::BrowsingDataCounter;
using password_manager::PasswordForm;
class PasswordsCounterTest : public InProcessBrowserTest {
public:
void SetUpOnMainThread() override {
finished_ = false;
time_ = base::Time::Now();
times_used_ = 0;
store_ = PasswordStoreFactory::GetForProfile(
browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
.get();
SetPasswordsDeletionPref(true);
SetDeletionPeriodPref(browsing_data::TimePeriod::ALL_TIME);
}
void AddLogin(const std::string& origin,
const std::string& username,
bool blocked_by_user) {
// Add login and wait until the password store actually changes.
// on the database thread.
store_->AddLogin(CreateCredentials(origin, username, blocked_by_user));
// GetLogins() blocks until reading on the background thread is finished.
passwords_helper::GetLogins(store_);
}
void RemoveLogin(const std::string& origin,
const std::string& username,
bool blocked_by_user) {
// Remove login and wait until the password store actually changes
// on the database thread.
store_->RemoveLogin(CreateCredentials(origin, username, blocked_by_user));
// GetLogins() blocks until reading on the background thread is finished.
passwords_helper::GetLogins(store_);
}
void SetPasswordsDeletionPref(bool value) {
browser()->profile()->GetPrefs()->SetBoolean(
browsing_data::prefs::kDeletePasswords, value);
}
void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
browser()->profile()->GetPrefs()->SetInteger(
browsing_data::prefs::kDeleteTimePeriod, static_cast<int>(period));
}
void RevertTimeInDays(int days) {
time_ -= base::TimeDelta::FromDays(days);
}
void SetTimesUsed(int occurrences) { times_used_ = occurrences; }
void WaitForCounting() {
// The counting takes place on the background thread. Wait until it
// finishes. GetLogins() blocks until reading on the background thread is
// finished
passwords_helper::GetLogins(store_);
// At this point, the calculation on DB thread should have finished, and
// a callback should be scheduled on the UI thread. Process the tasks until
// we get a finished result.
if (finished_)
return;
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}
// Once the GetResult() or GetDomainExamples() is called, it can be called
// again until the next result is available.
BrowsingDataCounter::ResultInt GetResult() {
DCHECK(finished_);
// Some tests call WaitForCounting() multiple times. Set `finished_` to
// false such that next call of WaitForCounting() will indeed block until
// counting is done.
finished_ = false;
return result_;
}
// Once the GetResult() or GetDomainExamples() is called, it can be called
// again until the next result is available.
std::vector<std::string> GetDomainExamples() {
DCHECK(finished_);
// Some tests call WaitForCounting() multiple times. Set `finished_` to
// false such that next call of WaitForCounting() will indeed block until
// counting is done.
finished_ = false;
return domain_examples_;
}
void Callback(std::unique_ptr<BrowsingDataCounter::Result> result) {
DCHECK(result);
finished_ = result->Finished();
if (finished_) {
auto* password_result =
static_cast<browsing_data::PasswordsCounter::PasswordsResult*>(
result.get());
result_ = password_result->Value();
domain_examples_ = password_result->domain_examples();
}
if (run_loop_ && finished_)
run_loop_->Quit();
}
private:
PasswordForm CreateCredentials(const std::string& origin,
const std::string& username,
bool blocked_by_user) {
PasswordForm result;
result.signon_realm = origin;
result.url = GURL(origin);
result.username_value = base::ASCIIToUTF16(username);
result.password_value = u"hunter2";
result.blocked_by_user = blocked_by_user;
result.date_created = time_;
result.times_used = times_used_;
return result;
}
password_manager::PasswordStoreInterface* store_;
std::unique_ptr<base::RunLoop> run_loop_;
base::Time time_;
int times_used_;
bool finished_;
BrowsingDataCounter::ResultInt result_;
std::vector<std::string> domain_examples_;
};
// Tests that the counter correctly counts each individual credential on
// the same domain.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, SameDomain) {
AddLogin("https://www.google.com", "user1", false);
AddLogin("https://www.google.com", "user2", false);
AddLogin("https://www.google.com", "user3", false);
AddLogin("https://www.chrome.com", "user1", false);
AddLogin("https://www.chrome.com", "user2", false);
Profile* profile = browser()->profile();
browsing_data::PasswordsCounter counter(
PasswordStoreFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS),
AccountPasswordStoreFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS),
SyncServiceFactory::GetForProfile(profile));
counter.Init(profile->GetPrefs(),
browsing_data::ClearBrowsingDataTab::ADVANCED,
base::BindRepeating(&PasswordsCounterTest::Callback,
base::Unretained(this)));
counter.Restart();
WaitForCounting();
EXPECT_EQ(5u, GetResult());
}
// Tests that the counter doesn't count blocklisted entries.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, blocklisted) {
AddLogin("https://www.google.com", "user1", false);
AddLogin("https://www.google.com", "user2", true);
AddLogin("https://www.chrome.com", "user3", true);
Profile* profile = browser()->profile();
browsing_data::PasswordsCounter counter(
PasswordStoreFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS),
AccountPasswordStoreFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS),
SyncServiceFactory::GetForProfile(profile));
counter.Init(profile->GetPrefs(),
browsing_data::ClearBrowsingDataTab::ADVANCED,
base::BindRepeating(&PasswordsCounterTest::Callback,
base::Unretained(this)));
counter.Restart();
WaitForCounting();
EXPECT_EQ(1u, GetResult());
}
// Tests that the counter starts counting automatically when the deletion
// pref changes to true.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, PrefChanged) {
SetPasswordsDeletionPref(false);
AddLogin("https://www.google.com", "user", false);
AddLogin("https://www.chrome.com", "user", false);
Profile* profile = browser()->profile();
browsing_data::PasswordsCounter counter(
PasswordStoreFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS),
AccountPasswordStoreFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS),
SyncServiceFactory::GetForProfile(profile));
counter.Init(profile->GetPrefs(),
browsing_data::ClearBrowsingDataTab::ADVANCED,
base::BindRepeating(&PasswordsCounterTest::Callback,
base::Unretained(this)));
SetPasswordsDeletionPref(true);
WaitForCounting();
EXPECT_EQ(2u, GetResult());
}
// Tests that the counter starts counting automatically when
// the password store changes.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, StoreChanged) {
AddLogin("https://www.google.com", "user", false);
Profile* profile = browser()->profile();
browsing_data::PasswordsCounter counter(
PasswordStoreFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS),
AccountPasswordStoreFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS),
SyncServiceFactory::GetForProfile(profile));
counter.Init(profile->GetPrefs(),
browsing_data::ClearBrowsingDataTab::ADVANCED,
base::BindRepeating(&PasswordsCounterTest::Callback,
base::Unretained(this)));
counter.Restart();
WaitForCounting();
EXPECT_EQ(1u, GetResult());
AddLogin("https://www.chrome.com", "user", false);
WaitForCounting();
EXPECT_EQ(2u, GetResult());
RemoveLogin("https://www.chrome.com", "user", false);
WaitForCounting();
EXPECT_EQ(1u, GetResult());
}
// Tests that changing the deletion period restarts the counting, and that
// the result takes login creation dates into account.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, PeriodChanged) {
AddLogin("https://www.google.com", "user", false);
RevertTimeInDays(2);
AddLogin("https://example.com", "user1", false);
RevertTimeInDays(3);
AddLogin("https://example.com", "user2", false);
RevertTimeInDays(30);
AddLogin("https://www.chrome.com", "user", false);
Profile* profile = browser()->profile();
browsing_data::PasswordsCounter counter(
PasswordStoreFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS),
AccountPasswordStoreFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS),
SyncServiceFactory::GetForProfile(profile));
counter.Init(profile->GetPrefs(),
browsing_data::ClearBrowsingDataTab::ADVANCED,
base::BindRepeating(&PasswordsCounterTest::Callback,
base::Unretained(this)));
SetDeletionPeriodPref(browsing_data::TimePeriod::LAST_HOUR);
WaitForCounting();
EXPECT_EQ(1u, GetResult());
SetDeletionPeriodPref(browsing_data::TimePeriod::LAST_DAY);
WaitForCounting();
EXPECT_EQ(1u, GetResult());
SetDeletionPeriodPref(browsing_data::TimePeriod::LAST_WEEK);
WaitForCounting();
EXPECT_EQ(3u, GetResult());
SetDeletionPeriodPref(browsing_data::TimePeriod::FOUR_WEEKS);
WaitForCounting();
EXPECT_EQ(3u, GetResult());
SetDeletionPeriodPref(browsing_data::TimePeriod::OLDER_THAN_30_DAYS);
WaitForCounting();
EXPECT_EQ(1u, GetResult());
SetDeletionPeriodPref(browsing_data::TimePeriod::ALL_TIME);
WaitForCounting();
EXPECT_EQ(4u, GetResult());
}
// Tests that the two most commonly used domains are chosen as the listed domain
// examples.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, MostCommonDomains) {
SetTimesUsed(3);
AddLogin("https://www.google.com", "user", false);
SetTimesUsed(4);
AddLogin("https://wwww.maps.google.com", "user", false);
SetTimesUsed(1);
AddLogin("https://www.example.com", "user", false);
SetTimesUsed(2);
AddLogin("https://www.chrome.com", "user", false);
Profile* profile = browser()->profile();
browsing_data::PasswordsCounter counter(
PasswordStoreFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS),
AccountPasswordStoreFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS),
SyncServiceFactory::GetForProfile(profile));
counter.Init(profile->GetPrefs(),
browsing_data::ClearBrowsingDataTab::ADVANCED,
base::BindRepeating(&PasswordsCounterTest::Callback,
base::Unretained(this)));
counter.Restart();
WaitForCounting();
std::vector<std::string> domain_examples = {"google.com", "chrome.com"};
EXPECT_EQ(domain_examples, GetDomainExamples());
}
} // namespace