• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 #include <vector>
6 
7 #include "base/message_loop.h"
8 #include "base/string_util.h"
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/password_manager/password_manager.h"
11 #include "chrome/browser/password_manager/password_manager_delegate.h"
12 #include "chrome/browser/password_manager/password_store.h"
13 #include "chrome/common/url_constants.h"
14 #include "chrome/test/testing_profile.h"
15 #include "content/browser/browser_thread.h"
16 #include "content/browser/renderer_host/test_render_view_host.h"
17 #include "content/browser/tab_contents/test_tab_contents.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 
21 using webkit_glue::PasswordForm;
22 using testing::_;
23 using testing::DoAll;
24 using ::testing::Exactly;
25 using ::testing::WithArg;
26 using ::testing::Return;
27 
28 class MockPasswordManagerDelegate : public PasswordManagerDelegate {
29  public:
30   MOCK_METHOD1(FillPasswordForm, void(
31      const webkit_glue::PasswordFormFillData&));
32   MOCK_METHOD1(AddSavePasswordInfoBar, void(PasswordFormManager*));
33   MOCK_METHOD0(GetProfileForPasswordManager, Profile*());
34   MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool());
35 };
36 
37 class TestingProfileWithPasswordStore : public TestingProfile {
38  public:
TestingProfileWithPasswordStore(PasswordStore * store)39   explicit TestingProfileWithPasswordStore(PasswordStore* store)
40       : store_(store) {}
~TestingProfileWithPasswordStore()41   virtual ~TestingProfileWithPasswordStore() {
42     store_->Shutdown();
43   }
GetPasswordStore(ServiceAccessType access)44   virtual PasswordStore* GetPasswordStore(ServiceAccessType access) {
45     return store_;
46   }
47  private:
48   scoped_refptr<PasswordStore> store_;
49 };
50 
51 class MockPasswordStore : public PasswordStore {
52  public:
53   MOCK_METHOD1(RemoveLogin, void(const PasswordForm&));
54   MOCK_METHOD2(GetLogins, int(const PasswordForm&, PasswordStoreConsumer*));
55   MOCK_METHOD1(AddLogin, void(const PasswordForm&));
56   MOCK_METHOD1(UpdateLogin, void(const PasswordForm&));
57   MOCK_METHOD0(ReportMetrics, void());
58   MOCK_METHOD0(ReportMetricsImpl, void());
59   MOCK_METHOD1(AddLoginImpl, void(const PasswordForm&));
60   MOCK_METHOD1(UpdateLoginImpl, void(const PasswordForm&));
61   MOCK_METHOD1(RemoveLoginImpl, void(const PasswordForm&));
62   MOCK_METHOD2(RemoveLoginsCreatedBetweenImpl, void(const base::Time&,
63                const base::Time&));
64   MOCK_METHOD2(GetLoginsImpl, void(GetLoginsRequest*, const PasswordForm&));
65   MOCK_METHOD1(GetAutofillableLoginsImpl, void(GetLoginsRequest*));
66   MOCK_METHOD1(GetBlacklistLoginsImpl, void(GetLoginsRequest*));
67   MOCK_METHOD1(FillAutofillableLogins,
68       bool(std::vector<webkit_glue::PasswordForm*>*));
69   MOCK_METHOD1(FillBlacklistLogins,
70       bool(std::vector<webkit_glue::PasswordForm*>*));
71 };
72 
ACTION_P2(InvokeConsumer,handle,forms)73 ACTION_P2(InvokeConsumer, handle, forms) {
74   arg0->OnPasswordStoreRequestDone(handle, forms);
75 }
76 
ACTION_P(SaveToScopedPtr,scoped)77 ACTION_P(SaveToScopedPtr, scoped) {
78   scoped->reset(arg0);
79 }
80 
81 class PasswordManagerTest : public RenderViewHostTestHarness {
82  public:
PasswordManagerTest()83   PasswordManagerTest()
84       : ui_thread_(BrowserThread::UI, MessageLoopForUI::current()) {}
85  protected:
86 
SetUp()87   virtual void SetUp() {
88     RenderViewHostTestHarness::SetUp();
89 
90     store_ = new MockPasswordStore();
91     profile_.reset(new TestingProfileWithPasswordStore(store_));
92     EXPECT_CALL(delegate_, GetProfileForPasswordManager())
93         .WillRepeatedly(Return(profile_.get()));
94     manager_.reset(new PasswordManager(contents(), &delegate_));
95     EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors())
96         .WillRepeatedly(Return(false));
97   }
98 
TearDown()99   virtual void TearDown() {
100     manager_.reset();
101     store_ = NULL;
102   }
103 
MakeSimpleForm()104   PasswordForm MakeSimpleForm() {
105     PasswordForm form;
106     form.origin = GURL("http://www.google.com/a/LoginAuth");
107     form.action = GURL("http://www.google.com/a/Login");
108     form.username_element = ASCIIToUTF16("Email");
109     form.password_element = ASCIIToUTF16("Passwd");
110     form.username_value = ASCIIToUTF16("google");
111     form.password_value = ASCIIToUTF16("password");
112     form.submit_element = ASCIIToUTF16("signIn");
113     form.signon_realm = "http://www.google.com";
114     return form;
115   }
116 
manager()117   PasswordManager* manager() { return manager_.get(); }
118 
119   // We create a UI thread to satisfy PasswordStore.
120   BrowserThread ui_thread_;
121 
122   scoped_ptr<Profile> profile_;
123   scoped_refptr<MockPasswordStore> store_;
124   MockPasswordManagerDelegate delegate_;  // Owned by manager_.
125   scoped_ptr<PasswordManager> manager_;
126 };
127 
128 MATCHER_P(FormMatches, form, "") {
129   return form.signon_realm == arg.signon_realm &&
130          form.origin == arg.origin &&
131          form.action == arg.action &&
132          form.username_element == arg.username_element &&
133          form.password_element == arg.password_element &&
134          form.submit_element == arg.submit_element;
135 }
136 
TEST_F(PasswordManagerTest,FormSubmitEmptyStore)137 TEST_F(PasswordManagerTest, FormSubmitEmptyStore) {
138   // Test that observing a newly submitted form shows the save password bar.
139   std::vector<PasswordForm*> result;  // Empty password store.
140   EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
141   EXPECT_CALL(*store_, GetLogins(_,_))
142       .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
143   std::vector<PasswordForm> observed;
144   PasswordForm form(MakeSimpleForm());
145   observed.push_back(form);
146   manager()->OnPasswordFormsFound(observed);  // The initial load.
147   manager()->OnPasswordFormsVisible(observed);  // The initial layout.
148 
149   // And the form submit contract is to call ProvisionallySavePassword.
150   manager()->ProvisionallySavePassword(form);
151 
152   scoped_ptr<PasswordFormManager> form_to_save;
153   EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
154       .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
155 
156   // Now the password manager waits for the navigation to complete.
157   manager()->DidStopLoading();
158 
159   ASSERT_FALSE(NULL == form_to_save.get());
160   EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
161 
162   // Simulate saving the form, as if the info bar was accepted.
163   form_to_save->Save();
164 }
165 
TEST_F(PasswordManagerTest,FormSubmitNoGoodMatch)166 TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) {
167   // Same as above, except with an existing form for the same signon realm,
168   // but different origin.  Detailed cases like this are covered by
169   // PasswordFormManagerTest.
170   std::vector<PasswordForm*> result;
171   PasswordForm* existing_different = new PasswordForm(MakeSimpleForm());
172   existing_different->username_value = ASCIIToUTF16("google2");
173   result.push_back(existing_different);
174   EXPECT_CALL(delegate_, FillPasswordForm(_));
175   EXPECT_CALL(*store_, GetLogins(_,_))
176       .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
177 
178   std::vector<PasswordForm> observed;
179   PasswordForm form(MakeSimpleForm());
180   observed.push_back(form);
181   manager()->OnPasswordFormsFound(observed);  // The initial load.
182   manager()->OnPasswordFormsVisible(observed);  // The initial layout.
183   manager()->ProvisionallySavePassword(form);
184 
185   // We still expect an add, since we didn't have a good match.
186   scoped_ptr<PasswordFormManager> form_to_save;
187   EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
188       .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
189 
190   manager()->DidStopLoading();
191 
192   EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
193   // Simulate saving the form.
194   form_to_save->Save();
195 }
196 
TEST_F(PasswordManagerTest,FormSeenThenLeftPage)197 TEST_F(PasswordManagerTest, FormSeenThenLeftPage) {
198   std::vector<PasswordForm*> result;  // Empty password store.
199   EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
200   EXPECT_CALL(*store_, GetLogins(_,_))
201     .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
202   std::vector<PasswordForm> observed;
203   PasswordForm form(MakeSimpleForm());
204   observed.push_back(form);
205   manager()->OnPasswordFormsFound(observed);  // The initial load.
206   manager()->OnPasswordFormsVisible(observed);  // The initial layout.
207 
208   manager()->DidNavigate();
209 
210   // No expected calls.
211   manager()->DidStopLoading();
212 }
213 
TEST_F(PasswordManagerTest,FormSubmitFailedLogin)214 TEST_F(PasswordManagerTest, FormSubmitFailedLogin) {
215   std::vector<PasswordForm*> result;  // Empty password store.
216   EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
217   EXPECT_CALL(*store_, GetLogins(_,_))
218     .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
219   std::vector<PasswordForm> observed;
220   PasswordForm form(MakeSimpleForm());
221   observed.push_back(form);
222   manager()->OnPasswordFormsFound(observed);  // The initial load.
223   manager()->OnPasswordFormsVisible(observed);  // The initial layout.
224 
225   manager()->ProvisionallySavePassword(form);
226 
227   // The form reappears, and is visible in the layout:
228   manager()->OnPasswordFormsFound(observed);
229   manager()->OnPasswordFormsVisible(observed);
230 
231   // No expected calls to the PasswordStore...
232   manager()->DidStopLoading();
233 }
234 
TEST_F(PasswordManagerTest,FormSubmitInvisibleLogin)235 TEST_F(PasswordManagerTest, FormSubmitInvisibleLogin) {
236   // Tests fix of issue 28911: if the login form reappears on the subsequent
237   // page, but is invisible, it shouldn't count as a failed login.
238   std::vector<PasswordForm*> result;  // Empty password store.
239   EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
240   EXPECT_CALL(*store_, GetLogins(_,_))
241       .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
242   std::vector<PasswordForm> observed;
243   PasswordForm form(MakeSimpleForm());
244   observed.push_back(form);
245   manager()->OnPasswordFormsFound(observed);  // The initial load.
246   manager()->OnPasswordFormsVisible(observed);  // The initial layout.
247 
248   manager()->ProvisionallySavePassword(form);
249 
250   // The form reappears, but is not visible in the layout:
251   manager()->OnPasswordFormsFound(observed);
252   // No call to PasswordFormsVisible.
253 
254   // Expect info bar to appear:
255   scoped_ptr<PasswordFormManager> form_to_save;
256   EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_))
257       .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
258 
259   manager()->DidStopLoading();
260 
261   ASSERT_FALSE(NULL == form_to_save.get());
262   EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
263   // Simulate saving the form.
264   form_to_save->Save();
265 }
266 
TEST_F(PasswordManagerTest,InitiallyInvisibleForm)267 TEST_F(PasswordManagerTest, InitiallyInvisibleForm) {
268   // Make sure an invisible login form still gets autofilled.
269   std::vector<PasswordForm*> result;
270   PasswordForm* existing = new PasswordForm(MakeSimpleForm());
271   result.push_back(existing);
272   EXPECT_CALL(delegate_, FillPasswordForm(_));
273   EXPECT_CALL(*store_, GetLogins(_,_))
274       .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0)));
275   std::vector<PasswordForm> observed;
276   PasswordForm form(MakeSimpleForm());
277   observed.push_back(form);
278   manager()->OnPasswordFormsFound(observed);  // The initial load.
279   // PasswordFormsVisible is not called.
280 
281   manager()->DidStopLoading();
282 }
283