1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_ORIGIN_UNITTEST_H_
6 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_ORIGIN_UNITTEST_H_
7
8 #include <memory>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/run_loop.h"
13 #include "base/time/time.h"
14 #include "components/password_manager/core/browser/password_manager_test_utils.h"
15 #include "components/password_manager/core/browser/password_store.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "url/gurl.h"
19 #include "url/origin.h"
20
21 using password_manager::PasswordStore;
22 using testing::_;
23 using testing::ElementsAre;
24
matchesOrigin(const url::Origin & origin,const GURL & url)25 bool matchesOrigin(const url::Origin& origin, const GURL& url) {
26 return origin.IsSameOriginWith(url::Origin::Create(url));
27 }
28
29 namespace password_manager {
30
CreateTestPasswordFormDataByOrigin(const char * origin_url)31 PasswordFormData CreateTestPasswordFormDataByOrigin(const char* origin_url) {
32 PasswordFormData data = {PasswordForm::Scheme::kHtml,
33 origin_url,
34 origin_url,
35 "login_element",
36 L"submit_element",
37 L"username_element",
38 L"password_element",
39 L"username_value",
40 L"password_value",
41 true,
42 1};
43 return data;
44 }
45
46 // Collection of origin-related testcases common to all platform-specific
47 // stores.
48 // The template type T represents a test delegate that must implement the
49 // following methods:
50 // // Returns a pointer to a fully initialized store for polymorphic usage.
51 // PasswordStore* store();
52 //
53 // // Finishes all asnychronous processing on the store.
54 // void FinishAsyncProcessing();
55 template <typename T>
56 class PasswordStoreOriginTest : public testing::Test {
57 protected:
58 T delegate_;
59 };
60
61 TYPED_TEST_SUITE_P(PasswordStoreOriginTest);
62
TYPED_TEST_P(PasswordStoreOriginTest,RemoveLoginsByURLAndTimeImpl_AllFittingOriginAndTime)63 TYPED_TEST_P(PasswordStoreOriginTest,
64 RemoveLoginsByURLAndTimeImpl_AllFittingOriginAndTime) {
65 const char origin_url[] = "http://foo.example.com/";
66 std::unique_ptr<PasswordForm> form =
67 FillPasswordFormWithData(CreateTestPasswordFormDataByOrigin(origin_url));
68 this->delegate_.store()->AddLogin(*form);
69 this->delegate_.FinishAsyncProcessing();
70
71 MockPasswordStoreObserver observer;
72 this->delegate_.store()->AddObserver(&observer);
73
74 const url::Origin origin = url::Origin::Create((GURL(origin_url)));
75 base::RepeatingCallback<bool(const GURL&)> filter =
76 base::BindRepeating(&matchesOrigin, origin);
77 base::RunLoop run_loop;
78 EXPECT_CALL(observer, OnLoginsChanged(ElementsAre(PasswordStoreChange(
79 PasswordStoreChange::REMOVE, *form))));
80 this->delegate_.store()->RemoveLoginsByURLAndTime(
81 filter, base::Time(), base::Time::Max(), run_loop.QuitClosure());
82 run_loop.Run();
83
84 this->delegate_.store()->RemoveObserver(&observer);
85 }
86
TYPED_TEST_P(PasswordStoreOriginTest,RemoveLoginsByURLAndTimeImpl_SomeFittingOriginAndTime)87 TYPED_TEST_P(PasswordStoreOriginTest,
88 RemoveLoginsByURLAndTimeImpl_SomeFittingOriginAndTime) {
89 const char fitting_url[] = "http://foo.example.com/";
90 std::unique_ptr<PasswordForm> form =
91 FillPasswordFormWithData(CreateTestPasswordFormDataByOrigin(fitting_url));
92 this->delegate_.store()->AddLogin(*form);
93
94 const char nonfitting_url[] = "http://bar.example.com/";
95 this->delegate_.store()->AddLogin(*FillPasswordFormWithData(
96 CreateTestPasswordFormDataByOrigin(nonfitting_url)));
97
98 this->delegate_.FinishAsyncProcessing();
99
100 MockPasswordStoreObserver observer;
101 this->delegate_.store()->AddObserver(&observer);
102
103 const url::Origin fitting_origin = url::Origin::Create((GURL(fitting_url)));
104 base::RepeatingCallback<bool(const GURL&)> filter =
105 base::BindRepeating(&matchesOrigin, fitting_origin);
106 base::RunLoop run_loop;
107 EXPECT_CALL(observer, OnLoginsChanged(ElementsAre(PasswordStoreChange(
108 PasswordStoreChange::REMOVE, *form))));
109 this->delegate_.store()->RemoveLoginsByURLAndTime(
110 filter, base::Time(), base::Time::Max(), run_loop.QuitClosure());
111 run_loop.Run();
112
113 this->delegate_.store()->RemoveObserver(&observer);
114 }
115
TYPED_TEST_P(PasswordStoreOriginTest,RemoveLoginsByURLAndTimeImpl_NonMatchingOrigin)116 TYPED_TEST_P(PasswordStoreOriginTest,
117 RemoveLoginsByURLAndTimeImpl_NonMatchingOrigin) {
118 const char origin_url[] = "http://foo.example.com/";
119 std::unique_ptr<PasswordForm> form =
120 FillPasswordFormWithData(CreateTestPasswordFormDataByOrigin(origin_url));
121 this->delegate_.store()->AddLogin(*form);
122 this->delegate_.FinishAsyncProcessing();
123
124 MockPasswordStoreObserver observer;
125 this->delegate_.store()->AddObserver(&observer);
126
127 const url::Origin other_origin =
128 url::Origin::Create(GURL("http://bar.example.com/"));
129 base::RepeatingCallback<bool(const GURL&)> filter =
130 base::BindRepeating(&matchesOrigin, other_origin);
131 base::RunLoop run_loop;
132 EXPECT_CALL(observer, OnLoginsChanged(_)).Times(0);
133 this->delegate_.store()->RemoveLoginsByURLAndTime(
134 filter, base::Time(), base::Time::Max(), run_loop.QuitClosure());
135 run_loop.Run();
136
137 this->delegate_.store()->RemoveObserver(&observer);
138 }
139
TYPED_TEST_P(PasswordStoreOriginTest,RemoveLoginsByURLAndTimeImpl_NotWithinTimeInterval)140 TYPED_TEST_P(PasswordStoreOriginTest,
141 RemoveLoginsByURLAndTimeImpl_NotWithinTimeInterval) {
142 const char origin_url[] = "http://foo.example.com/";
143 std::unique_ptr<PasswordForm> form =
144 FillPasswordFormWithData(CreateTestPasswordFormDataByOrigin(origin_url));
145 this->delegate_.store()->AddLogin(*form);
146 this->delegate_.FinishAsyncProcessing();
147
148 MockPasswordStoreObserver observer;
149 this->delegate_.store()->AddObserver(&observer);
150
151 const url::Origin origin = url::Origin::Create((GURL(origin_url)));
152 base::RepeatingCallback<bool(const GURL&)> filter =
153 base::BindRepeating(&matchesOrigin, origin);
154 base::Time time_after_creation_date =
155 form->date_created + base::TimeDelta::FromDays(1);
156 base::RunLoop run_loop;
157 EXPECT_CALL(observer, OnLoginsChanged(_)).Times(0);
158 this->delegate_.store()->RemoveLoginsByURLAndTime(
159 filter, time_after_creation_date, base::Time::Max(),
160 run_loop.QuitClosure());
161 run_loop.Run();
162
163 this->delegate_.store()->RemoveObserver(&observer);
164 }
165
166 REGISTER_TYPED_TEST_SUITE_P(
167 PasswordStoreOriginTest,
168 RemoveLoginsByURLAndTimeImpl_AllFittingOriginAndTime,
169 RemoveLoginsByURLAndTimeImpl_SomeFittingOriginAndTime,
170 RemoveLoginsByURLAndTimeImpl_NonMatchingOrigin,
171 RemoveLoginsByURLAndTimeImpl_NotWithinTimeInterval);
172
173 } // namespace password_manager
174
175 #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_ORIGIN_UNITTEST_H_
176