OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 <vector> | 5 #include <vector> |
6 | 6 |
7 #include "testing/gtest/include/gtest/gtest.h" | 7 #include "testing/gtest/include/gtest/gtest.h" |
8 | 8 |
9 #include "base/ref_counted.h" | 9 #include "base/ref_counted.h" |
10 #include "base/string16.h" | 10 #include "base/string16.h" |
11 #include "base/time.h" | 11 #include "base/time.h" |
12 #include "base/waitable_event.h" | 12 #include "base/waitable_event.h" |
13 #include "chrome/browser/sync/engine/syncapi.h" | 13 #include "chrome/browser/sync/engine/syncapi.h" |
14 #include "chrome/browser/sync/glue/autofill_change_processor.h" | 14 #include "chrome/browser/sync/glue/autofill_change_processor.h" |
15 #include "chrome/browser/sync/glue/autofill_data_type_controller.h" | 15 #include "chrome/browser/sync/glue/autofill_data_type_controller.h" |
16 #include "chrome/browser/sync/glue/autofill_model_associator.h" | 16 #include "chrome/browser/sync/glue/autofill_model_associator.h" |
17 #include "chrome/browser/sync/glue/sync_backend_host.h" | 17 #include "chrome/browser/sync/glue/sync_backend_host.h" |
18 #include "chrome/browser/sync/profile_sync_factory.h" | 18 #include "chrome/browser/sync/profile_sync_factory.h" |
19 #include "chrome/browser/sync/profile_sync_factory_mock.h" | 19 #include "chrome/browser/sync/profile_sync_factory_mock.h" |
20 #include "chrome/browser/sync/profile_sync_service.h" | 20 #include "chrome/browser/sync/profile_sync_service.h" |
21 #include "chrome/browser/sync/profile_sync_test_util.h" | 21 #include "chrome/browser/sync/profile_sync_test_util.h" |
22 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h" | 22 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h" |
| 23 #include "chrome/browser/sync/syncable/directory_manager.h" |
23 #include "chrome/browser/webdata/autofill_entry.h" | 24 #include "chrome/browser/webdata/autofill_entry.h" |
24 #include "chrome/browser/webdata/web_database.h" | 25 #include "chrome/browser/webdata/web_database.h" |
25 #include "chrome/common/notification_service.h" | 26 #include "chrome/common/notification_service.h" |
| 27 #include "chrome/test/sync/engine/test_id_factory.h" |
26 #include "chrome/test/testing_profile.h" | 28 #include "chrome/test/testing_profile.h" |
27 #include "testing/gmock/include/gmock/gmock.h" | 29 #include "testing/gmock/include/gmock/gmock.h" |
28 | 30 |
29 using base::Time; | 31 using base::Time; |
30 using base::WaitableEvent; | 32 using base::WaitableEvent; |
31 using browser_sync::AutofillChangeProcessor; | 33 using browser_sync::AutofillChangeProcessor; |
32 using browser_sync::AutofillDataTypeController; | 34 using browser_sync::AutofillDataTypeController; |
33 using browser_sync::AutofillModelAssociator; | 35 using browser_sync::AutofillModelAssociator; |
34 using browser_sync::SyncBackendHost; | 36 using browser_sync::SyncBackendHost; |
| 37 using browser_sync::TestIdFactory; |
35 using browser_sync::UnrecoverableErrorHandler; | 38 using browser_sync::UnrecoverableErrorHandler; |
36 using sync_api::SyncManager; | 39 using sync_api::SyncManager; |
| 40 using sync_api::UserShare; |
| 41 using syncable::BASE_VERSION; |
| 42 using syncable::CREATE; |
| 43 using syncable::DirectoryManager; |
| 44 using syncable::ID; |
| 45 using syncable::IS_DEL; |
| 46 using syncable::IS_DIR; |
| 47 using syncable::IS_UNAPPLIED_UPDATE; |
| 48 using syncable::IS_UNSYNCED; |
| 49 using syncable::MutableEntry; |
| 50 using syncable::SERVER_IS_DIR; |
| 51 using syncable::SERVER_VERSION; |
| 52 using syncable::SPECIFICS; |
| 53 using syncable::ScopedDirLookup; |
| 54 using syncable::UNIQUE_SERVER_TAG; |
| 55 using syncable::UNITTEST; |
| 56 using syncable::WriteTransaction; |
37 using testing::_; | 57 using testing::_; |
38 using testing::DoAll; | 58 using testing::DoAll; |
39 using testing::DoDefault; | 59 using testing::DoDefault; |
| 60 using testing::Invoke; |
40 using testing::Return; | 61 using testing::Return; |
41 using testing::SetArgumentPointee; | 62 using testing::SetArgumentPointee; |
42 | 63 |
43 class TestingProfileSyncService : public ProfileSyncService { | 64 class TestingProfileSyncService : public ProfileSyncService { |
44 public: | 65 public: |
45 explicit TestingProfileSyncService(ProfileSyncFactory* factory, | 66 explicit TestingProfileSyncService(ProfileSyncFactory* factory, |
46 Profile* profile, | 67 Profile* profile, |
47 bool bootstrap_sync_authentication) | 68 bool bootstrap_sync_authentication) |
48 : ProfileSyncService(factory, profile, bootstrap_sync_authentication) { | 69 : ProfileSyncService(factory, profile, bootstrap_sync_authentication) { |
49 RegisterPreferences(); | 70 RegisterPreferences(); |
(...skipping 12 matching lines...) Expand all Loading... |
62 } | 83 } |
63 | 84 |
64 private: | 85 private: |
65 // When testing under ChromiumOS, this method must not return an empty | 86 // When testing under ChromiumOS, this method must not return an empty |
66 // value value in order for the profile sync service to start. | 87 // value value in order for the profile sync service to start. |
67 virtual std::string GetLsidForAuthBootstraping() { | 88 virtual std::string GetLsidForAuthBootstraping() { |
68 return "foo"; | 89 return "foo"; |
69 } | 90 } |
70 }; | 91 }; |
71 | 92 |
72 class TestAutofillModelAssociator | |
73 : public TestModelAssociator<AutofillModelAssociator> { | |
74 public: | |
75 TestAutofillModelAssociator(ProfileSyncService* service, | |
76 WebDatabase* web_database, | |
77 UnrecoverableErrorHandler* error_handler) | |
78 : TestModelAssociator<AutofillModelAssociator>( | |
79 service, web_database, error_handler) { | |
80 } | |
81 }; | |
82 | |
83 class WebDatabaseMock : public WebDatabase { | 93 class WebDatabaseMock : public WebDatabase { |
84 public: | 94 public: |
85 MOCK_METHOD2(RemoveFormElement, | 95 MOCK_METHOD2(RemoveFormElement, |
86 bool(const string16& name, const string16& value)); | 96 bool(const string16& name, const string16& value)); |
87 MOCK_METHOD1(GetAllAutofillEntries, | 97 MOCK_METHOD1(GetAllAutofillEntries, |
88 bool(std::vector<AutofillEntry>* entries)); | 98 bool(std::vector<AutofillEntry>* entries)); |
89 MOCK_METHOD3(GetAutofillTimestamps, | 99 MOCK_METHOD3(GetAutofillTimestamps, |
90 bool(const string16& name, | 100 bool(const string16& name, |
91 const string16& value, | 101 const string16& value, |
92 std::vector<base::Time>* timestamps)); | 102 std::vector<base::Time>* timestamps)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 }; | 163 }; |
154 | 164 |
155 ACTION(QuitUIMessageLoop) { | 165 ACTION(QuitUIMessageLoop) { |
156 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 166 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
157 MessageLoop::current()->Quit(); | 167 MessageLoop::current()->Quit(); |
158 } | 168 } |
159 | 169 |
160 ACTION_P3(MakeAutofillSyncComponents, service, wd, dtc) { | 170 ACTION_P3(MakeAutofillSyncComponents, service, wd, dtc) { |
161 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 171 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
162 AutofillModelAssociator* model_associator = | 172 AutofillModelAssociator* model_associator = |
163 new TestAutofillModelAssociator(service, wd, dtc); | 173 new AutofillModelAssociator(service, wd, dtc); |
164 AutofillChangeProcessor* change_processor = | 174 AutofillChangeProcessor* change_processor = |
165 new AutofillChangeProcessor(model_associator, wd, service); | 175 new AutofillChangeProcessor(model_associator, wd, service); |
166 return ProfileSyncFactory::SyncComponents(model_associator, change_processor); | 176 return ProfileSyncFactory::SyncComponents(model_associator, change_processor); |
167 } | 177 } |
168 | 178 |
169 class ProfileSyncServiceAutofillTest : public testing::Test { | 179 class ProfileSyncServiceAutofillTest : public testing::Test { |
170 protected: | 180 protected: |
171 ProfileSyncServiceAutofillTest() | 181 ProfileSyncServiceAutofillTest() |
172 : ui_thread_(ChromeThread::UI, &message_loop_), | 182 : ui_thread_(ChromeThread::UI, &message_loop_), |
173 db_thread_(ChromeThread::DB), | 183 db_thread_(ChromeThread::DB), |
(...skipping 30 matching lines...) Expand all Loading... |
204 &web_database_, | 214 &web_database_, |
205 data_type_controller)); | 215 data_type_controller)); |
206 EXPECT_CALL(factory_, CreateDataTypeManager(_)). | 216 EXPECT_CALL(factory_, CreateDataTypeManager(_)). |
207 WillOnce(MakeDataTypeManager()); | 217 WillOnce(MakeDataTypeManager()); |
208 | 218 |
209 EXPECT_CALL(profile_, GetWebDataService(_)). | 219 EXPECT_CALL(profile_, GetWebDataService(_)). |
210 WillOnce(Return(web_data_service_.get())); | 220 WillOnce(Return(web_data_service_.get())); |
211 | 221 |
212 // State changes once for the backend init and once for startup done. | 222 // State changes once for the backend init and once for startup done. |
213 EXPECT_CALL(observer_, OnStateChanged()). | 223 EXPECT_CALL(observer_, OnStateChanged()). |
214 WillOnce(DoDefault()). | 224 WillOnce(Invoke(this, |
| 225 &ProfileSyncServiceAutofillTest::CreateAutofillRoot)). |
215 WillOnce(QuitUIMessageLoop()); | 226 WillOnce(QuitUIMessageLoop()); |
216 service_->RegisterDataTypeController(data_type_controller); | 227 service_->RegisterDataTypeController(data_type_controller); |
217 service_->Initialize(); | 228 service_->Initialize(); |
218 MessageLoop::current()->Run(); | 229 MessageLoop::current()->Run(); |
219 } | 230 } |
220 } | 231 } |
221 | 232 |
| 233 void CreateAutofillRoot() { |
| 234 UserShare* user_share = service_->backend()->GetUserShareHandle(); |
| 235 DirectoryManager* dir_manager = user_share->dir_manager.get(); |
| 236 |
| 237 ScopedDirLookup dir(dir_manager, user_share->authenticated_name); |
| 238 if (!dir.good()) |
| 239 return; |
| 240 |
| 241 WriteTransaction wtrans(dir, UNITTEST, __FILE__, __LINE__); |
| 242 MutableEntry node(&wtrans, |
| 243 CREATE, |
| 244 wtrans.root_id(), |
| 245 browser_sync::kAutofillTag); |
| 246 node.Put(UNIQUE_SERVER_TAG, browser_sync::kAutofillTag); |
| 247 node.Put(IS_DIR, true); |
| 248 node.Put(SERVER_IS_DIR, false); |
| 249 node.Put(IS_UNSYNCED, false); |
| 250 node.Put(IS_UNAPPLIED_UPDATE, false); |
| 251 node.Put(SERVER_VERSION, 20); |
| 252 node.Put(BASE_VERSION, 20); |
| 253 node.Put(IS_DEL, false); |
| 254 node.Put(ID, ids_.MakeServer(browser_sync::kAutofillTag)); |
| 255 sync_pb::EntitySpecifics specifics; |
| 256 specifics.MutableExtension(sync_pb::autofill); |
| 257 node.Put(SPECIFICS, specifics); |
| 258 } |
| 259 |
222 void GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries) { | 260 void GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries) { |
223 sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle()); | 261 sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle()); |
224 int64 autofill_root_id = | |
225 GetFakeServerTaggedNode(&trans, "google_chrome_autofill"); | |
226 if (autofill_root_id == sync_api::kInvalidId) | |
227 return; | |
228 | |
229 sync_api::ReadNode autofill_root(&trans); | 262 sync_api::ReadNode autofill_root(&trans); |
230 if (!autofill_root.InitByIdLookup(autofill_root_id)) | 263 if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag)) |
231 return; | 264 return; |
232 | 265 |
233 int64 child_id = autofill_root.GetFirstChildId(); | 266 int64 child_id = autofill_root.GetFirstChildId(); |
234 while (child_id != sync_api::kInvalidId) { | 267 while (child_id != sync_api::kInvalidId) { |
235 sync_api::ReadNode child_node(&trans); | 268 sync_api::ReadNode child_node(&trans); |
236 if (!child_node.InitByIdLookup(child_id)) | 269 if (!child_node.InitByIdLookup(child_id)) |
237 return; | 270 return; |
238 | 271 |
239 const sync_pb::AutofillSpecifics& autofill( | 272 const sync_pb::AutofillSpecifics& autofill( |
240 child_node.GetAutofillSpecifics()); | 273 child_node.GetAutofillSpecifics()); |
241 AutofillKey key(UTF8ToUTF16(autofill.name()), | 274 AutofillKey key(UTF8ToUTF16(autofill.name()), |
242 UTF8ToUTF16(autofill.value())); | 275 UTF8ToUTF16(autofill.value())); |
243 std::vector<base::Time> timestamps; | 276 std::vector<base::Time> timestamps; |
244 int timestamps_count = autofill.usage_timestamp_size(); | 277 int timestamps_count = autofill.usage_timestamp_size(); |
245 for (int i = 0; i < timestamps_count; ++i) { | 278 for (int i = 0; i < timestamps_count; ++i) { |
246 timestamps.push_back(Time::FromInternalValue( | 279 timestamps.push_back(Time::FromInternalValue( |
247 autofill.usage_timestamp(i))); | 280 autofill.usage_timestamp(i))); |
248 } | 281 } |
249 entries->push_back(AutofillEntry(key, timestamps)); | 282 entries->push_back(AutofillEntry(key, timestamps)); |
250 child_id = child_node.GetSuccessorId(); | 283 child_id = child_node.GetSuccessorId(); |
251 } | 284 } |
252 } | 285 } |
253 | 286 |
254 int64 GetFakeServerTaggedNode(sync_api::ReadTransaction* trans, | |
255 const std::string& tag) { | |
256 std::wstring tag_wide; | |
257 if (!UTF8ToWide(tag.c_str(), tag.length(), &tag_wide)) | |
258 return sync_api::kInvalidId; | |
259 | |
260 sync_api::ReadNode root(trans); | |
261 root.InitByRootLookup(); | |
262 | |
263 int64 last_child_id = sync_api::kInvalidId; | |
264 for (int64 id = root.GetFirstChildId(); id != sync_api::kInvalidId; /***/) { | |
265 sync_api::ReadNode child(trans); | |
266 child.InitByIdLookup(id); | |
267 last_child_id = id; | |
268 if (tag_wide == child.GetTitle()) { | |
269 return id; | |
270 } | |
271 id = child.GetSuccessorId(); | |
272 } | |
273 | |
274 return sync_api::kInvalidId; | |
275 } | |
276 | |
277 void SetIdleChangeProcessorExpectations() { | 287 void SetIdleChangeProcessorExpectations() { |
278 EXPECT_CALL(web_database_, RemoveFormElement(_, _)).Times(0); | 288 EXPECT_CALL(web_database_, RemoveFormElement(_, _)).Times(0); |
279 EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)).Times(0); | 289 EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)).Times(0); |
280 EXPECT_CALL(web_database_, UpdateAutofillEntries(_)).Times(0); | 290 EXPECT_CALL(web_database_, UpdateAutofillEntries(_)).Times(0); |
281 } | 291 } |
282 | 292 |
283 static AutofillEntry MakeAutofillEntry(const char* name, | 293 static AutofillEntry MakeAutofillEntry(const char* name, |
284 const char* value, | 294 const char* value, |
285 time_t timestamp) { | 295 time_t timestamp) { |
286 std::vector<Time> timestamps; | 296 std::vector<Time> timestamps; |
287 timestamps.push_back(Time::FromTimeT(timestamp)); | 297 timestamps.push_back(Time::FromTimeT(timestamp)); |
288 return AutofillEntry( | 298 return AutofillEntry( |
289 AutofillKey(ASCIIToUTF16(name), ASCIIToUTF16(value)), timestamps); | 299 AutofillKey(ASCIIToUTF16(name), ASCIIToUTF16(value)), timestamps); |
290 } | 300 } |
291 | 301 |
292 | |
293 MessageLoopForUI message_loop_; | 302 MessageLoopForUI message_loop_; |
294 ChromeThread ui_thread_; | 303 ChromeThread ui_thread_; |
295 ChromeThread db_thread_; | 304 ChromeThread db_thread_; |
296 WaitableEvent done_event_; | 305 WaitableEvent done_event_; |
297 scoped_refptr<DBThreadNotificationService> notification_service_; | 306 scoped_refptr<DBThreadNotificationService> notification_service_; |
298 | 307 |
299 scoped_ptr<TestingProfileSyncService> service_; | 308 scoped_ptr<TestingProfileSyncService> service_; |
300 ProfileMock profile_; | 309 ProfileMock profile_; |
301 ProfileSyncFactoryMock factory_; | 310 ProfileSyncFactoryMock factory_; |
302 ProfileSyncServiceObserverMock observer_; | 311 ProfileSyncServiceObserverMock observer_; |
303 WebDatabaseMock web_database_; | 312 WebDatabaseMock web_database_; |
304 scoped_refptr<WebDataService> web_data_service_; | 313 scoped_refptr<WebDataService> web_data_service_; |
| 314 |
| 315 TestIdFactory ids_; |
305 }; | 316 }; |
306 | 317 |
307 // TODO(sync): Test unrecoverable error during MA. | 318 // TODO(sync): Test unrecoverable error during MA. |
308 | 319 |
309 TEST_F(ProfileSyncServiceAutofillTest, EmptyNativeEmptySync) { | 320 TEST_F(ProfileSyncServiceAutofillTest, EmptyNativeEmptySync) { |
310 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); | 321 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); |
311 SetIdleChangeProcessorExpectations(); | 322 SetIdleChangeProcessorExpectations(); |
312 StartSyncService(); | 323 StartSyncService(); |
313 std::vector<AutofillEntry> sync_entries; | 324 std::vector<AutofillEntry> sync_entries; |
314 GetAutofillEntriesFromSyncDB(&sync_entries); | 325 GetAutofillEntriesFromSyncDB(&sync_entries); |
(...skipping 21 matching lines...) Expand all Loading... |
336 entries.push_back(MakeAutofillEntry("dup", "", 2)); | 347 entries.push_back(MakeAutofillEntry("dup", "", 2)); |
337 entries.push_back(MakeAutofillEntry("dup", "", 3)); | 348 entries.push_back(MakeAutofillEntry("dup", "", 3)); |
338 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). | 349 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). |
339 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); | 350 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); |
340 SetIdleChangeProcessorExpectations(); | 351 SetIdleChangeProcessorExpectations(); |
341 StartSyncService(); | 352 StartSyncService(); |
342 std::vector<AutofillEntry> sync_entries; | 353 std::vector<AutofillEntry> sync_entries; |
343 GetAutofillEntriesFromSyncDB(&sync_entries); | 354 GetAutofillEntriesFromSyncDB(&sync_entries); |
344 EXPECT_EQ(2U, sync_entries.size()); | 355 EXPECT_EQ(2U, sync_entries.size()); |
345 } | 356 } |
OLD | NEW |