Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(388)

Unified Diff: components/password_manager/core/browser/form_fetcher_impl_unittest.cc

Issue 2878463003: Introduce SuppressedHTTPSFormFetcher. (Closed)
Patch Set: Polish. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/password_manager/core/browser/form_fetcher_impl_unittest.cc
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index 90c36a90dbf9ad13e8a29391c28639b217517182..6373db3549eeca91c6291d9e45abb3fcf3f13a1e 100644
--- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -44,6 +44,12 @@ namespace password_manager {
namespace {
+const char kTestHttpRealm[] = "http://accounts.google.com/";
+const char kTestHttpURL[] = "http://accounts.google.com/a/LoginAuth";
+
+const char kTestHttpsRealm[] = "https://accounts.google.com/";
+const char kTestHttpsURL[] = "https://accounts.google.com/a/LoginAuth";
+
class MockConsumer : public FormFetcher::Consumer {
public:
MOCK_METHOD2(ProcessMatches,
@@ -128,7 +134,7 @@ PasswordForm CreateHTTPNonFederated() {
PasswordForm CreateFederated() {
PasswordForm form = CreateNonFederated();
form.password_value.clear();
- form.federation_origin = url::Origin(GURL("https://accounts.google.com/"));
+ form.federation_origin = url::Origin(GURL(kTestHttpsRealm));
return form;
}
@@ -162,13 +168,14 @@ class FormFetcherImplTest : public testing::Test {
public:
FormFetcherImplTest()
: form_digest_(PasswordForm::SCHEME_HTML,
- "http://accounts.google.com",
- GURL("http://accounts.google.com/a/LoginAuth")) {
+ kTestHttpRealm,
+ GURL(kTestHttpURL)) {
mock_store_ = new MockPasswordStore();
client_.set_store(mock_store_.get());
form_fetcher_ = base::MakeUnique<FormFetcherImpl>(
- form_digest_, &client_, /* should_migrate_http_passwords */ false);
+ form_digest_, &client_, false /* should_migrate_http_passwords */,
+ false /* should_query_suppressed_https_forms */);
}
~FormFetcherImplTest() override { mock_store_->ShutdownOnUIThread(); }
@@ -186,6 +193,52 @@ class FormFetcherImplTest : public testing::Test {
testing::Mock::VerifyAndClearExpectations(mock_store_.get());
}
+ void RecreateFormFetcherWithQueryingSuppressedHTTPSForms() {
+ form_fetcher_ = base::MakeUnique<FormFetcherImpl>(
+ form_digest_, &client_, false /* should_migrate_http_passwords */,
+ true /* should_query_suppressed_https_forms */);
+ EXPECT_CALL(consumer_, ProcessMatches(IsEmpty(), 0u));
+ form_fetcher_->AddConsumer(&consumer_);
+ testing::Mock::VerifyAndClearExpectations(&consumer_);
+ }
+
+ // Simulates a call to Fetch(), and supplies |simulated_matches| as the
+ // PasswordStore results. Expects that this will trigger the querying of
+ // suppressed HTTPS forms by means of a GetLogins call being issued against
+ // the |expected_form_digest|. Call CompleteQueryingSuppressedHTTPSForms with
+ // the emitted |consumer_ptr| to complete the query.
+ void SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ const std::vector<PasswordForm>& simulated_http_matches,
+ const PasswordStore::FormDigest expected_form_digest,
+ base::WeakPtr<PasswordStoreConsumer>* consumer_ptr /* out */) {
+ ASSERT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
+
+ Fetch();
+
+ EXPECT_CALL(*mock_store_, GetLogins(expected_form_digest, _))
+ .WillOnce(::testing::WithArg<1>(GetAndAssignWeakPtr(consumer_ptr)));
+ const size_t num_matches = simulated_http_matches.size();
+ EXPECT_CALL(consumer_, ProcessMatches(::testing::SizeIs(num_matches), 0u));
+
+ form_fetcher_->OnGetPasswordStoreResults(
+ MakeResults(simulated_http_matches));
+
+ ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&consumer_));
+ ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(mock_store_.get()));
+ ASSERT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
+ ASSERT_TRUE(*consumer_ptr);
+ }
+
+ void CompleteQueryingSuppressedHTTPSForms(
+ const std::vector<PasswordForm>& simulated_suppressed_https_forms,
+ base::WeakPtr<PasswordStoreConsumer> consumer_ptr) {
+ ASSERT_TRUE(consumer_ptr);
+ ASSERT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
+ consumer_ptr->OnGetPasswordStoreResults(
+ MakeResults(simulated_suppressed_https_forms));
+ ASSERT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
+ }
+
base::MessageLoop message_loop_; // Used by mock_store_.
PasswordStore::FormDigest form_digest_;
std::unique_ptr<FormFetcherImpl> form_fetcher_;
@@ -399,7 +452,8 @@ TEST_F(FormFetcherImplTest, DoNotTryToMigrateHTTPPasswordsOnHTTPSites) {
// A new form fetcher is created to be able to set the form digest and
// migration flag.
form_fetcher_ = base::MakeUnique<FormFetcherImpl>(
- form_digest_, &client_, /* should_migrate_http_passwords */ true);
+ form_digest_, &client_, true /* should_migrate_http_passwords */,
+ false /* should_query_suppressed_https_forms */);
EXPECT_CALL(consumer_, ProcessMatches(IsEmpty(), 0u));
form_fetcher_->AddConsumer(&consumer_);
@@ -441,7 +495,8 @@ TEST_F(FormFetcherImplTest, TryToMigrateHTTPPasswordsOnHTTPSSites) {
// A new form fetcher is created to be able to set the form digest and
// migration flag.
form_fetcher_ = base::MakeUnique<FormFetcherImpl>(
- form_digest_, &client_, /* should_migrate_http_passwords */ true);
+ form_digest_, &client_, true /* should_migrate_http_passwords */,
+ false /* should_query_suppressed_https_forms */);
EXPECT_CALL(consumer_, ProcessMatches(IsEmpty(), 0u));
form_fetcher_->AddConsumer(&consumer_);
@@ -510,7 +565,8 @@ TEST_F(FormFetcherImplTest, StateIsWaitingDuringMigration) {
// A new form fetcher is created to be able to set the form digest and
// migration flag.
form_fetcher_ = base::MakeUnique<FormFetcherImpl>(
- form_digest_, &client_, /* should_migrate_http_passwords */ true);
+ form_digest_, &client_, true /* should_migrate_http_passwords */,
+ false /* should_query_suppressed_https_forms */);
PasswordForm https_form = CreateNonFederated();
@@ -551,6 +607,149 @@ TEST_F(FormFetcherImplTest, StateIsWaitingDuringMigration) {
EXPECT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
}
+TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_QueriedForHTTPOrigins) {
+ RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
+
+ // The matching PasswordStore results coming in should trigger another
+ // GetLogins request to fetcht the suppressed HTTPS forms.
+ const PasswordStore::FormDigest https_version_of_form_digest(
+ PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
+ const PasswordForm matching_http_form = CreateHTTPNonFederated();
+ base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ {matching_http_form}, https_version_of_form_digest,
+ &https_form_fetcher_ptr));
+
+ EXPECT_FALSE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
+ EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(), IsEmpty());
+
+ const PasswordForm suppressed_https_form1 = CreateNonFederated();
+ const PasswordForm suppressed_https_form2 = CreateFederated();
+ ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
+ {suppressed_https_form1, suppressed_https_form2},
+ https_form_fetcher_ptr));
+
+ EXPECT_TRUE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
+ EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(),
+ UnorderedElementsAre(Pointee(suppressed_https_form1),
+ Pointee(suppressed_https_form2)));
+}
+
+TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_RequeriedOnRefetch) {
+ RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
+
+ const PasswordStore::FormDigest https_version_of_form_digest(
+ PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
+ base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_version_of_form_digest,
+ &https_form_fetcher_ptr));
+ ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_form_fetcher_ptr));
+
+ // Another call to Fetch() should refetch the list of suppressed HTTPS
+ // credentials as well.
+ const PasswordForm suppressed_https_form = CreateNonFederated();
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_version_of_form_digest,
+ &https_form_fetcher_ptr));
+ ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
+ {suppressed_https_form}, https_form_fetcher_ptr));
+
+ EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(),
+ UnorderedElementsAre(Pointee(suppressed_https_form)));
+}
+
+TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_NeverWiped) {
+ RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
+
+ const PasswordStore::FormDigest https_version_of_form_digest(
+ PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
+ const PasswordForm suppressed_https_form = CreateNonFederated();
+ base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_version_of_form_digest,
+ &https_form_fetcher_ptr));
+ ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
+ {suppressed_https_form}, https_form_fetcher_ptr));
+
+ // Ensure that calling Fetch() does not wipe (even temporarily) the previously
+ // fetched list of suppressed HTTPS credentials. Stale is better than nothing.
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_version_of_form_digest,
+ &https_form_fetcher_ptr));
+
+ EXPECT_TRUE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
+ EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(),
+ UnorderedElementsAre(Pointee(suppressed_https_form)));
+}
+
+TEST_F(FormFetcherImplTest,
+ SuppressedHTTPSForms_FormFetcherDestroyedWhileQuerying) {
+ RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
+
+ const PasswordStore::FormDigest https_version_of_form_digest(
+ PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
+ base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_version_of_form_digest,
+ &https_form_fetcher_ptr));
+
+ EXPECT_FALSE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
+
+ // Destroy FormFetcher while SuppressedHTTPSFormFetcher is busy.
+ form_fetcher_.reset();
+}
+
+// Exercise the scenario where querying the suppressed HTTPS logins takes so
+// long that in the meantime there is another call to Fetch(), which completes,
+// and triggers fetching HTTPS suppressed forms yet again. In this case, the
+// first SuppressedHTTPSFormFetcher is destroyed and its query cancelled.
+TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_SimultaneousQueries) {
+ RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
+
+ const PasswordStore::FormDigest https_version_of_form_digest(
+ PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
+ base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr1;
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_version_of_form_digest,
+ &https_form_fetcher_ptr1));
+
+ base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr2;
+ ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
+ std::vector<PasswordForm>(), https_version_of_form_digest,
+ &https_form_fetcher_ptr2));
+
+ EXPECT_FALSE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
+ EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(), IsEmpty());
+ EXPECT_FALSE(https_form_fetcher_ptr1);
+ ASSERT_TRUE(https_form_fetcher_ptr2);
+
+ const PasswordForm suppressed_https_form = CreateNonFederated();
+ ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
+ {suppressed_https_form}, https_form_fetcher_ptr2));
+
+ EXPECT_TRUE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
+ EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(),
+ UnorderedElementsAre(Pointee(suppressed_https_form)));
+}
+
+TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_NotQueriedForHTTPSOrigins) {
+ form_digest_ = PasswordStore::FormDigest(
+ PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
+ RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
+ Fetch();
+
+ EXPECT_CALL(*mock_store_, GetLogins(_, _)).Times(0);
+ EXPECT_CALL(consumer_, ProcessMatches(IsEmpty(), 0u));
+
+ form_fetcher_->OnGetPasswordStoreResults(
+ MakeResults(std::vector<PasswordForm>()));
+
+ EXPECT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
+ EXPECT_FALSE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
+}
+
// Cloning a FormFetcherImpl with empty results should result in an
// instance with empty results.
TEST_F(FormFetcherImplTest, Clone_EmptyResults) {
@@ -564,6 +763,7 @@ TEST_F(FormFetcherImplTest, Clone_EmptyResults) {
EXPECT_EQ(FormFetcher::State::NOT_WAITING, clone->GetState());
EXPECT_THAT(clone->GetInteractionsStats(), IsEmpty());
EXPECT_THAT(clone->GetFederatedMatches(), IsEmpty());
+ EXPECT_THAT(clone->GetSuppressedHTTPSForms(), IsEmpty());
MockConsumer consumer;
EXPECT_CALL(consumer, ProcessMatches(IsEmpty(), 0u));
clone->AddConsumer(&consumer);
@@ -615,6 +815,19 @@ TEST_F(FormFetcherImplTest, Clone_Stats) {
EXPECT_EQ(1u, clone->GetInteractionsStats().size());
}
+// Cloning a FormFetcherImpl with some suppressed HTTPS credentials should
+// result in an instance with the same suppressed credentials.
+TEST_F(FormFetcherImplTest, Clone_SuppressedHTTPSCredentials) {
+ Fetch();
+ form_fetcher_->OnGetPasswordStoreResults(
+ std::vector<std::unique_ptr<PasswordForm>>());
+ form_fetcher_->ProcessSuppressedHTTPSForms(
+ MakeResults({CreateNonFederated()}));
+
+ auto clone = form_fetcher_->Clone();
+ EXPECT_EQ(1u, clone->GetSuppressedHTTPSForms().size());
+}
+
// Check that removing consumers stops them from receiving store updates.
TEST_F(FormFetcherImplTest, RemoveConsumer) {
Fetch();

Powered by Google App Engine
This is Rietveld 408576698