Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Side by Side Diff: components/password_manager/core/browser/password_syncable_service_unittest.cc

Issue 2981293003: Save Android Autofill credentials in the right format. (Closed)
Patch Set: test comment Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/password_manager/core/browser/password_syncable_service.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/password_manager/core/browser/password_syncable_service.h" 5 #include "components/password_manager/core/browser/password_syncable_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <memory> 8 #include <memory>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h" 16 #include "base/memory/ref_counted.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "base/test/scoped_task_environment.h"
19 #include "base/test/simple_test_clock.h"
19 #include "components/password_manager/core/browser/mock_password_store.h" 20 #include "components/password_manager/core/browser/mock_password_store.h"
21 #include "components/password_manager/core/browser/password_manager_test_utils.h "
20 #include "components/sync/model/sync_change_processor.h" 22 #include "components/sync/model/sync_change_processor.h"
21 #include "components/sync/model/sync_error.h" 23 #include "components/sync/model/sync_error.h"
22 #include "components/sync/model/sync_error_factory_mock.h" 24 #include "components/sync/model/sync_error_factory_mock.h"
23 #include "testing/gmock/include/gmock/gmock.h" 25 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
25 27
26 using syncer::SyncChange; 28 using syncer::SyncChange;
27 using syncer::SyncData; 29 using syncer::SyncData;
28 using syncer::SyncDataList; 30 using syncer::SyncDataList;
29 using syncer::SyncError; 31 using syncer::SyncError;
(...skipping 14 matching lines...) Expand all
44 // Defined in the implementation file corresponding to this test. 46 // Defined in the implementation file corresponding to this test.
45 syncer::SyncData SyncDataFromPassword(const autofill::PasswordForm& password); 47 syncer::SyncData SyncDataFromPassword(const autofill::PasswordForm& password);
46 autofill::PasswordForm PasswordFromSpecifics( 48 autofill::PasswordForm PasswordFromSpecifics(
47 const sync_pb::PasswordSpecificsData& password); 49 const sync_pb::PasswordSpecificsData& password);
48 std::string MakePasswordSyncTag(const sync_pb::PasswordSpecificsData& password); 50 std::string MakePasswordSyncTag(const sync_pb::PasswordSpecificsData& password);
49 std::string MakePasswordSyncTag(const autofill::PasswordForm& password); 51 std::string MakePasswordSyncTag(const autofill::PasswordForm& password);
50 52
51 namespace { 53 namespace {
52 54
53 // PasswordForm values for tests. 55 // PasswordForm values for tests.
54 const autofill::PasswordForm::Type kArbitraryType = 56 constexpr autofill::PasswordForm::Type kArbitraryType =
55 autofill::PasswordForm::TYPE_GENERATED; 57 autofill::PasswordForm::TYPE_GENERATED;
56 const char kIconUrl[] = "https://fb.com/Icon"; 58 constexpr char kAndroidAutofillRealm[] = "android://hash@com.magisto";
57 const char kDisplayName[] = "Agent Smith"; 59 constexpr char kAndroidCorrectRealm[] = "android://hash@com.magisto/";
58 const char kFederationUrl[] = "https://fb.com/"; 60 constexpr char kIconUrl[] = "https://fb.com/Icon";
59 const char kPassword[] = "abcdef"; 61 constexpr char kDisplayName[] = "Agent Smith";
60 const char kSignonRealm[] = "abc"; 62 constexpr char kFederationUrl[] = "https://fb.com/";
61 const char kSignonRealm2[] = "def"; 63 constexpr char kPassword[] = "abcdef";
62 const char kSignonRealm3[] = "xyz"; 64 constexpr char kSignonRealm[] = "abc";
63 const int kTimesUsed = 5; 65 constexpr char kSignonRealm2[] = "def";
64 const char kUsername[] = "godzilla"; 66 constexpr char kSignonRealm3[] = "xyz";
67 constexpr int kTimesUsed = 5;
68 constexpr char kUsername[] = "godzilla";
65 69
66 typedef std::vector<SyncChange> SyncChangeList; 70 typedef std::vector<SyncChange> SyncChangeList;
67 71
68 const sync_pb::PasswordSpecificsData& GetPasswordSpecifics( 72 const sync_pb::PasswordSpecificsData& GetPasswordSpecifics(
69 const syncer::SyncData& sync_data) { 73 const syncer::SyncData& sync_data) {
70 return sync_data.GetSpecifics().password().client_only_encrypted_data(); 74 return sync_data.GetSpecifics().password().client_only_encrypted_data();
71 } 75 }
72 76
73 MATCHER(HasDateSynced, "") { 77 MATCHER_P(HasDateSynced, time, "") {
74 return !arg.date_synced.is_null() && !arg.date_synced.is_max(); 78 return arg.date_synced == time;
75 } 79 }
76 80
77 MATCHER_P(PasswordIs, form, "") { 81 MATCHER_P(PasswordIs, form, "") {
78 sync_pb::PasswordSpecificsData actual_password = 82 sync_pb::PasswordSpecificsData actual_password =
79 GetPasswordSpecifics(SyncDataFromPassword(arg)); 83 GetPasswordSpecifics(SyncDataFromPassword(arg));
80 sync_pb::PasswordSpecificsData expected_password = 84 sync_pb::PasswordSpecificsData expected_password =
81 GetPasswordSpecifics(SyncDataFromPassword(form)); 85 GetPasswordSpecifics(SyncDataFromPassword(form));
82 if (expected_password.scheme() == actual_password.scheme() && 86 if (expected_password.scheme() == actual_password.scheme() &&
83 expected_password.signon_realm() == actual_password.signon_realm() && 87 expected_password.signon_realm() == actual_password.signon_realm() &&
84 expected_password.origin() == actual_password.origin() && 88 expected_password.origin() == actual_password.origin() &&
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 Matches(PasswordIs(password))(form))); 121 Matches(PasswordIs(password))(form)));
118 } 122 }
119 123
120 // The argument is std::vector<autofill::PasswordForm*>*. The caller is 124 // The argument is std::vector<autofill::PasswordForm*>*. The caller is
121 // responsible for the lifetime of all the password forms. 125 // responsible for the lifetime of all the password forms.
122 ACTION_P(AppendForm, form) { 126 ACTION_P(AppendForm, form) {
123 arg0->push_back(base::MakeUnique<autofill::PasswordForm>(form)); 127 arg0->push_back(base::MakeUnique<autofill::PasswordForm>(form));
124 return true; 128 return true;
125 } 129 }
126 130
131 // The argument is std::vector<autofill::PasswordForm*>*. The caller is
132 // responsible for the lifetime of all the password forms.
133 ACTION_P(AppendForms, forms) {
134 for (const autofill::PasswordForm& form : forms)
135 arg0->push_back(base::MakeUnique<autofill::PasswordForm>(form));
136 return true;
137 }
138
127 // Creates a sync data consisting of password specifics. The sign on realm is 139 // Creates a sync data consisting of password specifics. The sign on realm is
128 // set to |signon_realm|. 140 // set to |signon_realm|.
129 SyncData CreateSyncData(const std::string& signon_realm) { 141 SyncData CreateSyncData(const std::string& signon_realm) {
130 sync_pb::EntitySpecifics password_data; 142 sync_pb::EntitySpecifics password_data;
131 sync_pb::PasswordSpecificsData* password_specifics = 143 sync_pb::PasswordSpecificsData* password_specifics =
132 password_data.mutable_password()->mutable_client_only_encrypted_data(); 144 password_data.mutable_password()->mutable_client_only_encrypted_data();
133 password_specifics->set_signon_realm(signon_realm); 145 password_specifics->set_signon_realm(signon_realm);
134 password_specifics->set_type(autofill::PasswordForm::TYPE_GENERATED); 146 password_specifics->set_type(autofill::PasswordForm::TYPE_GENERATED);
135 password_specifics->set_times_used(3); 147 password_specifics->set_times_used(3);
136 password_specifics->set_display_name("Mr. X"); 148 password_specifics->set_display_name("Mr. X");
137 password_specifics->set_avatar_url("https://accounts.google.com/Icon"); 149 password_specifics->set_avatar_url("https://accounts.google.com/Icon");
138 password_specifics->set_federation_url("https://google.com"); 150 password_specifics->set_federation_url("https://google.com");
139 password_specifics->set_username_value("kingkong"); 151 password_specifics->set_username_value("kingkong");
140 password_specifics->set_password_value("sicrit"); 152 password_specifics->set_password_value("sicrit");
141 153
142 std::string tag = MakePasswordSyncTag(*password_specifics); 154 std::string tag = MakePasswordSyncTag(*password_specifics);
143 return syncer::SyncData::CreateLocalData(tag, tag, password_data); 155 return syncer::SyncData::CreateLocalData(tag, tag, password_data);
144 } 156 }
145 157
146 SyncChange CreateSyncChange(const autofill::PasswordForm& password, 158 SyncChange CreateSyncChange(const autofill::PasswordForm& password,
147 SyncChange::SyncChangeType type) { 159 SyncChange::SyncChangeType type) {
148 SyncData data = SyncDataFromPassword(password); 160 SyncData data = SyncDataFromPassword(password);
149 return SyncChange(FROM_HERE, type, data); 161 return SyncChange(FROM_HERE, type, data);
150 } 162 }
151 163
152 // A testable implementation of the |PasswordSyncableService| that mocks
153 // out all interaction with the password database.
154 class MockPasswordSyncableService : public PasswordSyncableService {
155 public:
156 explicit MockPasswordSyncableService(PasswordStoreSync* password_store)
157 : PasswordSyncableService(password_store) {}
158
159 MOCK_METHOD1(StartSyncFlare, void(syncer::ModelType));
160
161 private:
162 DISALLOW_COPY_AND_ASSIGN(MockPasswordSyncableService);
163 };
164
165 // Mock implementation of SyncChangeProcessor. 164 // Mock implementation of SyncChangeProcessor.
166 class MockSyncChangeProcessor : public syncer::SyncChangeProcessor { 165 class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
167 public: 166 public:
168 MockSyncChangeProcessor() {} 167 MockSyncChangeProcessor() {}
169 168
170 MOCK_METHOD2(ProcessSyncChanges, 169 MOCK_METHOD2(ProcessSyncChanges,
171 SyncError(const tracked_objects::Location&, 170 SyncError(const tracked_objects::Location&,
172 const SyncChangeList& list)); 171 const SyncChangeList& list));
173 SyncDataList GetAllSyncData(syncer::ModelType type) const override { 172 SyncDataList GetAllSyncData(syncer::ModelType type) const override {
174 NOTREACHED(); 173 NOTREACHED();
175 return SyncDataList(); 174 return SyncDataList();
176 } 175 }
177 176
178 private: 177 private:
179 DISALLOW_COPY_AND_ASSIGN(MockSyncChangeProcessor); 178 DISALLOW_COPY_AND_ASSIGN(MockSyncChangeProcessor);
180 }; 179 };
181 180
182 // Convenience wrapper around a PasswordSyncableService and PasswordStore 181 // Convenience wrapper around a PasswordSyncableService and PasswordStore
183 // pair. 182 // pair.
184 class PasswordSyncableServiceWrapper { 183 class PasswordSyncableServiceWrapper {
185 public: 184 public:
186 PasswordSyncableServiceWrapper() { 185 PasswordSyncableServiceWrapper() {
187 password_store_ = new testing::StrictMock<MockPasswordStore>; 186 password_store_ = new testing::StrictMock<MockPasswordStore>;
188 service_.reset( 187 service_.reset(
189 new MockPasswordSyncableService(password_store_->GetSyncInterface())); 188 new PasswordSyncableService(password_store_->GetSyncInterface()));
190 ON_CALL(*password_store_, AddLoginImpl(HasDateSynced())) 189 auto clock = base::MakeUnique<base::SimpleTestClock>();
190 clock->SetNow(time());
191 service_->set_clock(std::move(clock));
192 ON_CALL(*password_store_, AddLoginImpl(HasDateSynced(time())))
191 .WillByDefault(Return(PasswordStoreChangeList())); 193 .WillByDefault(Return(PasswordStoreChangeList()));
192 ON_CALL(*password_store_, RemoveLoginImpl(_)) 194 ON_CALL(*password_store_, RemoveLoginImpl(_))
193 .WillByDefault(Return(PasswordStoreChangeList())); 195 .WillByDefault(Return(PasswordStoreChangeList()));
194 ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced())) 196 ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced(time())))
195 .WillByDefault(Return(PasswordStoreChangeList())); 197 .WillByDefault(Return(PasswordStoreChangeList()));
196 EXPECT_CALL(*password_store(), NotifyLoginsChanged(_)).Times(AnyNumber()); 198 EXPECT_CALL(*password_store(), NotifyLoginsChanged(_)).Times(AnyNumber());
197 } 199 }
198 200
199 ~PasswordSyncableServiceWrapper() { password_store_->ShutdownOnUIThread(); } 201 ~PasswordSyncableServiceWrapper() { password_store_->ShutdownOnUIThread(); }
200 202
201 MockPasswordStore* password_store() { return password_store_.get(); } 203 MockPasswordStore* password_store() { return password_store_.get(); }
202 204
203 MockPasswordSyncableService* service() { return service_.get(); } 205 PasswordSyncableService* service() { return service_.get(); }
206
207 static base::Time time() { return base::Time::FromInternalValue(100000); }
204 208
205 // Returnes the scoped_ptr to |service_| thus NULLing out it. 209 // Returnes the scoped_ptr to |service_| thus NULLing out it.
206 std::unique_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() { 210 std::unique_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() {
207 return std::move(service_); 211 return std::move(service_);
208 } 212 }
209 213
210 private: 214 private:
211 scoped_refptr<MockPasswordStore> password_store_; 215 scoped_refptr<MockPasswordStore> password_store_;
212 std::unique_ptr<MockPasswordSyncableService> service_; 216 std::unique_ptr<PasswordSyncableService> service_;
213 217
214 DISALLOW_COPY_AND_ASSIGN(PasswordSyncableServiceWrapper); 218 DISALLOW_COPY_AND_ASSIGN(PasswordSyncableServiceWrapper);
215 }; 219 };
216 220
217 class PasswordSyncableServiceTest : public testing::Test { 221 class PasswordSyncableServiceTest : public testing::Test {
218 public: 222 public:
219 PasswordSyncableServiceTest() 223 PasswordSyncableServiceTest()
220 : processor_(new testing::StrictMock<MockSyncChangeProcessor>) { 224 : processor_(new testing::StrictMock<MockSyncChangeProcessor>) {
221 ON_CALL(*processor_, ProcessSyncChanges(_, _)) 225 ON_CALL(*processor_, ProcessSyncChanges(_, _))
222 .WillByDefault(Return(SyncError())); 226 .WillByDefault(Return(SyncError()));
223 } 227 }
224 MockPasswordStore* password_store() { return wrapper_.password_store(); } 228 MockPasswordStore* password_store() { return wrapper_.password_store(); }
225 MockPasswordSyncableService* service() { return wrapper_.service(); } 229 PasswordSyncableService* service() { return wrapper_.service(); }
230
231 MOCK_METHOD1(StartSyncFlare, void(syncer::ModelType));
226 232
227 protected: 233 protected:
228 base::MessageLoop message_loop_;
229 std::unique_ptr<MockSyncChangeProcessor> processor_; 234 std::unique_ptr<MockSyncChangeProcessor> processor_;
230 235
231 private: 236 private:
237 base::test::ScopedTaskEnvironment scoped_task_environment_;
232 PasswordSyncableServiceWrapper wrapper_; 238 PasswordSyncableServiceWrapper wrapper_;
233 }; 239 };
234 240
235 // Both sync and password db have data that are not present in the other. 241 // Both sync and password db have data that are not present in the other.
236 TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) { 242 TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) {
237 autofill::PasswordForm form; 243 autofill::PasswordForm form;
238 form.signon_realm = kSignonRealm; 244 form.signon_realm = kSignonRealm;
239 form.username_value = base::ASCIIToUTF16(kUsername); 245 form.username_value = base::ASCIIToUTF16(kUsername);
240 form.password_value = base::ASCIIToUTF16(kPassword); 246 form.password_value = base::ASCIIToUTF16(kPassword);
241 247
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 form.signon_realm = kSignonRealm; 487 form.signon_realm = kSignonRealm;
482 form.username_value = base::ASCIIToUTF16(kUsername); 488 form.username_value = base::ASCIIToUTF16(kUsername);
483 form.password_value = base::ASCIIToUTF16(kPassword); 489 form.password_value = base::ASCIIToUTF16(kPassword);
484 PasswordStoreChangeList list; 490 PasswordStoreChangeList list;
485 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form)); 491 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
486 492
487 // No flare and no SyncChangeProcessor, the call shouldn't crash. 493 // No flare and no SyncChangeProcessor, the call shouldn't crash.
488 service()->ActOnPasswordStoreChanges(list); 494 service()->ActOnPasswordStoreChanges(list);
489 495
490 // Set the flare. It should be called as there is no SyncChangeProcessor. 496 // Set the flare. It should be called as there is no SyncChangeProcessor.
491 service()->InjectStartSyncFlare( 497 service()->InjectStartSyncFlare(base::Bind(
492 base::Bind(&MockPasswordSyncableService::StartSyncFlare, 498 &PasswordSyncableServiceTest::StartSyncFlare, base::Unretained(this)));
493 base::Unretained(service()))); 499 EXPECT_CALL(*this, StartSyncFlare(syncer::PASSWORDS));
494 EXPECT_CALL(*service(), StartSyncFlare(syncer::PASSWORDS));
495 service()->ActOnPasswordStoreChanges(list); 500 service()->ActOnPasswordStoreChanges(list);
496 } 501 }
497 502
498 // Start syncing with an error. Subsequent password store updates shouldn't be 503 // Start syncing with an error. Subsequent password store updates shouldn't be
499 // propagated to Sync. 504 // propagated to Sync.
500 TEST_F(PasswordSyncableServiceTest, FailedReadFromPasswordStore) { 505 TEST_F(PasswordSyncableServiceTest, FailedReadFromPasswordStore) {
501 std::unique_ptr<syncer::SyncErrorFactoryMock> error_factory( 506 std::unique_ptr<syncer::SyncErrorFactoryMock> error_factory(
502 new syncer::SyncErrorFactoryMock); 507 new syncer::SyncErrorFactoryMock);
503 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, 508 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
504 "Failed to get passwords from store.", 509 "Failed to get passwords from store.",
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 EXPECT_TRUE(specifics.has_times_used()); 671 EXPECT_TRUE(specifics.has_times_used());
667 EXPECT_EQ(11, specifics.times_used()); 672 EXPECT_EQ(11, specifics.times_used());
668 EXPECT_TRUE(specifics.has_display_name()); 673 EXPECT_TRUE(specifics.has_display_name());
669 EXPECT_EQ("Great Peter", specifics.display_name()); 674 EXPECT_EQ("Great Peter", specifics.display_name());
670 EXPECT_TRUE(specifics.has_avatar_url()); 675 EXPECT_TRUE(specifics.has_avatar_url());
671 EXPECT_EQ("https://google.com/icon", specifics.avatar_url()); 676 EXPECT_EQ("https://google.com/icon", specifics.avatar_url());
672 EXPECT_TRUE(specifics.has_federation_url()); 677 EXPECT_TRUE(specifics.has_federation_url());
673 EXPECT_EQ("https://google.com", specifics.federation_url()); 678 EXPECT_EQ("https://google.com", specifics.federation_url());
674 } 679 }
675 680
681 // Tests for Android Autofill credentials. Those are saved in the wrong format
682 // without trailing '/'. Nevertheless, password store should always contain the
683 // correct values.
684 class PasswordSyncableServiceAndroidAutofillTest : public testing::Test {
685 public:
686 PasswordSyncableServiceAndroidAutofillTest() = default;
687
688 static PasswordFormData android_incorrect(double creation_time) {
689 PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML,
690 kAndroidAutofillRealm,
691 kAndroidAutofillRealm,
692 "",
693 L"",
694 L"",
695 L"",
696 L"username_value_1",
697 L"11111",
698 true,
699 creation_time};
700 return data;
701 }
702
703 static PasswordFormData android_correct(double creation_time) {
704 PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML,
705 kAndroidCorrectRealm,
706 kAndroidCorrectRealm,
707 "",
708 L"",
709 L"",
710 L"",
711 L"username_value_1",
712 L"22222",
713 true,
714 creation_time};
715 return data;
716 }
717
718 static PasswordFormData android_incorrect2(double creation_time) {
719 PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML,
720 kAndroidAutofillRealm,
721 kAndroidAutofillRealm,
722 "",
723 L"",
724 L"",
725 L"",
726 L"username_value_1",
727 L"33333",
728 false,
729 creation_time};
730 return data;
731 }
732
733 static PasswordFormData android_correct2(double creation_time) {
734 PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML,
735 kAndroidCorrectRealm,
736 kAndroidCorrectRealm,
737 "",
738 L"",
739 L"",
740 L"",
741 L"username_value_1",
742 L"444444",
743 false,
744 creation_time};
745 return data;
746 }
747
748 static autofill::PasswordForm FormWithCorrectTag(PasswordFormData data) {
749 autofill::PasswordForm form = *CreatePasswordFormFromDataForTesting(data);
750 form.signon_realm = kAndroidCorrectRealm;
751 form.origin = GURL(kAndroidCorrectRealm);
752 form.date_synced = PasswordSyncableServiceWrapper::time();
753 return form;
754 }
755
756 static autofill::PasswordForm FormWithAndroidAutofillTag(
757 PasswordFormData data) {
758 autofill::PasswordForm form = *CreatePasswordFormFromDataForTesting(data);
759 form.signon_realm = kAndroidAutofillRealm;
760 form.origin = GURL(kAndroidAutofillRealm);
761 form.date_synced = PasswordSyncableServiceWrapper::time();
762 return form;
763 }
764
765 // Transforms |val| into |count| numbers from 1 to |count| inclusive.
766 static std::vector<unsigned> ExtractTimestamps(unsigned val, unsigned count) {
767 std::vector<unsigned> result;
768 for (unsigned i = 0; i < count; ++i) {
769 result.push_back(val % count + 1);
770 val /= count;
771 }
772 return result;
773 }
774
775 static testing::Message FormDataMessage(const std::string& prefix,
776 const PasswordFormData* data) {
777 testing::Message message;
778 message << prefix;
779 if (data)
780 message << *CreatePasswordFormFromDataForTesting(*data);
781 else
782 message << "NULL";
783 return message;
784 }
785
786 protected:
787 base::test::ScopedTaskEnvironment scoped_task_environment_;
788 };
789
790 TEST_F(PasswordSyncableServiceAndroidAutofillTest, FourWayMerge) {
791 for (unsigned val = 0; val < 4 * 4 * 4 * 4; ++val) {
792 // Generate 4 creation timestamps for all the entries.
793 std::vector<unsigned> dates = ExtractTimestamps(val, 4);
794 ASSERT_EQ(4u, dates.size());
795 const unsigned latest = *std::max_element(dates.begin(), dates.end());
796 // Sync correct, Sync Android autofill, local correct, local incorrect.
797 const PasswordFormData data[4] = {
798 android_correct(dates[0]), android_incorrect(dates[1]),
799 android_correct2(dates[2]), android_incorrect2(dates[3])};
800 const PasswordFormData* latest_data =
801 std::find_if(data, data + 4, [latest](const PasswordFormData& data) {
802 return data.creation_time == latest;
803 });
804 ASSERT_TRUE(latest_data);
805 std::vector<autofill::PasswordForm> expected_sync_updates;
806 if (latest_data != &data[0])
807 expected_sync_updates.push_back(FormWithCorrectTag(*latest_data));
808 if (latest_data != &data[1])
809 expected_sync_updates.push_back(FormWithAndroidAutofillTag(*latest_data));
810 autofill::PasswordForm local_correct =
811 *CreatePasswordFormFromDataForTesting(data[2]);
812 autofill::PasswordForm local_incorrect =
813 *CreatePasswordFormFromDataForTesting(data[3]);
814 syncer::SyncData sync_correct =
815 SyncDataFromPassword(*CreatePasswordFormFromDataForTesting(data[0]));
816 syncer::SyncData sync_incorrect =
817 SyncDataFromPassword(*CreatePasswordFormFromDataForTesting(data[1]));
818
819 SCOPED_TRACE(*CreatePasswordFormFromDataForTesting(data[0]));
820 SCOPED_TRACE(*CreatePasswordFormFromDataForTesting(data[1]));
821 SCOPED_TRACE(*CreatePasswordFormFromDataForTesting(data[2]));
822 SCOPED_TRACE(*CreatePasswordFormFromDataForTesting(data[3]));
823
824 for (bool correct_sync_first : {true, false}) {
825 auto wrapper = base::MakeUnique<PasswordSyncableServiceWrapper>();
826 auto processor =
827 base::MakeUnique<testing::StrictMock<MockSyncChangeProcessor>>();
828
829 std::vector<autofill::PasswordForm> stored_forms = {local_correct,
830 local_incorrect};
831 EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_))
832 .WillOnce(AppendForms(stored_forms));
833 EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_))
834 .WillOnce(Return(true));
835 if (latest_data != &data[2]) {
836 EXPECT_CALL(*wrapper->password_store(),
837 UpdateLoginImpl(FormWithCorrectTag(*latest_data)));
838 }
839 if (latest_data != &data[3]) {
840 EXPECT_CALL(*wrapper->password_store(),
841 UpdateLoginImpl(FormWithAndroidAutofillTag(*latest_data)));
842 }
843
844 if (expected_sync_updates.size() == 1) {
845 EXPECT_CALL(*processor,
846 ProcessSyncChanges(_, ElementsAre(SyncChangeIs(
847 SyncChange::ACTION_UPDATE,
848 expected_sync_updates[0]))));
849 } else {
850 EXPECT_CALL(
851 *processor,
852 ProcessSyncChanges(_, UnorderedElementsAre(
853 SyncChangeIs(SyncChange::ACTION_UPDATE,
854 expected_sync_updates[0]),
855 SyncChangeIs(SyncChange::ACTION_UPDATE,
856 expected_sync_updates[1]))));
857 }
858
859 SyncDataList sync_list = {sync_correct, sync_incorrect};
860 if (!correct_sync_first)
861 std::swap(sync_list[0], sync_list[1]);
862 wrapper->service()->MergeDataAndStartSyncing(
863 syncer::PASSWORDS, sync_list, std::move(processor),
864 std::unique_ptr<syncer::SyncErrorFactory>());
865 wrapper.reset();
866 // Wait til PasswordStore is destroy end therefore all the expectations on
867 // it are checked.
868 scoped_task_environment_.RunUntilIdle();
869 }
870 }
871 }
872
873 TEST_F(PasswordSyncableServiceAndroidAutofillTest, ThreeWayMerge) {
874 for (int j = 0; j < 4; ++j) {
875 // Whether the entry exists: Sync correct, Sync Android autofill,
876 // local correct, local incorrect.
877 bool entry_present[4] = {true, true, true, true};
878 entry_present[j] = false;
879 for (unsigned val = 0; val < 3 * 3 * 3; ++val) {
880 // Generate 3 creation timestamps for all the entries.
881 std::vector<unsigned> dates = ExtractTimestamps(val, 3);
882 ASSERT_EQ(3u, dates.size());
883 const unsigned latest = *std::max_element(dates.begin(), dates.end());
884
885 // Sync correct, Sync Android autofill, local correct, local incorrect.
886 std::vector<std::unique_ptr<PasswordFormData>> data;
887 int date_index = 0;
888 data.push_back(entry_present[0]
889 ? base::MakeUnique<PasswordFormData>(
890 android_correct(dates[date_index++]))
891 : nullptr);
892 data.push_back(entry_present[1]
893 ? base::MakeUnique<PasswordFormData>(
894 android_incorrect(dates[date_index++]))
895 : nullptr);
896 data.push_back(entry_present[2]
897 ? base::MakeUnique<PasswordFormData>(
898 android_correct2(dates[date_index++]))
899 : nullptr);
900 data.push_back(entry_present[3]
901 ? base::MakeUnique<PasswordFormData>(
902 android_incorrect2(dates[date_index++]))
903 : nullptr);
904
905 SCOPED_TRACE(val);
906 SCOPED_TRACE(j);
907 SCOPED_TRACE(FormDataMessage("data[0]=", data[0].get()));
908 SCOPED_TRACE(FormDataMessage("data[1]=", data[1].get()));
909 SCOPED_TRACE(FormDataMessage("data[2]=", data[2].get()));
910 SCOPED_TRACE(FormDataMessage("data[3]=", data[3].get()));
911
912 const PasswordFormData* latest_data =
913 std::find_if(data.begin(), data.end(),
914 [latest](const std::unique_ptr<PasswordFormData>& data) {
915 return data && data->creation_time == latest;
916 })
917 ->get();
918 ASSERT_TRUE(latest_data);
919 std::vector<std::pair<SyncChange::SyncChangeType, autofill::PasswordForm>>
920 expected_sync_updates;
921 for (int i = 0; i < 2; ++i) {
922 if (latest_data != data[i].get()) {
923 expected_sync_updates.push_back(std::make_pair(
924 data[i] ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD,
925 i == 0 ? FormWithCorrectTag(*latest_data)
926 : FormWithAndroidAutofillTag(*latest_data)));
927 }
928 }
929
930 std::vector<autofill::PasswordForm> stored_forms;
931 for (int i = 2; i < 4; ++i) {
932 if (data[i])
933 stored_forms.push_back(
934 *CreatePasswordFormFromDataForTesting(*data[i]));
935 }
936
937 SyncDataList sync_list;
938 for (int i = 0; i < 2; ++i) {
939 if (data[i]) {
940 sync_list.push_back(SyncDataFromPassword(
941 *CreatePasswordFormFromDataForTesting(*data[i])));
942 }
943 }
944
945 for (bool swap_sync_list : {false, true}) {
946 auto wrapper = base::MakeUnique<PasswordSyncableServiceWrapper>();
947 auto processor =
948 base::MakeUnique<testing::StrictMock<MockSyncChangeProcessor>>();
949
950 EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_))
951 .WillOnce(AppendForms(stored_forms));
952 EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_))
953 .WillOnce(Return(true));
954 for (int i = 2; i < 4; ++i) {
955 if (latest_data != data[i].get()) {
956 autofill::PasswordForm latest_form =
957 i == 2 ? FormWithCorrectTag(*latest_data)
958 : FormWithAndroidAutofillTag(*latest_data);
959 if (data[i]) {
960 EXPECT_CALL(*wrapper->password_store(),
961 UpdateLoginImpl(latest_form));
962 } else {
963 EXPECT_CALL(*wrapper->password_store(),
964 AddLoginImpl(latest_form));
965 }
966 }
967 }
968
969 if (expected_sync_updates.size() == 0) {
970 EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty()));
971 } else if (expected_sync_updates.size() == 1) {
972 EXPECT_CALL(
973 *processor,
974 ProcessSyncChanges(_, ElementsAre(SyncChangeIs(
975 expected_sync_updates[0].first,
976 expected_sync_updates[0].second))));
977 } else if (expected_sync_updates.size() == 2) {
978 EXPECT_CALL(
979 *processor,
980 ProcessSyncChanges(
981 _, UnorderedElementsAre(
982 SyncChangeIs(expected_sync_updates[0].first,
983 expected_sync_updates[0].second),
984 SyncChangeIs(expected_sync_updates[1].first,
985 expected_sync_updates[1].second))));
986 }
987
988 if (swap_sync_list && sync_list.size() == 2)
989 std::swap(sync_list[0], sync_list[1]);
990 wrapper->service()->MergeDataAndStartSyncing(
991 syncer::PASSWORDS, sync_list, std::move(processor),
992 std::unique_ptr<syncer::SyncErrorFactory>());
993 wrapper.reset();
994 // Wait til PasswordStore is destroy end therefore all the expectations
995 // on it are checked.
996 scoped_task_environment_.RunUntilIdle();
997 }
998 }
999 }
1000 }
1001
1002 TEST_F(PasswordSyncableServiceAndroidAutofillTest, TwoWayServerAndLocalMerge) {
1003 for (unsigned i = 0; i < 2 * 2; ++i) {
1004 // Generate 4 different combinations for local/server entries.
1005 std::vector<unsigned> combination = ExtractTimestamps(i, 2);
1006 ASSERT_EQ(2u, combination.size());
1007 const bool sync_data_correct = !!combination[0];
1008 const bool local_data_correct = !!combination[1];
1009
1010 for (unsigned val = 0; val < 2 * 2; ++val) {
1011 std::vector<unsigned> dates = ExtractTimestamps(i, 2);
1012 ASSERT_EQ(2u, dates.size());
1013
1014 const PasswordFormData sync_data = sync_data_correct
1015 ? android_correct(dates[0])
1016 : android_incorrect(dates[0]);
1017 const PasswordFormData local_data = local_data_correct
1018 ? android_correct2(dates[1])
1019 : android_incorrect2(dates[1]);
1020
1021 const PasswordFormData* latest_data =
1022 dates[1] > dates[0] ? &local_data : &sync_data;
1023
1024 auto wrapper = base::MakeUnique<PasswordSyncableServiceWrapper>();
1025 auto processor =
1026 base::MakeUnique<testing::StrictMock<MockSyncChangeProcessor>>();
1027
1028 EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_))
1029 .WillOnce(
1030 AppendForm(*CreatePasswordFormFromDataForTesting(local_data)));
1031 EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_))
1032 .WillOnce(Return(true));
1033 if (!local_data_correct || latest_data == &sync_data) {
1034 if (local_data_correct) {
1035 EXPECT_CALL(*wrapper->password_store(),
1036 UpdateLoginImpl(FormWithCorrectTag(*latest_data)));
1037 } else {
1038 EXPECT_CALL(*wrapper->password_store(),
1039 AddLoginImpl(FormWithCorrectTag(*latest_data)));
1040 }
1041 }
1042 if (!local_data_correct && latest_data == &sync_data) {
1043 EXPECT_CALL(*wrapper->password_store(),
1044 UpdateLoginImpl(FormWithAndroidAutofillTag(*latest_data)));
1045 } else if (local_data_correct && !sync_data_correct) {
1046 EXPECT_CALL(*wrapper->password_store(),
1047 AddLoginImpl(FormWithAndroidAutofillTag(*latest_data)));
1048 }
1049
1050 std::vector<std::pair<SyncChange::SyncChangeType, autofill::PasswordForm>>
1051 expected_sync_updates;
1052 // Deal with the correct sync entry and incorrect one.
1053 if (sync_data_correct) {
1054 if (latest_data != &sync_data) {
1055 expected_sync_updates.push_back(std::make_pair(
1056 SyncChange::ACTION_UPDATE, FormWithCorrectTag(*latest_data)));
1057 }
1058 if (!local_data_correct) {
1059 expected_sync_updates.push_back(
1060 std::make_pair(SyncChange::ACTION_ADD,
1061 FormWithAndroidAutofillTag(*latest_data)));
1062 }
1063 } else {
1064 expected_sync_updates.push_back(std::make_pair(
1065 SyncChange::ACTION_ADD, FormWithCorrectTag(*latest_data)));
1066 if (latest_data != &sync_data) {
1067 expected_sync_updates.push_back(
1068 std::make_pair(SyncChange::ACTION_UPDATE,
1069 FormWithAndroidAutofillTag(*latest_data)));
1070 }
1071 }
1072
1073 // Set expectation on |processor|.
1074 if (expected_sync_updates.size() == 0) {
1075 EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty()));
1076 } else if (expected_sync_updates.size() == 1) {
1077 EXPECT_CALL(
1078 *processor,
1079 ProcessSyncChanges(
1080 _, ElementsAre(SyncChangeIs(expected_sync_updates[0].first,
1081 expected_sync_updates[0].second))));
1082 } else if (expected_sync_updates.size() == 2) {
1083 EXPECT_CALL(*processor,
1084 ProcessSyncChanges(
1085 _, UnorderedElementsAre(
1086 SyncChangeIs(expected_sync_updates[0].first,
1087 expected_sync_updates[0].second),
1088 SyncChangeIs(expected_sync_updates[1].first,
1089 expected_sync_updates[1].second))));
1090 }
1091
1092 SyncDataList sync_list = {SyncDataFromPassword(
1093 *CreatePasswordFormFromDataForTesting(sync_data))};
1094 wrapper->service()->MergeDataAndStartSyncing(
1095 syncer::PASSWORDS, sync_list, std::move(processor),
1096 std::unique_ptr<syncer::SyncErrorFactory>());
1097 wrapper.reset();
1098 // Wait til PasswordStore is destroy end therefore all the expectations on
1099 // it are checked.
1100 scoped_task_environment_.RunUntilIdle();
1101 }
1102 }
1103 }
1104
1105 TEST_F(PasswordSyncableServiceAndroidAutofillTest, OneEntryOnly) {
1106 for (int i = 0; i < 3; ++i) {
1107 // The case when only local incorrect entry exists is excluded. It's very
1108 // exotic because a local incorrect entry can come only from the server.
1109 // In such a case a copy will be uploaded to the server and next
1110 // MergeDataAndStartSyncing will do a proper migration.
1111 SCOPED_TRACE(i);
1112 // Whether the entry exists: Sync correct, Sync Android autofill,
1113 // local correct, local incorrect.
1114 const bool entry_is_correct = i == 0 || i == 2;
1115 const bool entry_is_local = i >= 2;
1116 PasswordFormData data =
1117 entry_is_correct ? android_correct(100) : android_incorrect(100);
1118
1119 auto wrapper = base::MakeUnique<PasswordSyncableServiceWrapper>();
1120 auto processor =
1121 base::MakeUnique<testing::StrictMock<MockSyncChangeProcessor>>();
1122
1123 if (entry_is_local) {
1124 EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_))
1125 .WillOnce(AppendForm(*CreatePasswordFormFromDataForTesting(data)));
1126 } else {
1127 EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_))
1128 .WillOnce(Return(true));
1129 }
1130 EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_))
1131 .WillOnce(Return(true));
1132 if (!entry_is_local && !entry_is_correct) {
1133 EXPECT_CALL(*wrapper->password_store(),
1134 AddLoginImpl(FormWithAndroidAutofillTag(data)));
1135 }
1136 if (!entry_is_local) {
1137 EXPECT_CALL(*wrapper->password_store(),
1138 AddLoginImpl(FormWithCorrectTag(data)));
1139 }
1140
1141 if (entry_is_correct && !entry_is_local) {
1142 EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty()));
1143 } else {
1144 EXPECT_CALL(*processor,
1145 ProcessSyncChanges(
1146 _, ElementsAre(SyncChangeIs(SyncChange::ACTION_ADD,
1147 FormWithCorrectTag(data)))));
1148 }
1149
1150 SyncDataList sync_list;
1151 if (!entry_is_local) {
1152 sync_list.push_back(
1153 SyncDataFromPassword(*CreatePasswordFormFromDataForTesting(data)));
1154 }
1155 wrapper->service()->MergeDataAndStartSyncing(
1156 syncer::PASSWORDS, sync_list, std::move(processor),
1157 std::unique_ptr<syncer::SyncErrorFactory>());
1158 wrapper.reset();
1159 // Wait til PasswordStore is destroy end therefore all the expectations on
1160 // it are checked.
1161 scoped_task_environment_.RunUntilIdle();
1162 }
1163 }
1164
1165 TEST_F(PasswordSyncableServiceAndroidAutofillTest, FourEqualEntries) {
1166 // Sync correct, Sync Android autofill, local correct, local incorrect with
1167 // the same content. Nothing should happen.
1168 const PasswordFormData data = android_correct(100);
1169 autofill::PasswordForm local_correct = FormWithCorrectTag(data);
1170 autofill::PasswordForm local_incorrect = FormWithAndroidAutofillTag(data);
1171 syncer::SyncData sync_correct = SyncDataFromPassword(local_correct);
1172 syncer::SyncData sync_incorrect = SyncDataFromPassword(local_incorrect);
1173
1174 for (bool correct_sync_first : {true, false}) {
1175 auto wrapper = base::MakeUnique<PasswordSyncableServiceWrapper>();
1176 auto processor =
1177 base::MakeUnique<testing::StrictMock<MockSyncChangeProcessor>>();
1178
1179 std::vector<autofill::PasswordForm> stored_forms = {local_correct,
1180 local_incorrect};
1181 EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_))
1182 .WillOnce(AppendForms(stored_forms));
1183 EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_))
1184 .WillOnce(Return(true));
1185 EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty()));
1186
1187 SyncDataList sync_list = {sync_correct, sync_incorrect};
1188 if (!correct_sync_first)
1189 std::swap(sync_list[0], sync_list[1]);
1190 wrapper->service()->MergeDataAndStartSyncing(
1191 syncer::PASSWORDS, sync_list, std::move(processor),
1192 std::unique_ptr<syncer::SyncErrorFactory>());
1193 wrapper.reset();
1194 // Wait til PasswordStore is destroy end therefore all the expectations on
1195 // it are checked.
1196 scoped_task_environment_.RunUntilIdle();
1197 }
1198 }
1199
1200 TEST_F(PasswordSyncableServiceAndroidAutofillTest, AndroidCorrectEqualEntries) {
1201 // Sync correct, local correct with the same content. Nothing should happen.
1202 const PasswordFormData data = android_correct(100);
1203 autofill::PasswordForm local_correct = FormWithCorrectTag(data);
1204 syncer::SyncData sync_correct = SyncDataFromPassword(local_correct);
1205
1206 auto wrapper = base::MakeUnique<PasswordSyncableServiceWrapper>();
1207 auto processor =
1208 base::MakeUnique<testing::StrictMock<MockSyncChangeProcessor>>();
1209
1210 EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_))
1211 .WillOnce(AppendForm(local_correct));
1212 EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_))
1213 .WillOnce(Return(true));
1214 EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty()));
1215
1216 wrapper->service()->MergeDataAndStartSyncing(
1217 syncer::PASSWORDS, {sync_correct}, std::move(processor),
1218 std::unique_ptr<syncer::SyncErrorFactory>());
1219 wrapper.reset();
1220 // Wait til PasswordStore is destroy end therefore all the expectations on
1221 // it are checked.
1222 scoped_task_environment_.RunUntilIdle();
1223 }
1224
676 } // namespace 1225 } // namespace
677 1226
678 } // namespace password_manager 1227 } // namespace password_manager
OLDNEW
« no previous file with comments | « components/password_manager/core/browser/password_syncable_service.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698