| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 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 <stddef.h> | |
| 6 #include <stdint.h> | |
| 7 | |
| 8 #include <set> | |
| 9 #include <string> | |
| 10 #include <utility> | |
| 11 #include <vector> | |
| 12 | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | |
| 14 | |
| 15 #include "base/bind.h" | |
| 16 #include "base/bind_helpers.h" | |
| 17 #include "base/callback.h" | |
| 18 #include "base/location.h" | |
| 19 #include "base/macros.h" | |
| 20 #include "base/memory/ref_counted.h" | |
| 21 #include "base/memory/scoped_ptr.h" | |
| 22 #include "base/run_loop.h" | |
| 23 #include "base/strings/string16.h" | |
| 24 #include "base/strings/utf_string_conversions.h" | |
| 25 #include "base/synchronization/waitable_event.h" | |
| 26 #include "base/thread_task_runner_handle.h" | |
| 27 #include "base/threading/thread.h" | |
| 28 #include "base/time/time.h" | |
| 29 #include "chrome/browser/sync/abstract_profile_sync_service_test.h" | |
| 30 #include "chrome/browser/sync/test_profile_sync_service.h" | |
| 31 #include "components/autofill/core/browser/autofill_test_utils.h" | |
| 32 #include "components/autofill/core/browser/country_names.h" | |
| 33 #include "components/autofill/core/browser/personal_data_manager.h" | |
| 34 #include "components/autofill/core/browser/webdata/autocomplete_syncable_service
.h" | |
| 35 #include "components/autofill/core/browser/webdata/autofill_change.h" | |
| 36 #include "components/autofill/core/browser/webdata/autofill_data_type_controller
.h" | |
| 37 #include "components/autofill/core/browser/webdata/autofill_entry.h" | |
| 38 #include "components/autofill/core/browser/webdata/autofill_profile_data_type_co
ntroller.h" | |
| 39 #include "components/autofill/core/browser/webdata/autofill_profile_syncable_ser
vice.h" | |
| 40 #include "components/autofill/core/browser/webdata/autofill_table.h" | |
| 41 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" | |
| 42 #include "components/autofill/core/common/autofill_pref_names.h" | |
| 43 #include "components/browser_sync/browser/profile_sync_service.h" | |
| 44 #include "components/sync_driver/data_type_controller.h" | |
| 45 #include "components/sync_driver/data_type_manager_impl.h" | |
| 46 #include "components/sync_driver/sync_api_component_factory_mock.h" | |
| 47 #include "components/syncable_prefs/pref_service_syncable.h" | |
| 48 #include "components/webdata/common/web_database.h" | |
| 49 #include "components/webdata_services/web_data_service_test_util.h" | |
| 50 #include "sync/internal_api/public/base/model_type.h" | |
| 51 #include "sync/internal_api/public/data_type_debug_info_listener.h" | |
| 52 #include "sync/internal_api/public/read_node.h" | |
| 53 #include "sync/internal_api/public/read_transaction.h" | |
| 54 #include "sync/internal_api/public/write_node.h" | |
| 55 #include "sync/internal_api/public/write_transaction.h" | |
| 56 #include "sync/protocol/autofill_specifics.pb.h" | |
| 57 #include "sync/syncable/mutable_entry.h" | |
| 58 #include "sync/syncable/syncable_write_transaction.h" | |
| 59 #include "testing/gmock/include/gmock/gmock.h" | |
| 60 | |
| 61 using autofill::AutocompleteSyncableService; | |
| 62 using autofill::AutofillChange; | |
| 63 using autofill::AutofillChangeList; | |
| 64 using autofill::AutofillEntry; | |
| 65 using autofill::AutofillKey; | |
| 66 using autofill::AutofillProfile; | |
| 67 using autofill::AutofillProfileChange; | |
| 68 using autofill::AutofillProfileSyncableService; | |
| 69 using autofill::AutofillTable; | |
| 70 using autofill::AutofillWebDataService; | |
| 71 using autofill::PersonalDataManager; | |
| 72 using base::Time; | |
| 73 using base::TimeDelta; | |
| 74 using base::WaitableEvent; | |
| 75 using browser_sync::AutofillDataTypeController; | |
| 76 using browser_sync::AutofillProfileDataTypeController; | |
| 77 using syncer::AUTOFILL; | |
| 78 using syncer::AUTOFILL_PROFILE; | |
| 79 using syncer::BaseNode; | |
| 80 using syncer::syncable::CREATE; | |
| 81 using syncer::syncable::GET_TYPE_ROOT; | |
| 82 using syncer::syncable::MutableEntry; | |
| 83 using syncer::syncable::UNITTEST; | |
| 84 using syncer::syncable::WriterTag; | |
| 85 using syncer::syncable::WriteTransaction; | |
| 86 using testing::_; | |
| 87 using testing::DoAll; | |
| 88 using testing::ElementsAre; | |
| 89 using testing::Not; | |
| 90 using testing::SetArgumentPointee; | |
| 91 using testing::Return; | |
| 92 | |
| 93 namespace { | |
| 94 | |
| 95 void RegisterAutofillPrefs(user_prefs::PrefRegistrySyncable* registry) { | |
| 96 registry->RegisterBooleanPref(autofill::prefs::kAutofillEnabled, true); | |
| 97 registry->RegisterBooleanPref(autofill::prefs::kAutofillWalletImportEnabled, | |
| 98 true); | |
| 99 } | |
| 100 | |
| 101 void RunAndSignal(const base::Closure& cb, WaitableEvent* event) { | |
| 102 cb.Run(); | |
| 103 event->Signal(); | |
| 104 } | |
| 105 | |
| 106 } // namespace | |
| 107 | |
| 108 class AutofillTableMock : public AutofillTable { | |
| 109 public: | |
| 110 AutofillTableMock() {} | |
| 111 MOCK_METHOD2(RemoveFormElement, | |
| 112 bool(const base::string16& name, | |
| 113 const base::string16& value)); // NOLINT | |
| 114 MOCK_METHOD1(GetAllAutofillEntries, | |
| 115 bool(std::vector<AutofillEntry>* entries)); // NOLINT | |
| 116 MOCK_METHOD4(GetAutofillTimestamps, | |
| 117 bool(const base::string16& name, // NOLINT | |
| 118 const base::string16& value, | |
| 119 Time* date_created, | |
| 120 Time* date_last_used)); | |
| 121 MOCK_METHOD1(UpdateAutofillEntries, | |
| 122 bool(const std::vector<AutofillEntry>&)); // NOLINT | |
| 123 MOCK_METHOD1(GetAutofillProfiles, | |
| 124 bool(std::vector<AutofillProfile*>*)); // NOLINT | |
| 125 MOCK_METHOD1(UpdateAutofillProfile, | |
| 126 bool(const AutofillProfile&)); // NOLINT | |
| 127 MOCK_METHOD1(AddAutofillProfile, | |
| 128 bool(const AutofillProfile&)); // NOLINT | |
| 129 MOCK_METHOD1(RemoveAutofillProfile, | |
| 130 bool(const std::string&)); // NOLINT | |
| 131 }; | |
| 132 | |
| 133 MATCHER_P(MatchProfiles, profile, "") { | |
| 134 return (profile.Compare(arg) == 0); | |
| 135 } | |
| 136 | |
| 137 class WebDatabaseFake : public WebDatabase { | |
| 138 public: | |
| 139 explicit WebDatabaseFake(AutofillTable* autofill_table) { | |
| 140 AddTable(autofill_table); | |
| 141 } | |
| 142 }; | |
| 143 | |
| 144 class MockAutofillBackend : public autofill::AutofillWebDataBackend { | |
| 145 public: | |
| 146 MockAutofillBackend(WebDatabase* web_database, | |
| 147 const base::Closure& on_changed, | |
| 148 const scoped_refptr<base::SequencedTaskRunner>& ui_thread) | |
| 149 : web_database_(web_database), | |
| 150 on_changed_(on_changed), | |
| 151 ui_thread_(ui_thread) {} | |
| 152 | |
| 153 ~MockAutofillBackend() override {} | |
| 154 WebDatabase* GetDatabase() override { return web_database_; } | |
| 155 void AddObserver( | |
| 156 autofill::AutofillWebDataServiceObserverOnDBThread* observer) override {} | |
| 157 void RemoveObserver( | |
| 158 autofill::AutofillWebDataServiceObserverOnDBThread* observer) override {} | |
| 159 void RemoveExpiredFormElements() override {} | |
| 160 void NotifyOfMultipleAutofillChanges() override { | |
| 161 DCHECK(!ui_thread_->RunsTasksOnCurrentThread()); | |
| 162 ui_thread_->PostTask(FROM_HERE, on_changed_); | |
| 163 } | |
| 164 | |
| 165 private: | |
| 166 WebDatabase* web_database_; | |
| 167 base::Closure on_changed_; | |
| 168 const scoped_refptr<base::SequencedTaskRunner> ui_thread_; | |
| 169 }; | |
| 170 | |
| 171 class ProfileSyncServiceAutofillTest; | |
| 172 | |
| 173 template<class AutofillProfile> | |
| 174 syncer::ModelType GetModelType() { | |
| 175 return syncer::UNSPECIFIED; | |
| 176 } | |
| 177 | |
| 178 template<> | |
| 179 syncer::ModelType GetModelType<AutofillEntry>() { | |
| 180 return AUTOFILL; | |
| 181 } | |
| 182 | |
| 183 template<> | |
| 184 syncer::ModelType GetModelType<AutofillProfile>() { | |
| 185 return AUTOFILL_PROFILE; | |
| 186 } | |
| 187 | |
| 188 class TokenWebDataServiceFake : public TokenWebData { | |
| 189 public: | |
| 190 TokenWebDataServiceFake( | |
| 191 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, | |
| 192 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread) | |
| 193 : TokenWebData(ui_thread, db_thread) {} | |
| 194 | |
| 195 bool IsDatabaseLoaded() override { return true; } | |
| 196 | |
| 197 AutofillWebDataService::Handle GetAllTokens( | |
| 198 WebDataServiceConsumer* consumer) override { | |
| 199 // TODO(tim): It would be nice if WebDataService was injected on | |
| 200 // construction of ProfileOAuth2TokenService rather than fetched by | |
| 201 // Initialize so that this isn't necessary (we could pass a NULL service). | |
| 202 // We currently do return it via EXPECT_CALLs, but without depending on | |
| 203 // order-of-initialization (which seems way more fragile) we can't tell | |
| 204 // which component is asking at what time, and some components in these | |
| 205 // Autofill tests require a WebDataService. | |
| 206 return 0; | |
| 207 } | |
| 208 | |
| 209 private: | |
| 210 ~TokenWebDataServiceFake() override {} | |
| 211 | |
| 212 DISALLOW_COPY_AND_ASSIGN(TokenWebDataServiceFake); | |
| 213 }; | |
| 214 | |
| 215 class WebDataServiceFake : public AutofillWebDataService { | |
| 216 public: | |
| 217 WebDataServiceFake( | |
| 218 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, | |
| 219 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread) | |
| 220 : AutofillWebDataService(ui_thread, db_thread), | |
| 221 web_database_(NULL), | |
| 222 autocomplete_syncable_service_(NULL), | |
| 223 autofill_profile_syncable_service_(NULL), | |
| 224 syncable_service_created_or_destroyed_(false, false), | |
| 225 db_thread_(db_thread), | |
| 226 ui_thread_(ui_thread) {} | |
| 227 | |
| 228 void SetDatabase(WebDatabase* web_database) { | |
| 229 web_database_ = web_database; | |
| 230 } | |
| 231 | |
| 232 void StartSyncableService() { | |
| 233 // The |autofill_profile_syncable_service_| must be constructed on the DB | |
| 234 // thread. | |
| 235 const base::Closure& on_changed_callback = base::Bind( | |
| 236 &WebDataServiceFake::NotifyAutofillMultipleChangedOnUIThread, | |
| 237 AsWeakPtr()); | |
| 238 | |
| 239 db_thread_->PostTask( | |
| 240 FROM_HERE, base::Bind(&WebDataServiceFake::CreateSyncableService, | |
| 241 base::Unretained(this), on_changed_callback)); | |
| 242 syncable_service_created_or_destroyed_.Wait(); | |
| 243 } | |
| 244 | |
| 245 void ShutdownSyncableService() { | |
| 246 // The |autofill_profile_syncable_service_| must be destructed on the DB | |
| 247 // thread. | |
| 248 db_thread_->PostTask(FROM_HERE, | |
| 249 base::Bind(&WebDataServiceFake::DestroySyncableService, | |
| 250 base::Unretained(this))); | |
| 251 syncable_service_created_or_destroyed_.Wait(); | |
| 252 } | |
| 253 | |
| 254 bool IsDatabaseLoaded() override { return true; } | |
| 255 | |
| 256 WebDatabase* GetDatabase() override { return web_database_; } | |
| 257 | |
| 258 void OnAutofillEntriesChanged(const AutofillChangeList& changes) { | |
| 259 WaitableEvent event(true, false); | |
| 260 | |
| 261 base::Closure notify_cb = | |
| 262 base::Bind(&AutocompleteSyncableService::AutofillEntriesChanged, | |
| 263 base::Unretained(autocomplete_syncable_service_), | |
| 264 changes); | |
| 265 db_thread_->PostTask(FROM_HERE, | |
| 266 base::Bind(&RunAndSignal, notify_cb, &event)); | |
| 267 event.Wait(); | |
| 268 } | |
| 269 | |
| 270 void OnAutofillProfileChanged(const AutofillProfileChange& changes) { | |
| 271 WaitableEvent event(true, false); | |
| 272 | |
| 273 base::Closure notify_cb = | |
| 274 base::Bind(&AutocompleteSyncableService::AutofillProfileChanged, | |
| 275 base::Unretained(autofill_profile_syncable_service_), | |
| 276 changes); | |
| 277 db_thread_->PostTask(FROM_HERE, | |
| 278 base::Bind(&RunAndSignal, notify_cb, &event)); | |
| 279 event.Wait(); | |
| 280 } | |
| 281 | |
| 282 private: | |
| 283 ~WebDataServiceFake() override {} | |
| 284 | |
| 285 void CreateSyncableService(const base::Closure& on_changed_callback) { | |
| 286 ASSERT_TRUE(db_thread_->RunsTasksOnCurrentThread()); | |
| 287 // These services are deleted in DestroySyncableService(). | |
| 288 backend_.reset(new MockAutofillBackend(GetDatabase(), on_changed_callback, | |
| 289 ui_thread_.get())); | |
| 290 AutocompleteSyncableService::CreateForWebDataServiceAndBackend( | |
| 291 this, backend_.get()); | |
| 292 AutofillProfileSyncableService::CreateForWebDataServiceAndBackend( | |
| 293 this, backend_.get(), "en-US"); | |
| 294 | |
| 295 autocomplete_syncable_service_ = | |
| 296 AutocompleteSyncableService::FromWebDataService(this); | |
| 297 autofill_profile_syncable_service_ = | |
| 298 AutofillProfileSyncableService::FromWebDataService(this); | |
| 299 | |
| 300 syncable_service_created_or_destroyed_.Signal(); | |
| 301 } | |
| 302 | |
| 303 void DestroySyncableService() { | |
| 304 ASSERT_TRUE(db_thread_->RunsTasksOnCurrentThread()); | |
| 305 autocomplete_syncable_service_ = NULL; | |
| 306 autofill_profile_syncable_service_ = NULL; | |
| 307 backend_.reset(); | |
| 308 syncable_service_created_or_destroyed_.Signal(); | |
| 309 } | |
| 310 | |
| 311 WebDatabase* web_database_; | |
| 312 AutocompleteSyncableService* autocomplete_syncable_service_; | |
| 313 AutofillProfileSyncableService* autofill_profile_syncable_service_; | |
| 314 scoped_ptr<autofill::AutofillWebDataBackend> backend_; | |
| 315 | |
| 316 WaitableEvent syncable_service_created_or_destroyed_; | |
| 317 | |
| 318 const scoped_refptr<base::SingleThreadTaskRunner> db_thread_; | |
| 319 const scoped_refptr<base::SingleThreadTaskRunner> ui_thread_; | |
| 320 | |
| 321 DISALLOW_COPY_AND_ASSIGN(WebDataServiceFake); | |
| 322 }; | |
| 323 | |
| 324 ACTION_P(ReturnNewDataTypeManagerWithDebugListener, debug_listener) { | |
| 325 return new sync_driver::DataTypeManagerImpl( | |
| 326 debug_listener, | |
| 327 arg1, | |
| 328 arg2, | |
| 329 arg3, | |
| 330 arg4); | |
| 331 } | |
| 332 | |
| 333 class MockPersonalDataManager : public PersonalDataManager { | |
| 334 public: | |
| 335 MockPersonalDataManager() : PersonalDataManager("en-US") {} | |
| 336 MOCK_CONST_METHOD0(IsDataLoaded, bool()); | |
| 337 MOCK_METHOD0(LoadProfiles, void()); | |
| 338 MOCK_METHOD0(LoadCreditCards, void()); | |
| 339 MOCK_METHOD0(Refresh, void()); | |
| 340 }; | |
| 341 | |
| 342 template <class T> class AddAutofillHelper; | |
| 343 | |
| 344 class ProfileSyncServiceAutofillTest | |
| 345 : public AbstractProfileSyncServiceTest, | |
| 346 public syncer::DataTypeDebugInfoListener { | |
| 347 public: | |
| 348 // DataTypeDebugInfoListener implementation. | |
| 349 void OnDataTypeConfigureComplete(const std::vector< | |
| 350 syncer::DataTypeConfigurationStats>& configuration_stats) override { | |
| 351 ASSERT_EQ(1u, configuration_stats.size()); | |
| 352 association_stats_ = configuration_stats[0].association_stats; | |
| 353 } | |
| 354 | |
| 355 protected: | |
| 356 ProfileSyncServiceAutofillTest() : debug_ptr_factory_(this) { | |
| 357 autofill::CountryNames::SetLocaleString("en-US"); | |
| 358 RegisterAutofillPrefs( | |
| 359 profile_sync_service_bundle_.pref_service()->registry()); | |
| 360 | |
| 361 data_type_thread_.Start(); | |
| 362 profile_sync_service_bundle_.set_db_thread(data_type_thread_.task_runner()); | |
| 363 | |
| 364 web_database_.reset(new WebDatabaseFake(&autofill_table_)); | |
| 365 web_data_wrapper_ = make_scoped_ptr(new MockWebDataServiceWrapper( | |
| 366 new WebDataServiceFake(base::ThreadTaskRunnerHandle::Get(), | |
| 367 data_type_thread_.task_runner()), | |
| 368 new TokenWebDataServiceFake(base::ThreadTaskRunnerHandle::Get(), | |
| 369 data_type_thread_.task_runner()))); | |
| 370 web_data_service_ = static_cast<WebDataServiceFake*>( | |
| 371 web_data_wrapper_->GetAutofillWebData().get()); | |
| 372 web_data_service_->SetDatabase(web_database_.get()); | |
| 373 | |
| 374 personal_data_manager_ = make_scoped_ptr(new MockPersonalDataManager()); | |
| 375 | |
| 376 EXPECT_CALL(*personal_data_manager_, LoadProfiles()); | |
| 377 EXPECT_CALL(*personal_data_manager_, LoadCreditCards()); | |
| 378 | |
| 379 personal_data_manager_->Init( | |
| 380 web_data_service_, profile_sync_service_bundle_.pref_service(), | |
| 381 profile_sync_service_bundle_.account_tracker(), | |
| 382 profile_sync_service_bundle_.signin_manager(), false); | |
| 383 | |
| 384 web_data_service_->StartSyncableService(); | |
| 385 | |
| 386 browser_sync::ProfileSyncServiceBundle::SyncClientBuilder builder( | |
| 387 &profile_sync_service_bundle_); | |
| 388 builder.SetPersonalDataManager(personal_data_manager_.get()); | |
| 389 builder.SetSyncServiceCallback( | |
| 390 base::Bind(&ProfileSyncServiceAutofillTest::GetSyncService, | |
| 391 base::Unretained(this))); | |
| 392 builder.SetSyncableServiceCallback( | |
| 393 base::Bind(&ProfileSyncServiceAutofillTest::GetSyncableServiceForType, | |
| 394 base::Unretained(this))); | |
| 395 builder.set_activate_model_creation(); | |
| 396 sync_client_owned_ = builder.Build(); | |
| 397 sync_client_ = sync_client_owned_.get(); | |
| 398 | |
| 399 // When UpdateAutofillEntries() is called with an empty list, the return | |
| 400 // value should be |true|, rather than the default of |false|. | |
| 401 std::vector<AutofillEntry> empty; | |
| 402 EXPECT_CALL(autofill_table_, UpdateAutofillEntries(empty)) | |
| 403 .WillRepeatedly(Return(true)); | |
| 404 } | |
| 405 | |
| 406 ~ProfileSyncServiceAutofillTest() override { | |
| 407 web_data_service_->ShutdownOnUIThread(); | |
| 408 web_data_service_->ShutdownSyncableService(); | |
| 409 web_data_wrapper_->Shutdown(); | |
| 410 web_data_service_ = nullptr; | |
| 411 web_data_wrapper_.reset(); | |
| 412 web_database_.reset(); | |
| 413 // Shut down the service explicitly before some data members from this | |
| 414 // test it needs will be deleted. | |
| 415 sync_service_->Shutdown(); | |
| 416 } | |
| 417 | |
| 418 int GetSyncCount(syncer::ModelType type) { | |
| 419 syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 420 syncer::ReadNode node(&trans); | |
| 421 if (node.InitTypeRoot(type) != BaseNode::INIT_OK) | |
| 422 return 0; | |
| 423 return node.GetTotalNodeCount() - 1; | |
| 424 } | |
| 425 | |
| 426 void StartSyncService(const base::Closure& callback, | |
| 427 bool will_fail_association, | |
| 428 syncer::ModelType type) { | |
| 429 SigninManagerBase* signin = profile_sync_service_bundle_.signin_manager(); | |
| 430 signin->SetAuthenticatedAccountInfo("12345", "test_user@gmail.com"); | |
| 431 sync_service_ = CreateSyncService(std::move(sync_client_owned_), callback); | |
| 432 | |
| 433 EXPECT_CALL(*profile_sync_service_bundle_.component_factory(), | |
| 434 CreateDataTypeManager(_, _, _, _, _)) | |
| 435 .WillOnce(ReturnNewDataTypeManagerWithDebugListener( | |
| 436 syncer::MakeWeakHandle(debug_ptr_factory_.GetWeakPtr()))); | |
| 437 | |
| 438 EXPECT_CALL(*personal_data_manager_, IsDataLoaded()). | |
| 439 WillRepeatedly(Return(true)); | |
| 440 | |
| 441 // We need tokens to get the tests going | |
| 442 profile_sync_service_bundle_.auth_service()->UpdateCredentials( | |
| 443 signin->GetAuthenticatedAccountId(), "oauth2_login_token"); | |
| 444 | |
| 445 sync_service_->RegisterDataTypeController(CreateDataTypeController(type)); | |
| 446 sync_service_->Initialize(); | |
| 447 base::RunLoop().Run(); | |
| 448 | |
| 449 // It's possible this test triggered an unrecoverable error, in which case | |
| 450 // we can't get the sync count. | |
| 451 if (sync_service_->IsSyncActive()) { | |
| 452 EXPECT_EQ(GetSyncCount(type), | |
| 453 association_stats_.num_sync_items_after_association); | |
| 454 } | |
| 455 EXPECT_EQ(association_stats_.num_sync_items_after_association, | |
| 456 association_stats_.num_sync_items_before_association + | |
| 457 association_stats_.num_sync_items_added - | |
| 458 association_stats_.num_sync_items_deleted); | |
| 459 } | |
| 460 | |
| 461 bool AddAutofillSyncNode(const AutofillEntry& entry) { | |
| 462 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 463 syncer::WriteNode node(&trans); | |
| 464 std::string tag = AutocompleteSyncableService::KeyToTag( | |
| 465 base::UTF16ToUTF8(entry.key().name()), | |
| 466 base::UTF16ToUTF8(entry.key().value())); | |
| 467 syncer::WriteNode::InitUniqueByCreationResult result = | |
| 468 node.InitUniqueByCreation(AUTOFILL, tag); | |
| 469 if (result != syncer::WriteNode::INIT_SUCCESS) | |
| 470 return false; | |
| 471 | |
| 472 sync_pb::EntitySpecifics specifics; | |
| 473 AutocompleteSyncableService::WriteAutofillEntry(entry, &specifics); | |
| 474 node.SetEntitySpecifics(specifics); | |
| 475 return true; | |
| 476 } | |
| 477 | |
| 478 bool AddAutofillSyncNode(const AutofillProfile& profile) { | |
| 479 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 480 syncer::WriteNode node(&trans); | |
| 481 std::string tag = profile.guid(); | |
| 482 syncer::WriteNode::InitUniqueByCreationResult result = | |
| 483 node.InitUniqueByCreation(AUTOFILL_PROFILE, tag); | |
| 484 if (result != syncer::WriteNode::INIT_SUCCESS) | |
| 485 return false; | |
| 486 | |
| 487 sync_pb::EntitySpecifics specifics; | |
| 488 AutofillProfileSyncableService::WriteAutofillProfile(profile, &specifics); | |
| 489 node.SetEntitySpecifics(specifics); | |
| 490 return true; | |
| 491 } | |
| 492 | |
| 493 bool GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries, | |
| 494 std::vector<AutofillProfile>* profiles) { | |
| 495 syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 496 syncer::ReadNode autofill_root(&trans); | |
| 497 if (autofill_root.InitTypeRoot(AUTOFILL) != BaseNode::INIT_OK) { | |
| 498 return false; | |
| 499 } | |
| 500 | |
| 501 int64_t child_id = autofill_root.GetFirstChildId(); | |
| 502 while (child_id != syncer::kInvalidId) { | |
| 503 syncer::ReadNode child_node(&trans); | |
| 504 if (child_node.InitByIdLookup(child_id) != BaseNode::INIT_OK) | |
| 505 return false; | |
| 506 | |
| 507 const sync_pb::AutofillSpecifics& autofill( | |
| 508 child_node.GetEntitySpecifics().autofill()); | |
| 509 if (autofill.has_value()) { | |
| 510 AutofillKey key(base::UTF8ToUTF16(autofill.name()), | |
| 511 base::UTF8ToUTF16(autofill.value())); | |
| 512 std::vector<Time> timestamps; | |
| 513 int timestamps_count = autofill.usage_timestamp_size(); | |
| 514 for (int i = 0; i < timestamps_count; ++i) { | |
| 515 timestamps.push_back(Time::FromInternalValue( | |
| 516 autofill.usage_timestamp(i))); | |
| 517 } | |
| 518 entries->push_back( | |
| 519 AutofillEntry(key, timestamps.front(), timestamps.back())); | |
| 520 } else if (autofill.has_profile()) { | |
| 521 AutofillProfile p; | |
| 522 p.set_guid(autofill.profile().guid()); | |
| 523 AutofillProfileSyncableService::OverwriteProfileWithServerData( | |
| 524 autofill.profile(), &p); | |
| 525 profiles->push_back(p); | |
| 526 } | |
| 527 child_id = child_node.GetSuccessorId(); | |
| 528 } | |
| 529 return true; | |
| 530 } | |
| 531 | |
| 532 bool GetAutofillProfilesFromSyncDBUnderProfileNode( | |
| 533 std::vector<AutofillProfile>* profiles) { | |
| 534 syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 535 syncer::ReadNode autofill_root(&trans); | |
| 536 if (autofill_root.InitTypeRoot(AUTOFILL_PROFILE) != BaseNode::INIT_OK) { | |
| 537 return false; | |
| 538 } | |
| 539 | |
| 540 int64_t child_id = autofill_root.GetFirstChildId(); | |
| 541 while (child_id != syncer::kInvalidId) { | |
| 542 syncer::ReadNode child_node(&trans); | |
| 543 if (child_node.InitByIdLookup(child_id) != BaseNode::INIT_OK) | |
| 544 return false; | |
| 545 | |
| 546 const sync_pb::AutofillProfileSpecifics& autofill( | |
| 547 child_node.GetEntitySpecifics().autofill_profile()); | |
| 548 AutofillProfile p; | |
| 549 p.set_guid(autofill.guid()); | |
| 550 AutofillProfileSyncableService::OverwriteProfileWithServerData(autofill, | |
| 551 &p); | |
| 552 profiles->push_back(p); | |
| 553 child_id = child_node.GetSuccessorId(); | |
| 554 } | |
| 555 return true; | |
| 556 } | |
| 557 | |
| 558 void SetIdleChangeProcessorExpectations() { | |
| 559 EXPECT_CALL(autofill_table_, RemoveFormElement(_, _)).Times(0); | |
| 560 EXPECT_CALL(autofill_table_, GetAutofillTimestamps(_, _, _, _)).Times(0); | |
| 561 | |
| 562 // Only permit UpdateAutofillEntries() to be called with an empty list. | |
| 563 std::vector<AutofillEntry> empty; | |
| 564 EXPECT_CALL(autofill_table_, UpdateAutofillEntries(Not(empty))).Times(0); | |
| 565 } | |
| 566 | |
| 567 static AutofillEntry MakeAutofillEntry(const char* name, | |
| 568 const char* value, | |
| 569 int time_shift0, | |
| 570 int time_shift1) { | |
| 571 // Time deep in the past would cause Autocomplete sync to discard the | |
| 572 // entries. | |
| 573 static Time base_time = Time::Now().LocalMidnight(); | |
| 574 | |
| 575 Time date_created = base_time + TimeDelta::FromSeconds(time_shift0); | |
| 576 Time date_last_used = date_created; | |
| 577 if (time_shift1 >= 0) | |
| 578 date_last_used = base_time + TimeDelta::FromSeconds(time_shift1); | |
| 579 return AutofillEntry( | |
| 580 AutofillKey(base::ASCIIToUTF16(name), base::ASCIIToUTF16(value)), | |
| 581 date_created, date_last_used); | |
| 582 } | |
| 583 | |
| 584 static AutofillEntry MakeAutofillEntry(const char* name, | |
| 585 const char* value, | |
| 586 int time_shift) { | |
| 587 return MakeAutofillEntry(name, value, time_shift, -1); | |
| 588 } | |
| 589 | |
| 590 sync_driver::DataTypeController* CreateDataTypeController( | |
| 591 syncer::ModelType type) { | |
| 592 DCHECK(type == AUTOFILL || type == AUTOFILL_PROFILE); | |
| 593 if (type == AUTOFILL) { | |
| 594 return new AutofillDataTypeController( | |
| 595 base::ThreadTaskRunnerHandle::Get(), data_type_thread_.task_runner(), | |
| 596 base::Bind(&base::DoNothing), sync_client_, web_data_service_); | |
| 597 } else { | |
| 598 return new AutofillProfileDataTypeController( | |
| 599 base::ThreadTaskRunnerHandle::Get(), data_type_thread_.task_runner(), | |
| 600 base::Bind(&base::DoNothing), sync_client_, web_data_service_); | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 friend class AddAutofillHelper<AutofillEntry>; | |
| 605 friend class AddAutofillHelper<AutofillProfile>; | |
| 606 friend class FakeServerUpdater; | |
| 607 | |
| 608 AutofillTableMock autofill_table_; | |
| 609 scoped_ptr<WebDatabaseFake> web_database_; | |
| 610 scoped_ptr<MockWebDataServiceWrapper> web_data_wrapper_; | |
| 611 scoped_refptr<WebDataServiceFake> web_data_service_; | |
| 612 scoped_ptr<MockPersonalDataManager> personal_data_manager_; | |
| 613 syncer::DataTypeAssociationStats association_stats_; | |
| 614 base::WeakPtrFactory<DataTypeDebugInfoListener> debug_ptr_factory_; | |
| 615 // |sync_client_owned_| keeps the created client until it is passed to the | |
| 616 // created ProfileSyncService. |sync_client_| just keeps a weak reference to | |
| 617 // the client the whole time. | |
| 618 scoped_ptr<sync_driver::FakeSyncClient> sync_client_owned_; | |
| 619 sync_driver::FakeSyncClient* sync_client_; | |
| 620 | |
| 621 private: | |
| 622 sync_driver::SyncService* GetSyncService() { return sync_service_.get(); } | |
| 623 | |
| 624 base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType( | |
| 625 syncer::ModelType type) { | |
| 626 DCHECK(type == AUTOFILL || type == AUTOFILL_PROFILE); | |
| 627 if (type == AUTOFILL) { | |
| 628 return AutocompleteSyncableService::FromWebDataService( | |
| 629 web_data_service_.get()) | |
| 630 ->AsWeakPtr(); | |
| 631 } else { | |
| 632 return AutofillProfileSyncableService::FromWebDataService( | |
| 633 web_data_service_.get()) | |
| 634 ->AsWeakPtr(); | |
| 635 } | |
| 636 } | |
| 637 | |
| 638 DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceAutofillTest); | |
| 639 }; | |
| 640 | |
| 641 template <class T> | |
| 642 class AddAutofillHelper { | |
| 643 public: | |
| 644 AddAutofillHelper(ProfileSyncServiceAutofillTest* test, | |
| 645 const std::vector<T>& entries) | |
| 646 : callback_(base::Bind(&AddAutofillHelper::AddAutofillCallback, | |
| 647 base::Unretained(this), test, entries)), | |
| 648 success_(false) { | |
| 649 } | |
| 650 | |
| 651 const base::Closure& callback() const { return callback_; } | |
| 652 bool success() { return success_; } | |
| 653 | |
| 654 private: | |
| 655 void AddAutofillCallback(ProfileSyncServiceAutofillTest* test, | |
| 656 const std::vector<T>& entries) { | |
| 657 if (!test->CreateRoot(GetModelType<T>())) | |
| 658 return; | |
| 659 | |
| 660 for (size_t i = 0; i < entries.size(); ++i) { | |
| 661 if (!test->AddAutofillSyncNode(entries[i])) | |
| 662 return; | |
| 663 } | |
| 664 success_ = true; | |
| 665 } | |
| 666 | |
| 667 base::Closure callback_; | |
| 668 bool success_; | |
| 669 }; | |
| 670 | |
| 671 // Overload write transaction to use custom NotifyTransactionComplete | |
| 672 class WriteTransactionTest: public WriteTransaction { | |
| 673 public: | |
| 674 WriteTransactionTest(const tracked_objects::Location& from_here, | |
| 675 WriterTag writer, | |
| 676 syncer::syncable::Directory* directory, | |
| 677 WaitableEvent* wait_for_syncapi) | |
| 678 : WriteTransaction(from_here, writer, directory), | |
| 679 wait_for_syncapi_(wait_for_syncapi) {} | |
| 680 | |
| 681 void NotifyTransactionComplete(syncer::ModelTypeSet types) override { | |
| 682 // This is where we differ. Force a thread change here, giving another | |
| 683 // thread a chance to create a WriteTransaction | |
| 684 wait_for_syncapi_->Wait(); | |
| 685 | |
| 686 WriteTransaction::NotifyTransactionComplete(types); | |
| 687 } | |
| 688 | |
| 689 private: | |
| 690 WaitableEvent* const wait_for_syncapi_; | |
| 691 }; | |
| 692 | |
| 693 // Our fake server updater. Needs the RefCountedThreadSafe inheritance so we can | |
| 694 // post tasks with it. | |
| 695 class FakeServerUpdater : public base::RefCountedThreadSafe<FakeServerUpdater> { | |
| 696 public: | |
| 697 FakeServerUpdater(TestProfileSyncService* service, | |
| 698 WaitableEvent* wait_for_start, | |
| 699 WaitableEvent* wait_for_syncapi, | |
| 700 scoped_refptr<base::SequencedTaskRunner> db_thread) | |
| 701 : entry_(ProfileSyncServiceAutofillTest::MakeAutofillEntry("0", "0", 0)), | |
| 702 service_(service), | |
| 703 wait_for_start_(wait_for_start), | |
| 704 wait_for_syncapi_(wait_for_syncapi), | |
| 705 is_finished_(false, false), | |
| 706 db_thread_(db_thread) {} | |
| 707 | |
| 708 void Update() { | |
| 709 // This gets called in a modelsafeworker thread. | |
| 710 ASSERT_TRUE(db_thread_->RunsTasksOnCurrentThread()); | |
| 711 | |
| 712 syncer::UserShare* user_share = service_->GetUserShare(); | |
| 713 syncer::syncable::Directory* directory = user_share->directory.get(); | |
| 714 | |
| 715 // Create autofill protobuf. | |
| 716 std::string tag = AutocompleteSyncableService::KeyToTag( | |
| 717 base::UTF16ToUTF8(entry_.key().name()), | |
| 718 base::UTF16ToUTF8(entry_.key().value())); | |
| 719 sync_pb::AutofillSpecifics new_autofill; | |
| 720 new_autofill.set_name(base::UTF16ToUTF8(entry_.key().name())); | |
| 721 new_autofill.set_value(base::UTF16ToUTF8(entry_.key().value())); | |
| 722 new_autofill.add_usage_timestamp(entry_.date_created().ToInternalValue()); | |
| 723 if (entry_.date_created() != entry_.date_last_used()) { | |
| 724 new_autofill.add_usage_timestamp( | |
| 725 entry_.date_last_used().ToInternalValue()); | |
| 726 } | |
| 727 | |
| 728 sync_pb::EntitySpecifics entity_specifics; | |
| 729 entity_specifics.mutable_autofill()->CopyFrom(new_autofill); | |
| 730 | |
| 731 { | |
| 732 // Tell main thread we've started | |
| 733 wait_for_start_->Signal(); | |
| 734 | |
| 735 // Create write transaction. | |
| 736 WriteTransactionTest trans(FROM_HERE, UNITTEST, directory, | |
| 737 wait_for_syncapi_); | |
| 738 | |
| 739 // Create actual entry based on autofill protobuf information. | |
| 740 // Simulates effects of UpdateLocalDataFromServerData | |
| 741 MutableEntry parent(&trans, GET_TYPE_ROOT, AUTOFILL); | |
| 742 MutableEntry item(&trans, CREATE, AUTOFILL, parent.GetId(), tag); | |
| 743 ASSERT_TRUE(item.good()); | |
| 744 item.PutSpecifics(entity_specifics); | |
| 745 item.PutServerSpecifics(entity_specifics); | |
| 746 item.PutBaseVersion(1); | |
| 747 syncer::syncable::Id server_item_id = | |
| 748 service_->id_factory()->NewServerId(); | |
| 749 item.PutId(server_item_id); | |
| 750 syncer::syncable::Id new_predecessor; | |
| 751 ASSERT_TRUE(item.PutPredecessor(new_predecessor)); | |
| 752 } | |
| 753 DVLOG(1) << "FakeServerUpdater finishing."; | |
| 754 is_finished_.Signal(); | |
| 755 } | |
| 756 | |
| 757 void CreateNewEntry(const AutofillEntry& entry) { | |
| 758 entry_ = entry; | |
| 759 ASSERT_FALSE(db_thread_->RunsTasksOnCurrentThread()); | |
| 760 if (!db_thread_->PostTask(FROM_HERE, | |
| 761 base::Bind(&FakeServerUpdater::Update, this))) { | |
| 762 NOTREACHED() << "Failed to post task to the db thread."; | |
| 763 return; | |
| 764 } | |
| 765 } | |
| 766 | |
| 767 void WaitForUpdateCompletion() { | |
| 768 is_finished_.Wait(); | |
| 769 } | |
| 770 | |
| 771 private: | |
| 772 friend class base::RefCountedThreadSafe<FakeServerUpdater>; | |
| 773 ~FakeServerUpdater() { } | |
| 774 | |
| 775 AutofillEntry entry_; | |
| 776 TestProfileSyncService* service_; | |
| 777 WaitableEvent* const wait_for_start_; | |
| 778 WaitableEvent* const wait_for_syncapi_; | |
| 779 WaitableEvent is_finished_; | |
| 780 syncer::syncable::Id parent_id_; | |
| 781 scoped_refptr<base::SequencedTaskRunner> db_thread_; | |
| 782 | |
| 783 DISALLOW_COPY_AND_ASSIGN(FakeServerUpdater); | |
| 784 }; | |
| 785 | |
| 786 // TODO(skrul): Test abort startup. | |
| 787 // TODO(skrul): Test processing of cloud changes. | |
| 788 // TODO(tim): Add autofill data type controller test, and a case to cover | |
| 789 // waiting for the PersonalDataManager. | |
| 790 TEST_F(ProfileSyncServiceAutofillTest, FailModelAssociation) { | |
| 791 // Don't create the root autofill node so startup fails. | |
| 792 StartSyncService(base::Closure(), true, AUTOFILL); | |
| 793 EXPECT_TRUE(sync_service_->HasUnrecoverableError()); | |
| 794 } | |
| 795 | |
| 796 TEST_F(ProfileSyncServiceAutofillTest, EmptyNativeEmptySync) { | |
| 797 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)).WillOnce(Return(true)); | |
| 798 SetIdleChangeProcessorExpectations(); | |
| 799 CreateRootHelper create_root(this, AUTOFILL); | |
| 800 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 801 StartSyncService(create_root.callback(), false, AUTOFILL); | |
| 802 EXPECT_TRUE(create_root.success()); | |
| 803 std::vector<AutofillEntry> sync_entries; | |
| 804 std::vector<AutofillProfile> sync_profiles; | |
| 805 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); | |
| 806 EXPECT_EQ(0U, sync_entries.size()); | |
| 807 EXPECT_EQ(0U, sync_profiles.size()); | |
| 808 } | |
| 809 | |
| 810 TEST_F(ProfileSyncServiceAutofillTest, HasNativeEntriesEmptySync) { | |
| 811 std::vector<AutofillEntry> entries; | |
| 812 entries.push_back(MakeAutofillEntry("foo", "bar", 1)); | |
| 813 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)). | |
| 814 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); | |
| 815 SetIdleChangeProcessorExpectations(); | |
| 816 CreateRootHelper create_root(this, AUTOFILL); | |
| 817 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 818 StartSyncService(create_root.callback(), false, AUTOFILL); | |
| 819 ASSERT_TRUE(create_root.success()); | |
| 820 std::vector<AutofillEntry> sync_entries; | |
| 821 std::vector<AutofillProfile> sync_profiles; | |
| 822 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); | |
| 823 ASSERT_EQ(1U, entries.size()); | |
| 824 EXPECT_TRUE(entries[0] == sync_entries[0]); | |
| 825 EXPECT_EQ(0U, sync_profiles.size()); | |
| 826 } | |
| 827 | |
| 828 TEST_F(ProfileSyncServiceAutofillTest, HasProfileEmptySync) { | |
| 829 std::vector<AutofillProfile*> profiles; | |
| 830 std::vector<AutofillProfile> expected_profiles; | |
| 831 // Owned by GetAutofillProfiles caller. | |
| 832 AutofillProfile* profile0 = new AutofillProfile; | |
| 833 autofill::test::SetProfileInfoWithGuid(profile0, | |
| 834 "54B3F9AA-335E-4F71-A27D-719C41564230", "Billing", | |
| 835 "Mitchell", "Morrison", | |
| 836 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", | |
| 837 "91601", "US", "12345678910"); | |
| 838 profiles.push_back(profile0); | |
| 839 expected_profiles.push_back(*profile0); | |
| 840 EXPECT_CALL(autofill_table_, GetAutofillProfiles(_)). | |
| 841 WillOnce(DoAll(SetArgumentPointee<0>(profiles), Return(true))); | |
| 842 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 843 SetIdleChangeProcessorExpectations(); | |
| 844 CreateRootHelper create_root(this, AUTOFILL_PROFILE); | |
| 845 StartSyncService(create_root.callback(), false, AUTOFILL_PROFILE); | |
| 846 ASSERT_TRUE(create_root.success()); | |
| 847 std::vector<AutofillProfile> sync_profiles; | |
| 848 ASSERT_TRUE(GetAutofillProfilesFromSyncDBUnderProfileNode(&sync_profiles)); | |
| 849 EXPECT_EQ(1U, sync_profiles.size()); | |
| 850 EXPECT_EQ(0, expected_profiles[0].Compare(sync_profiles[0])); | |
| 851 } | |
| 852 | |
| 853 TEST_F(ProfileSyncServiceAutofillTest, HasNativeWithDuplicatesEmptySync) { | |
| 854 // There is buggy autofill code that allows duplicate name/value | |
| 855 // pairs to exist in the database with separate pair_ids. | |
| 856 std::vector<AutofillEntry> entries; | |
| 857 entries.push_back(MakeAutofillEntry("foo", "bar", 1)); | |
| 858 entries.push_back(MakeAutofillEntry("dup", "", 2)); | |
| 859 entries.push_back(MakeAutofillEntry("dup", "", 3)); | |
| 860 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)). | |
| 861 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); | |
| 862 SetIdleChangeProcessorExpectations(); | |
| 863 CreateRootHelper create_root(this, AUTOFILL); | |
| 864 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 865 StartSyncService(create_root.callback(), false, AUTOFILL); | |
| 866 ASSERT_TRUE(create_root.success()); | |
| 867 std::vector<AutofillEntry> sync_entries; | |
| 868 std::vector<AutofillProfile> sync_profiles; | |
| 869 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); | |
| 870 EXPECT_EQ(2U, sync_entries.size()); | |
| 871 } | |
| 872 | |
| 873 TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncNoMerge) { | |
| 874 AutofillEntry native_entry(MakeAutofillEntry("native", "entry", 1)); | |
| 875 AutofillEntry sync_entry(MakeAutofillEntry("sync", "entry", 2)); | |
| 876 | |
| 877 std::vector<AutofillEntry> native_entries; | |
| 878 native_entries.push_back(native_entry); | |
| 879 | |
| 880 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)). | |
| 881 WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true))); | |
| 882 | |
| 883 std::vector<AutofillEntry> sync_entries; | |
| 884 sync_entries.push_back(sync_entry); | |
| 885 | |
| 886 AddAutofillHelper<AutofillEntry> add_autofill(this, sync_entries); | |
| 887 | |
| 888 EXPECT_CALL(autofill_table_, UpdateAutofillEntries(ElementsAre(sync_entry))). | |
| 889 WillOnce(Return(true)); | |
| 890 | |
| 891 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 892 StartSyncService(add_autofill.callback(), false, AUTOFILL); | |
| 893 ASSERT_TRUE(add_autofill.success()); | |
| 894 | |
| 895 std::set<AutofillEntry> expected_entries; | |
| 896 expected_entries.insert(native_entry); | |
| 897 expected_entries.insert(sync_entry); | |
| 898 | |
| 899 std::vector<AutofillEntry> new_sync_entries; | |
| 900 std::vector<AutofillProfile> new_sync_profiles; | |
| 901 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, | |
| 902 &new_sync_profiles)); | |
| 903 std::set<AutofillEntry> new_sync_entries_set(new_sync_entries.begin(), | |
| 904 new_sync_entries.end()); | |
| 905 | |
| 906 EXPECT_TRUE(expected_entries == new_sync_entries_set); | |
| 907 } | |
| 908 | |
| 909 TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeEntry) { | |
| 910 AutofillEntry native_entry(MakeAutofillEntry("merge", "entry", 1)); | |
| 911 AutofillEntry sync_entry(MakeAutofillEntry("merge", "entry", 2)); | |
| 912 AutofillEntry merged_entry(MakeAutofillEntry("merge", "entry", 1, 2)); | |
| 913 | |
| 914 std::vector<AutofillEntry> native_entries; | |
| 915 native_entries.push_back(native_entry); | |
| 916 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)). | |
| 917 WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true))); | |
| 918 | |
| 919 std::vector<AutofillEntry> sync_entries; | |
| 920 sync_entries.push_back(sync_entry); | |
| 921 AddAutofillHelper<AutofillEntry> add_autofill(this, sync_entries); | |
| 922 | |
| 923 EXPECT_CALL(autofill_table_, | |
| 924 UpdateAutofillEntries(ElementsAre(merged_entry))).WillOnce(Return(true)); | |
| 925 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 926 StartSyncService(add_autofill.callback(), false, AUTOFILL); | |
| 927 ASSERT_TRUE(add_autofill.success()); | |
| 928 | |
| 929 std::vector<AutofillEntry> new_sync_entries; | |
| 930 std::vector<AutofillProfile> new_sync_profiles; | |
| 931 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, | |
| 932 &new_sync_profiles)); | |
| 933 ASSERT_EQ(1U, new_sync_entries.size()); | |
| 934 EXPECT_TRUE(merged_entry == new_sync_entries[0]); | |
| 935 } | |
| 936 | |
| 937 TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeProfile) { | |
| 938 AutofillProfile sync_profile; | |
| 939 autofill::test::SetProfileInfoWithGuid(&sync_profile, | |
| 940 "23355099-1170-4B71-8ED4-144470CC9EBE", "Billing", | |
| 941 "Mitchell", "Morrison", | |
| 942 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", | |
| 943 "91601", "US", "12345678910"); | |
| 944 | |
| 945 AutofillProfile* native_profile = new AutofillProfile; | |
| 946 autofill::test::SetProfileInfoWithGuid(native_profile, | |
| 947 "23355099-1170-4B71-8ED4-144470CC9EBE", "Billing", "Alicia", "Saenz", | |
| 948 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", | |
| 949 "32801", "US", "19482937549"); | |
| 950 | |
| 951 std::vector<AutofillProfile*> native_profiles; | |
| 952 native_profiles.push_back(native_profile); | |
| 953 EXPECT_CALL(autofill_table_, GetAutofillProfiles(_)). | |
| 954 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); | |
| 955 | |
| 956 std::vector<AutofillProfile> sync_profiles; | |
| 957 sync_profiles.push_back(sync_profile); | |
| 958 AddAutofillHelper<AutofillProfile> add_autofill(this, sync_profiles); | |
| 959 | |
| 960 EXPECT_CALL(autofill_table_, | |
| 961 UpdateAutofillProfile(MatchProfiles(sync_profile))). | |
| 962 WillOnce(Return(true)); | |
| 963 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 964 StartSyncService(add_autofill.callback(), false, AUTOFILL_PROFILE); | |
| 965 ASSERT_TRUE(add_autofill.success()); | |
| 966 | |
| 967 std::vector<AutofillProfile> new_sync_profiles; | |
| 968 ASSERT_TRUE(GetAutofillProfilesFromSyncDBUnderProfileNode( | |
| 969 &new_sync_profiles)); | |
| 970 ASSERT_EQ(1U, new_sync_profiles.size()); | |
| 971 EXPECT_EQ(0, sync_profile.Compare(new_sync_profiles[0])); | |
| 972 } | |
| 973 | |
| 974 TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeProfileCombine) { | |
| 975 AutofillProfile sync_profile; | |
| 976 autofill::test::SetProfileInfoWithGuid(&sync_profile, | |
| 977 "23355099-1170-4B71-8ED4-144470CC9EBE", "Billing", | |
| 978 "Mitchell", "Morrison", | |
| 979 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", | |
| 980 "91601", "US", "12345678910"); | |
| 981 | |
| 982 AutofillProfile* native_profile = new AutofillProfile; | |
| 983 // Same address, but different names, phones and e-mails. | |
| 984 autofill::test::SetProfileInfoWithGuid(native_profile, | |
| 985 "23355099-1170-4B71-8ED4-144470CC9EBF", "Billing", "Alicia", "Saenz", | |
| 986 "joewayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", | |
| 987 "91601", "US", "19482937549"); | |
| 988 | |
| 989 AutofillProfile expected_profile(sync_profile); | |
| 990 expected_profile.OverwriteWith(*native_profile, "en-US"); | |
| 991 | |
| 992 std::vector<AutofillProfile*> native_profiles; | |
| 993 native_profiles.push_back(native_profile); | |
| 994 EXPECT_CALL(autofill_table_, GetAutofillProfiles(_)). | |
| 995 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); | |
| 996 EXPECT_CALL(autofill_table_, | |
| 997 AddAutofillProfile(MatchProfiles(expected_profile))). | |
| 998 WillOnce(Return(true)); | |
| 999 EXPECT_CALL(autofill_table_, | |
| 1000 RemoveAutofillProfile("23355099-1170-4B71-8ED4-144470CC9EBF")). | |
| 1001 WillOnce(Return(true)); | |
| 1002 std::vector<AutofillProfile> sync_profiles; | |
| 1003 sync_profiles.push_back(sync_profile); | |
| 1004 AddAutofillHelper<AutofillProfile> add_autofill(this, sync_profiles); | |
| 1005 | |
| 1006 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 1007 StartSyncService(add_autofill.callback(), false, AUTOFILL_PROFILE); | |
| 1008 ASSERT_TRUE(add_autofill.success()); | |
| 1009 | |
| 1010 std::vector<AutofillProfile> new_sync_profiles; | |
| 1011 ASSERT_TRUE(GetAutofillProfilesFromSyncDBUnderProfileNode( | |
| 1012 &new_sync_profiles)); | |
| 1013 ASSERT_EQ(1U, new_sync_profiles.size()); | |
| 1014 // Check that key fields are the same. | |
| 1015 EXPECT_TRUE(new_sync_profiles[0].IsSubsetOf(sync_profile, "en-US")); | |
| 1016 } | |
| 1017 | |
| 1018 TEST_F(ProfileSyncServiceAutofillTest, MergeProfileWithDifferentGuid) { | |
| 1019 AutofillProfile sync_profile; | |
| 1020 | |
| 1021 autofill::test::SetProfileInfoWithGuid(&sync_profile, | |
| 1022 "23355099-1170-4B71-8ED4-144470CC9EBE", "Billing", | |
| 1023 "Mitchell", "Morrison", | |
| 1024 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", | |
| 1025 "91601", "US", "12345678910"); | |
| 1026 | |
| 1027 std::string native_guid = "EDC609ED-7EEE-4F27-B00C-423242A9C44B"; | |
| 1028 AutofillProfile* native_profile = new AutofillProfile; | |
| 1029 autofill::test::SetProfileInfoWithGuid(native_profile, | |
| 1030 native_guid.c_str(), "Billing", | |
| 1031 "Mitchell", "Morrison", | |
| 1032 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", | |
| 1033 "91601", "US", "12345678910"); | |
| 1034 | |
| 1035 std::vector<AutofillProfile*> native_profiles; | |
| 1036 native_profiles.push_back(native_profile); | |
| 1037 EXPECT_CALL(autofill_table_, GetAutofillProfiles(_)). | |
| 1038 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); | |
| 1039 | |
| 1040 std::vector<AutofillProfile> sync_profiles; | |
| 1041 sync_profiles.push_back(sync_profile); | |
| 1042 AddAutofillHelper<AutofillProfile> add_autofill(this, sync_profiles); | |
| 1043 | |
| 1044 EXPECT_CALL(autofill_table_, AddAutofillProfile(_)). | |
| 1045 WillOnce(Return(true)); | |
| 1046 EXPECT_CALL(autofill_table_, RemoveAutofillProfile(native_guid)). | |
| 1047 WillOnce(Return(true)); | |
| 1048 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 1049 StartSyncService(add_autofill.callback(), false, AUTOFILL_PROFILE); | |
| 1050 ASSERT_TRUE(add_autofill.success()); | |
| 1051 | |
| 1052 std::vector<AutofillProfile> new_sync_profiles; | |
| 1053 ASSERT_TRUE(GetAutofillProfilesFromSyncDBUnderProfileNode( | |
| 1054 &new_sync_profiles)); | |
| 1055 ASSERT_EQ(1U, new_sync_profiles.size()); | |
| 1056 EXPECT_EQ(0, sync_profile.Compare(new_sync_profiles[0])); | |
| 1057 EXPECT_EQ(sync_profile.guid(), new_sync_profiles[0].guid()); | |
| 1058 } | |
| 1059 | |
| 1060 TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddEntry) { | |
| 1061 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)).WillOnce(Return(true)); | |
| 1062 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 1063 SetIdleChangeProcessorExpectations(); | |
| 1064 CreateRootHelper create_root(this, AUTOFILL); | |
| 1065 StartSyncService(create_root.callback(), false, AUTOFILL); | |
| 1066 ASSERT_TRUE(create_root.success()); | |
| 1067 | |
| 1068 AutofillEntry added_entry(MakeAutofillEntry("added", "entry", 1)); | |
| 1069 | |
| 1070 EXPECT_CALL(autofill_table_, GetAutofillTimestamps(_, _, _, _)). | |
| 1071 WillOnce(DoAll(SetArgumentPointee<2>(added_entry.date_created()), | |
| 1072 SetArgumentPointee<3>(added_entry.date_last_used()), | |
| 1073 Return(true))); | |
| 1074 | |
| 1075 AutofillChangeList changes; | |
| 1076 changes.push_back(AutofillChange(AutofillChange::ADD, added_entry.key())); | |
| 1077 | |
| 1078 web_data_service_->OnAutofillEntriesChanged(changes); | |
| 1079 | |
| 1080 std::vector<AutofillEntry> new_sync_entries; | |
| 1081 std::vector<AutofillProfile> new_sync_profiles; | |
| 1082 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, | |
| 1083 &new_sync_profiles)); | |
| 1084 ASSERT_EQ(1U, new_sync_entries.size()); | |
| 1085 EXPECT_TRUE(added_entry == new_sync_entries[0]); | |
| 1086 } | |
| 1087 | |
| 1088 TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfile) { | |
| 1089 EXPECT_CALL(autofill_table_, GetAutofillProfiles(_)).WillOnce(Return(true)); | |
| 1090 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 1091 SetIdleChangeProcessorExpectations(); | |
| 1092 CreateRootHelper create_root(this, AUTOFILL_PROFILE); | |
| 1093 StartSyncService(create_root.callback(), false, AUTOFILL_PROFILE); | |
| 1094 ASSERT_TRUE(create_root.success()); | |
| 1095 | |
| 1096 AutofillProfile added_profile; | |
| 1097 autofill::test::SetProfileInfoWithGuid(&added_profile, | |
| 1098 "D6ADA912-D374-4C0A-917D-F5C8EBE43011", "Josephine", "Alicia", "Saenz", | |
| 1099 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", | |
| 1100 "32801", "US", "19482937549"); | |
| 1101 | |
| 1102 AutofillProfileChange change( | |
| 1103 AutofillProfileChange::ADD, added_profile.guid(), &added_profile); | |
| 1104 web_data_service_->OnAutofillProfileChanged(change); | |
| 1105 | |
| 1106 std::vector<AutofillProfile> new_sync_profiles; | |
| 1107 ASSERT_TRUE(GetAutofillProfilesFromSyncDBUnderProfileNode( | |
| 1108 &new_sync_profiles)); | |
| 1109 ASSERT_EQ(1U, new_sync_profiles.size()); | |
| 1110 EXPECT_EQ(0, added_profile.Compare(new_sync_profiles[0])); | |
| 1111 } | |
| 1112 | |
| 1113 TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateEntry) { | |
| 1114 AutofillEntry original_entry(MakeAutofillEntry("my", "entry", 1)); | |
| 1115 std::vector<AutofillEntry> original_entries; | |
| 1116 original_entries.push_back(original_entry); | |
| 1117 | |
| 1118 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)). | |
| 1119 WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true))); | |
| 1120 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 1121 CreateRootHelper create_root(this, AUTOFILL); | |
| 1122 StartSyncService(create_root.callback(), false, AUTOFILL); | |
| 1123 ASSERT_TRUE(create_root.success()); | |
| 1124 | |
| 1125 AutofillEntry updated_entry(MakeAutofillEntry("my", "entry", 1, 2)); | |
| 1126 | |
| 1127 EXPECT_CALL(autofill_table_, GetAutofillTimestamps(_, _, _, _)). | |
| 1128 WillOnce(DoAll(SetArgumentPointee<2>(updated_entry.date_created()), | |
| 1129 SetArgumentPointee<3>(updated_entry.date_last_used()), | |
| 1130 Return(true))); | |
| 1131 | |
| 1132 AutofillChangeList changes; | |
| 1133 changes.push_back(AutofillChange(AutofillChange::UPDATE, | |
| 1134 updated_entry.key())); | |
| 1135 web_data_service_->OnAutofillEntriesChanged(changes); | |
| 1136 | |
| 1137 std::vector<AutofillEntry> new_sync_entries; | |
| 1138 std::vector<AutofillProfile> new_sync_profiles; | |
| 1139 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, | |
| 1140 &new_sync_profiles)); | |
| 1141 ASSERT_EQ(1U, new_sync_entries.size()); | |
| 1142 EXPECT_TRUE(updated_entry == new_sync_entries[0]); | |
| 1143 } | |
| 1144 | |
| 1145 | |
| 1146 TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveEntry) { | |
| 1147 AutofillEntry original_entry(MakeAutofillEntry("my", "entry", 1)); | |
| 1148 std::vector<AutofillEntry> original_entries; | |
| 1149 original_entries.push_back(original_entry); | |
| 1150 | |
| 1151 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)). | |
| 1152 WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true))); | |
| 1153 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 1154 CreateRootHelper create_root(this, AUTOFILL); | |
| 1155 StartSyncService(create_root.callback(), false, AUTOFILL); | |
| 1156 ASSERT_TRUE(create_root.success()); | |
| 1157 | |
| 1158 AutofillChangeList changes; | |
| 1159 changes.push_back(AutofillChange(AutofillChange::REMOVE, | |
| 1160 original_entry.key())); | |
| 1161 web_data_service_->OnAutofillEntriesChanged(changes); | |
| 1162 | |
| 1163 std::vector<AutofillEntry> new_sync_entries; | |
| 1164 std::vector<AutofillProfile> new_sync_profiles; | |
| 1165 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, | |
| 1166 &new_sync_profiles)); | |
| 1167 ASSERT_EQ(0U, new_sync_entries.size()); | |
| 1168 } | |
| 1169 | |
| 1170 TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveProfile) { | |
| 1171 AutofillProfile sync_profile; | |
| 1172 autofill::test::SetProfileInfoWithGuid(&sync_profile, | |
| 1173 "3BA5FA1B-1EC4-4BB3-9B57-EC92BE3C1A09", "Josephine", "Alicia", "Saenz", | |
| 1174 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", | |
| 1175 "32801", "US", "19482937549"); | |
| 1176 AutofillProfile* native_profile = new AutofillProfile; | |
| 1177 autofill::test::SetProfileInfoWithGuid(native_profile, | |
| 1178 "3BA5FA1B-1EC4-4BB3-9B57-EC92BE3C1A09", "Josephine", "Alicia", "Saenz", | |
| 1179 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", | |
| 1180 "32801", "US", "19482937549"); | |
| 1181 | |
| 1182 std::vector<AutofillProfile*> native_profiles; | |
| 1183 native_profiles.push_back(native_profile); | |
| 1184 EXPECT_CALL(autofill_table_, GetAutofillProfiles(_)). | |
| 1185 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); | |
| 1186 | |
| 1187 std::vector<AutofillProfile> sync_profiles; | |
| 1188 sync_profiles.push_back(sync_profile); | |
| 1189 AddAutofillHelper<AutofillProfile> add_autofill(this, sync_profiles); | |
| 1190 EXPECT_CALL(*personal_data_manager_, Refresh()); | |
| 1191 StartSyncService(add_autofill.callback(), false, AUTOFILL_PROFILE); | |
| 1192 ASSERT_TRUE(add_autofill.success()); | |
| 1193 | |
| 1194 AutofillProfileChange change( | |
| 1195 AutofillProfileChange::REMOVE, sync_profile.guid(), NULL); | |
| 1196 web_data_service_->OnAutofillProfileChanged(change); | |
| 1197 | |
| 1198 std::vector<AutofillProfile> new_sync_profiles; | |
| 1199 ASSERT_TRUE(GetAutofillProfilesFromSyncDBUnderProfileNode( | |
| 1200 &new_sync_profiles)); | |
| 1201 ASSERT_EQ(0U, new_sync_profiles.size()); | |
| 1202 } | |
| 1203 | |
| 1204 TEST_F(ProfileSyncServiceAutofillTest, ServerChangeRace) { | |
| 1205 // Once for MergeDataAndStartSyncing() and twice for ProcessSyncChanges(), via | |
| 1206 // LoadAutofillData(). | |
| 1207 EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)). | |
| 1208 Times(3).WillRepeatedly(Return(true)); | |
| 1209 // On the other hand Autofill and Autocomplete are separated now, so | |
| 1210 // GetAutofillProfiles() should not be called. | |
| 1211 EXPECT_CALL(autofill_table_, GetAutofillProfiles(_)).Times(0); | |
| 1212 EXPECT_CALL(autofill_table_, UpdateAutofillEntries(_)). | |
| 1213 WillRepeatedly(Return(true)); | |
| 1214 EXPECT_CALL(*personal_data_manager_, Refresh()).Times(3); | |
| 1215 CreateRootHelper create_root(this, AUTOFILL); | |
| 1216 StartSyncService(create_root.callback(), false, AUTOFILL); | |
| 1217 ASSERT_TRUE(create_root.success()); | |
| 1218 | |
| 1219 // (true, false) means we have to reset after |Signal|, init to unsignaled. | |
| 1220 scoped_ptr<WaitableEvent> wait_for_start(new WaitableEvent(true, false)); | |
| 1221 scoped_ptr<WaitableEvent> wait_for_syncapi(new WaitableEvent(true, false)); | |
| 1222 scoped_refptr<FakeServerUpdater> updater(new FakeServerUpdater( | |
| 1223 sync_service_.get(), wait_for_start.get(), wait_for_syncapi.get(), | |
| 1224 data_type_thread_.task_runner())); | |
| 1225 | |
| 1226 // This server side update will stall waiting for CommitWaiter. | |
| 1227 updater->CreateNewEntry(MakeAutofillEntry("server", "entry", 1)); | |
| 1228 wait_for_start->Wait(); | |
| 1229 | |
| 1230 AutofillEntry syncapi_entry(MakeAutofillEntry("syncapi", "entry", 2)); | |
| 1231 ASSERT_TRUE(AddAutofillSyncNode(syncapi_entry)); | |
| 1232 DVLOG(1) << "Syncapi update finished."; | |
| 1233 | |
| 1234 // If we reach here, it means syncapi succeeded and we didn't deadlock. Yay! | |
| 1235 // Signal FakeServerUpdater that it can complete. | |
| 1236 wait_for_syncapi->Signal(); | |
| 1237 | |
| 1238 // Make another entry to ensure nothing broke afterwards and wait for finish | |
| 1239 // to clean up. | |
| 1240 updater->WaitForUpdateCompletion(); | |
| 1241 updater->CreateNewEntry(MakeAutofillEntry("server2", "entry2", 3)); | |
| 1242 updater->WaitForUpdateCompletion(); | |
| 1243 | |
| 1244 // Let callbacks posted on UI thread execute. | |
| 1245 base::RunLoop().RunUntilIdle(); | |
| 1246 | |
| 1247 std::vector<AutofillEntry> sync_entries; | |
| 1248 std::vector<AutofillProfile> sync_profiles; | |
| 1249 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); | |
| 1250 EXPECT_EQ(3U, sync_entries.size()); | |
| 1251 EXPECT_EQ(0U, sync_profiles.size()); | |
| 1252 for (size_t i = 0; i < sync_entries.size(); i++) { | |
| 1253 DVLOG(1) << "Entry " << i << ": " << sync_entries[i].key().name() | |
| 1254 << ", " << sync_entries[i].key().value(); | |
| 1255 } | |
| 1256 } | |
| OLD | NEW |