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

Unified Diff: chrome/browser/password_manager/password_manager_util_unittest.cc

Issue 2714543006: Clean Obsolete HTTP Data from the Password Store (Closed)
Patch Set: Address Vasilii's comments and fix includes Created 3 years, 9 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: chrome/browser/password_manager/password_manager_util_unittest.cc
diff --git a/chrome/browser/password_manager/password_manager_util_unittest.cc b/chrome/browser/password_manager/password_manager_util_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bfcc9c037990be616b4704225cc77ac08f0ac36f
--- /dev/null
+++ b/chrome/browser/password_manager/password_manager_util_unittest.cc
@@ -0,0 +1,313 @@
+// Copyright 2017 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_manager/password_manager_util.h"
+
+#include <initializer_list>
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/password_manager/core/browser/mock_password_store.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/http/transport_security_state.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using autofill::PasswordForm;
+using password_manager::InteractionsStats;
+using testing::Invoke;
+using testing::Mock;
+using testing::NiceMock;
+using testing::_;
+
+namespace password_manager_util {
+
+namespace {
+
+constexpr char kTestHttpURL[] = "http://example.org/";
+constexpr char kTestHttpsURL[] = "https://example.org/";
+
+PasswordForm CreateTestHTTPForm() {
+ PasswordForm form;
+ form.origin = GURL(kTestHttpURL);
+ form.signon_realm = form.origin.spec();
+ form.action = form.origin;
+ form.username_value = base::ASCIIToUTF16("user");
+ form.password_value = base::ASCIIToUTF16("password");
+ return form;
+}
+
+PasswordForm CreateTestHTTPSForm() {
+ PasswordForm form;
+ form.origin = GURL(kTestHttpsURL);
+ form.signon_realm = form.origin.spec();
+ form.action = form.origin;
+ form.username_value = base::ASCIIToUTF16("user");
+ form.password_value = base::ASCIIToUTF16("password");
+ return form;
+}
+
+InteractionsStats CreateTestHTTPStats() {
+ InteractionsStats stats;
+ stats.origin_domain = GURL(kTestHttpURL);
+ stats.username_value = base::ASCIIToUTF16("user");
+ return stats;
+}
+
+InteractionsStats CreateTestHTTPSStats() {
+ InteractionsStats stats;
+ stats.origin_domain = GURL(kTestHttpsURL);
+ stats.username_value = base::ASCIIToUTF16("user");
+ return stats;
+}
+
+std::vector<std::unique_ptr<PasswordForm>> MakeResults(
+ const std::vector<PasswordForm>& forms) {
+ std::vector<std::unique_ptr<PasswordForm>> results;
+ results.reserve(forms.size());
+ for (const auto& form : forms)
+ results.push_back(base::MakeUnique<PasswordForm>(form));
+ return results;
+}
+
+// Auxiliary class to automatically set and reset the HSTS state for a given
+// host.
+class HSTSStateManager {
+ public:
+ HSTSStateManager(net::TransportSecurityState* state,
+ bool is_hsts,
+ const std::string& host);
+ ~HSTSStateManager();
+
+ private:
+ net::TransportSecurityState* state_;
+ const bool is_hsts_;
+ const std::string host_;
+};
+
+HSTSStateManager::HSTSStateManager(net::TransportSecurityState* state,
+ bool is_hsts,
+ const std::string& host)
+ : state_(state), is_hsts_(is_hsts), host_(host) {
+ if (is_hsts_) {
+ base::Time expiry = base::Time::Max();
+ bool include_subdomains = false;
+ state_->AddHSTS(host_, expiry, include_subdomains);
+ }
+}
+
+HSTSStateManager::~HSTSStateManager() {
+ if (is_hsts_)
+ state_->DeleteDynamicDataForHost(host_);
+}
+
+} // namespace
+
+class PasswordManagerUtilTest : public testing::Test {
+ public:
+ PasswordManagerUtilTest();
+
+ TestingProfile& profile() { return profile_; }
+ password_manager::MockPasswordStore* store() { return store_; }
+ net::TransportSecurityState* GetTransportSecurityState();
+
+ private:
+ content::TestBrowserThreadBundle thread_bundle_;
+ TestingProfile profile_;
+ password_manager::MockPasswordStore* store_;
+};
+
+PasswordManagerUtilTest::PasswordManagerUtilTest() {
+ PasswordStoreFactory::GetInstance()->SetTestingFactory(
+ &profile_, password_manager::BuildPasswordStore<
+ content::BrowserContext,
+ NiceMock<password_manager::MockPasswordStore>>);
+
+ store_ = static_cast<password_manager::MockPasswordStore*>(
+ PasswordStoreFactory::GetForProfile(&profile_,
+ ServiceAccessType::IMPLICIT_ACCESS)
+ .get());
+}
+
+net::TransportSecurityState*
+PasswordManagerUtilTest::GetTransportSecurityState() {
+ return profile()
+ .GetRequestContext()
+ ->GetURLRequestContext()
+ ->transport_security_state();
+}
+
+TEST_F(PasswordManagerUtilTest, TestPostHSTSQueryForHostAndProfile) {
+ const GURL test_origin(kTestHttpsURL);
+ for (bool is_hsts : {false, true}) {
+ SCOPED_TRACE(testing::Message()
+ << std::boolalpha << "is_hsts: " << is_hsts);
+
+ HSTSStateManager manager(GetTransportSecurityState(), is_hsts,
+ test_origin.host());
+ // Post query and ensure callback gets run.
+ bool callback_ran = false;
+ PostHSTSQueryForHostAndProfile(
+ test_origin, &profile(),
+ base::Bind(
+ [](bool* ran, bool expectation, bool result) {
+ *ran = true;
+ EXPECT_EQ(expectation, result);
+ },
+ &callback_ran, is_hsts));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(callback_ran);
+ }
+}
+
+TEST_F(PasswordManagerUtilTest, TestBlacklistDeletion) {
+ for (bool is_http : {false, true}) {
+ for (bool is_hsts : {false, true}) {
+ SCOPED_TRACE(testing::Message()
+ << std::boolalpha << "(is_http, is_hsts): (" << is_http
+ << ", " << is_hsts << ")");
+
+ const bool should_be_deleted = is_http && is_hsts;
+
+ PasswordForm form =
+ is_http ? CreateTestHTTPForm() : CreateTestHTTPSForm();
+ form.blacklisted_by_user = true;
+
+ HSTSStateManager manager(GetTransportSecurityState(), is_hsts,
+ form.origin.host());
+
+ EXPECT_CALL(*store(), FillBlacklistLogins(_))
+ .WillOnce(Invoke(
+ [&form](
+ std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) {
+ *forms = MakeResults({form});
+ return true;
+ }));
+
+ EXPECT_CALL(*store(), RemoveLogin(form)).Times(should_be_deleted);
+
+ // Initiate clean up and make sure all aync tasks are run until
+ // completion.
+ DelayCleanObsoleteHttpDataForProfile(&profile(), 0);
+ base::RunLoop().RunUntilIdle();
+
+ // Verify and clear all expectations as well as the preference.
+ Mock::VerifyAndClearExpectations(store());
+ EXPECT_TRUE(profile().GetPrefs()->GetBoolean(
+ password_manager::prefs::kWasObsoleteHttpDataCleaned));
+ profile().GetPrefs()->SetBoolean(
vasilii 2017/03/24 15:14:30 I'd set the pref in the beginning of the block and
+ password_manager::prefs::kWasObsoleteHttpDataCleaned, false);
+ }
+ }
+}
+
+TEST_F(PasswordManagerUtilTest, TestAutofillableDeletion) {
+ for (bool is_hsts : {false, true}) {
+ for (bool same_host : {false, true}) {
+ for (bool same_user : {false, true}) {
+ for (bool same_pass : {false, true}) {
+ SCOPED_TRACE(testing::Message()
+ << std::boolalpha
+ << "(is_hsts, same_host, same_user, same_pass): ("
+ << is_hsts << ", " << same_host << ", " << same_user
+ << ", " << same_pass);
+
+ const bool should_be_deleted =
+ is_hsts && same_host && same_user && same_pass;
+
+ PasswordForm http_form = CreateTestHTTPForm();
+ PasswordForm https_form = CreateTestHTTPSForm();
+
+ if (!same_host) {
+ GURL::Replacements rep;
+ rep.SetHostStr("a-totally-different-host");
+ http_form.origin = http_form.origin.ReplaceComponents(rep);
+ }
+
+ if (!same_user)
+ http_form.username_value = base::ASCIIToUTF16("different-user");
+
+ if (!same_pass)
+ http_form.password_value = base::ASCIIToUTF16("different-pass");
+
+ HSTSStateManager manager(GetTransportSecurityState(), is_hsts,
+ https_form.origin.host());
+
+ EXPECT_CALL(*store(), FillAutofillableLogins(_))
+ .WillOnce(Invoke(
+ [&http_form, &https_form](
+ std::vector<std::unique_ptr<autofill::PasswordForm>>*
+ forms) {
+ *forms = MakeResults({http_form, https_form});
+ return true;
+ }));
+
+ EXPECT_CALL(*store(), RemoveLogin(http_form))
+ .Times(should_be_deleted);
+
+ // Initiate clean up and make sure all aync tasks are run until
+ // completion.
+ DelayCleanObsoleteHttpDataForProfile(&profile(), 0);
+ base::RunLoop().RunUntilIdle();
+
+ // Verify and clear all expectations as well as the preference.
+ Mock::VerifyAndClearExpectations(store());
+ EXPECT_TRUE(profile().GetPrefs()->GetBoolean(
+ password_manager::prefs::kWasObsoleteHttpDataCleaned));
+ profile().GetPrefs()->SetBoolean(
+ password_manager::prefs::kWasObsoleteHttpDataCleaned, false);
+ }
+ }
+ }
+ }
+}
+
+TEST_F(PasswordManagerUtilTest, TestSiteStatsDeletion) {
+ for (bool is_http : {false, true}) {
+ for (bool is_hsts : {false, true}) {
+ SCOPED_TRACE(testing::Message()
+ << std::boolalpha << "(is_http, is_hsts): (" << is_http
+ << ", " << is_hsts);
+
+ const bool should_be_deleted = is_http && is_hsts;
+
+ InteractionsStats stats =
+ is_http ? CreateTestHTTPStats() : CreateTestHTTPSStats();
+
+ HSTSStateManager manager(GetTransportSecurityState(), is_hsts,
+ stats.origin_domain.host());
+
+ EXPECT_CALL(*store(), GetAllSiteStatsImpl()).WillOnce(Invoke([&stats]() {
+ return std::vector<InteractionsStats>({stats});
+ }));
+ EXPECT_CALL(*store(), RemoveSiteStatsImpl(stats.origin_domain))
+ .Times(should_be_deleted);
+
+ // Initiate clean up and make sure all aync tasks are run until
+ // completion.
+ DelayCleanObsoleteHttpDataForProfile(&profile(), 0);
+ base::RunLoop().RunUntilIdle();
+
+ // Verify and clear all expectations as well as the preference.
+ Mock::VerifyAndClearExpectations(store());
+ EXPECT_TRUE(profile().GetPrefs()->GetBoolean(
+ password_manager::prefs::kWasObsoleteHttpDataCleaned));
+ profile().GetPrefs()->SetBoolean(
+ password_manager::prefs::kWasObsoleteHttpDataCleaned, false);
+ }
+ }
+}
+
+} // namespace password_manager_util
« no previous file with comments | « chrome/browser/password_manager/password_manager_util.cc ('k') | chrome/browser/password_manager/password_store_factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698