Home | History | Annotate | Download | only in password_manager
      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:
     39   explicit TestingProfileWithPasswordStore(PasswordStore* store)
     40       : store_(store) {}
     41   virtual ~TestingProfileWithPasswordStore() {
     42     store_->Shutdown();
     43   }
     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 
     73 ACTION_P2(InvokeConsumer, handle, forms) {
     74   arg0->OnPasswordStoreRequestDone(handle, forms);
     75 }
     76 
     77 ACTION_P(SaveToScopedPtr, scoped) {
     78   scoped->reset(arg0);
     79 }
     80 
     81 class PasswordManagerTest : public RenderViewHostTestHarness {
     82  public:
     83   PasswordManagerTest()
     84       : ui_thread_(BrowserThread::UI, MessageLoopForUI::current()) {}
     85  protected:
     86 
     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 
     99   virtual void TearDown() {
    100     manager_.reset();
    101     store_ = NULL;
    102   }
    103 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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