| // Copyright 2018 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 "components/password_manager/ios/account_select_fill_data.h" |
| |
| #include "base/stl_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "components/autofill/core/common/password_form_fill_data.h" |
| #include "components/password_manager/ios/test_helpers.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/platform_test.h" |
| |
| using autofill::PasswordFormFillData; |
| using password_manager::AccountSelectFillData; |
| using password_manager::FillData; |
| using password_manager::UsernameAndRealm; |
| using test_helpers::SetPasswordFormFillData; |
| |
| namespace { |
| // Test data. |
| const char* kUrl = "http://example.com/"; |
| const char* kFormNames[] = {"form_name1", "form_name2"}; |
| const char* kUsernameElements[] = {"username1", "username2"}; |
| const char* kUsernames[] = {"user0", "u_s_e_r"}; |
| const char* kPasswordElements[] = {"password1", "password2"}; |
| const char* kPasswords[] = {"password0", "secret"}; |
| const char* kAdditionalUsernames[] = {"u$er2", nullptr}; |
| const char* kAdditionalPasswords[] = {"secret", nullptr}; |
| |
| class AccountSelectFillDataTest : public PlatformTest { |
| public: |
| AccountSelectFillDataTest() { |
| for (size_t i = 0; i < base::size(form_data_); ++i) { |
| SetPasswordFormFillData(kUrl, kUrl, kUsernameElements[i], kUsernames[i], |
| kPasswordElements[i], kPasswords[i], |
| kAdditionalUsernames[i], kAdditionalPasswords[i], |
| false, &form_data_[i]); |
| |
| form_data_[i].name = base::ASCIIToUTF16(kFormNames[i]); |
| } |
| } |
| |
| protected: |
| PasswordFormFillData form_data_[2]; |
| }; |
| |
| TEST_F(AccountSelectFillDataTest, EmptyReset) { |
| AccountSelectFillData account_select_fill_data; |
| EXPECT_TRUE(account_select_fill_data.Empty()); |
| |
| account_select_fill_data.Add(form_data_[0]); |
| EXPECT_FALSE(account_select_fill_data.Empty()); |
| |
| account_select_fill_data.Reset(); |
| EXPECT_TRUE(account_select_fill_data.Empty()); |
| } |
| |
| TEST_F(AccountSelectFillDataTest, IsSuggestionsAvailableOneForm) { |
| AccountSelectFillData account_select_fill_data; |
| account_select_fill_data.Add(form_data_[0]); |
| |
| // Suggestions are avaialable for the correct form and field names. |
| EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[0].name, form_data_[0].username_field.unique_id, false)); |
| // Suggestion should be available to any password field. |
| EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[0].name, base::ASCIIToUTF16("password"), true)); |
| |
| // Suggestions are not avaialable for different form name. |
| EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[0].name + base::ASCIIToUTF16("1"), |
| form_data_[0].username_field.unique_id, false)); |
| EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[0].name + base::ASCIIToUTF16("1"), |
| form_data_[0].password_field.unique_id, true)); |
| |
| // Suggestions are not avaialable for different field name. |
| EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[0].name, |
| form_data_[0].username_field.unique_id + base::ASCIIToUTF16("1"), false)); |
| } |
| |
| TEST_F(AccountSelectFillDataTest, IsSuggestionsAvailableTwoForms) { |
| AccountSelectFillData account_select_fill_data; |
| account_select_fill_data.Add(form_data_[0]); |
| account_select_fill_data.Add(form_data_[1]); |
| |
| // Suggestions are avaialable for the correct form and field names. |
| EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[0].name, form_data_[0].username_field.unique_id, false)); |
| // Suggestions are avaialable for the correct form and field names. |
| EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[1].name, form_data_[1].username_field.unique_id, false)); |
| // Suggestions are not avaialable for different form name. |
| EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( |
| form_data_[0].name + base::ASCIIToUTF16("1"), |
| form_data_[0].username_field.unique_id, false)); |
| } |
| |
| TEST_F(AccountSelectFillDataTest, RetrieveSuggestionsOneForm) { |
| AccountSelectFillData account_select_fill_data; |
| account_select_fill_data.Add(form_data_[0]); |
| |
| for (bool is_password_field : {false, true}) { |
| const base::string16 field_id = |
| is_password_field ? form_data_[0].password_field.unique_id |
| : form_data_[0].username_field.unique_id; |
| std::vector<UsernameAndRealm> suggestions = |
| account_select_fill_data.RetrieveSuggestions( |
| form_data_[0].name, field_id, is_password_field); |
| EXPECT_EQ(2u, suggestions.size()); |
| EXPECT_EQ(base::ASCIIToUTF16(kUsernames[0]), suggestions[0].username); |
| EXPECT_EQ(std::string(), suggestions[0].realm); |
| EXPECT_EQ(base::ASCIIToUTF16(kAdditionalUsernames[0]), |
| suggestions[1].username); |
| EXPECT_EQ(std::string(), suggestions[1].realm); |
| } |
| } |
| |
| TEST_F(AccountSelectFillDataTest, RetrieveSuggestionsTwoForm) { |
| // Test that after adding two PasswordFormFillData, suggestions for both forms |
| // are shown, with credentials from the second PasswordFormFillData. That |
| // emulates the case when credentials in the Password Store were changed |
| // between load the first and the second forms. |
| AccountSelectFillData account_select_fill_data; |
| account_select_fill_data.Add(form_data_[0]); |
| account_select_fill_data.Add(form_data_[1]); |
| |
| std::vector<UsernameAndRealm> suggestions = |
| account_select_fill_data.RetrieveSuggestions( |
| form_data_[0].name, form_data_[0].username_field.unique_id, false); |
| EXPECT_EQ(1u, suggestions.size()); |
| EXPECT_EQ(base::ASCIIToUTF16(kUsernames[1]), suggestions[0].username); |
| |
| suggestions = account_select_fill_data.RetrieveSuggestions( |
| form_data_[1].name, form_data_[1].username_field.unique_id, false); |
| EXPECT_EQ(1u, suggestions.size()); |
| EXPECT_EQ(base::ASCIIToUTF16(kUsernames[1]), suggestions[0].username); |
| } |
| |
| TEST_F(AccountSelectFillDataTest, RetrievePSLMatchedSuggestions) { |
| AccountSelectFillData account_select_fill_data; |
| const char* kRealm = "http://a.example.com/"; |
| std::string kAdditionalRealm = "http://b.example.com/"; |
| |
| // Make logins to be PSL matched by setting non-empy realm. |
| form_data_[0].preferred_realm = kRealm; |
| form_data_[0].additional_logins.begin()->second.realm = kAdditionalRealm; |
| |
| account_select_fill_data.Add(form_data_[0]); |
| std::vector<UsernameAndRealm> suggestions = |
| account_select_fill_data.RetrieveSuggestions( |
| form_data_[0].name, form_data_[0].username_field.unique_id, false); |
| EXPECT_EQ(2u, suggestions.size()); |
| EXPECT_EQ(base::ASCIIToUTF16(kUsernames[0]), suggestions[0].username); |
| EXPECT_EQ(kRealm, suggestions[0].realm); |
| EXPECT_EQ(base::ASCIIToUTF16(kAdditionalUsernames[0]), |
| suggestions[1].username); |
| EXPECT_EQ(kAdditionalRealm, suggestions[1].realm); |
| } |
| |
| TEST_F(AccountSelectFillDataTest, GetFillData) { |
| AccountSelectFillData account_select_fill_data; |
| account_select_fill_data.Add(form_data_[0]); |
| account_select_fill_data.Add(form_data_[1]); |
| |
| for (bool is_password_field : {false, true}) { |
| for (size_t form_i = 0; form_i < base::size(form_data_); ++form_i) { |
| const auto& form_data = form_data_[form_i]; |
| // Suggestions should be shown on any password field on the form. So in |
| // case of clicking on a password field it is taken an id different from |
| // existing field ids. |
| const base::string16 password_field = |
| form_data.password_field.unique_id + |
| (is_password_field ? base::ASCIIToUTF16("1") : base::string16()); |
| const base::string16 clicked_field = |
| is_password_field ? password_field |
| : form_data.username_field.unique_id; |
| |
| // GetFillData() doesn't have form identifier in arguments, it should be |
| // provided in RetrieveSuggestions(). |
| account_select_fill_data.RetrieveSuggestions( |
| form_data.name, clicked_field, is_password_field); |
| std::unique_ptr<FillData> fill_data = |
| account_select_fill_data.GetFillData( |
| base::ASCIIToUTF16(kUsernames[1])); |
| |
| ASSERT_TRUE(fill_data); |
| EXPECT_EQ(form_data.origin, fill_data->origin); |
| EXPECT_EQ(form_data.action, fill_data->action); |
| EXPECT_EQ(base::ASCIIToUTF16(kUsernameElements[form_i]), |
| fill_data->username_element); |
| EXPECT_EQ(base::ASCIIToUTF16(kUsernames[1]), fill_data->username_value); |
| EXPECT_EQ(password_field, fill_data->password_element); |
| EXPECT_EQ(base::ASCIIToUTF16(kPasswords[1]), fill_data->password_value); |
| } |
| } |
| } |
| |
| TEST_F(AccountSelectFillDataTest, GetFillDataOldCredentials) { |
| AccountSelectFillData account_select_fill_data; |
| account_select_fill_data.Add(form_data_[0]); |
| account_select_fill_data.Add(form_data_[1]); |
| |
| // GetFillData() doesn't have form identifier in arguments, it should be |
| // provided in RetrieveSuggestions(). |
| account_select_fill_data.RetrieveSuggestions( |
| form_data_[0].name, form_data_[0].username_field.unique_id, false); |
| |
| // AccountSelectFillData should keep only last credentials. Check that in |
| // request of old credentials nothing is returned. |
| std::unique_ptr<FillData> fill_data = |
| account_select_fill_data.GetFillData(base::ASCIIToUTF16(kUsernames[0])); |
| EXPECT_FALSE(fill_data); |
| } |
| |
| } // namespace |