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