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