| 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 |