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 |