diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-15 14:18:00 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-15 14:00:37 +0000 |
commit | 66a2147d838e293f4a5db7711c8eba4e6faaaf0f (patch) | |
tree | 61ad99912355f5b6cc603d9b1dfadd77b950ce98 /chromium/components/password_manager/core | |
parent | da51f56cc21233c2d30f0fe0d171727c3102b2e0 (diff) | |
download | qtwebengine-chromium-66a2147d838e293f4a5db7711c8eba4e6faaaf0f.tar.gz |
BASELINE: Update Chromium to 65.0.3325.75
Change-Id: I5485bc5c111539356276457516584fa5737f07d8
Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/components/password_manager/core')
3 files changed, 63 insertions, 939 deletions
diff --git a/chromium/components/password_manager/core/browser/password_syncable_service.cc b/chromium/components/password_manager/core/browser/password_syncable_service.cc index 4653ac0cf8b..4f959a6ba44 100644 --- a/chromium/components/password_manager/core/browser/password_syncable_service.cc +++ b/chromium/components/password_manager/core/browser/password_syncable_service.cc @@ -12,12 +12,8 @@ #include "base/auto_reset.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" -#include "base/optional.h" -#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/time/default_clock.h" #include "components/autofill/core/common/password_form.h" -#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_store_sync.h" #include "components/sync/model/sync_error_factory.h" @@ -40,12 +36,20 @@ std::string MakePasswordSyncTag(const autofill::PasswordForm& password); namespace { // Returns true iff |password_specifics| and |password_specifics| are equal -// in the fields which don't comprise the sync tag. -bool AreLocalAndSyncPasswordsNonSyncTagEqual( +// memberwise. +bool AreLocalAndSyncPasswordsEqual( const sync_pb::PasswordSpecificsData& password_specifics, const autofill::PasswordForm& password_form) { return (password_form.scheme == password_specifics.scheme() && + password_form.signon_realm == password_specifics.signon_realm() && + password_form.origin.spec() == password_specifics.origin() && password_form.action.spec() == password_specifics.action() && + base::UTF16ToUTF8(password_form.username_element) == + password_specifics.username_element() && + base::UTF16ToUTF8(password_form.password_element) == + password_specifics.password_element() && + base::UTF16ToUTF8(password_form.username_value) == + password_specifics.username_value() && base::UTF16ToUTF8(password_form.password_value) == password_specifics.password_value() && password_form.preferred == password_specifics.preferred() && @@ -62,38 +66,6 @@ bool AreLocalAndSyncPasswordsNonSyncTagEqual( .Serialize() == password_form.federation_origin.Serialize()); } -// Returns true iff |password_specifics| and |password_specifics| are equal -// memberwise. -bool AreLocalAndSyncPasswordsEqual( - const sync_pb::PasswordSpecificsData& password_specifics, - const autofill::PasswordForm& password_form) { - return (password_form.signon_realm == password_specifics.signon_realm() && - password_form.origin.spec() == password_specifics.origin() && - base::UTF16ToUTF8(password_form.username_element) == - password_specifics.username_element() && - base::UTF16ToUTF8(password_form.password_element) == - password_specifics.password_element() && - base::UTF16ToUTF8(password_form.username_value) == - password_specifics.username_value() && - AreLocalAndSyncPasswordsNonSyncTagEqual(password_specifics, - password_form)); -} - -// Compares the fields which are not part of the sync tag. -bool AreNonSyncTagFieldsEqual(const sync_pb::PasswordSpecificsData& left, - const sync_pb::PasswordSpecificsData& right) { - return (left.scheme() == right.scheme() && left.action() == right.action() && - left.password_value() == right.password_value() && - left.preferred() == right.preferred() && - left.date_created() == right.date_created() && - left.blacklisted() == right.blacklisted() && - left.type() == right.type() && - left.times_used() == right.times_used() && - left.display_name() == right.display_name() && - left.avatar_url() == right.avatar_url() && - left.federation_url() == right.federation_url()); -} - syncer::SyncChange::SyncChangeType GetSyncChangeType( PasswordStoreChange::Type type) { switch (type) { @@ -119,190 +91,6 @@ void AppendPasswordFromSpecifics( entries->back()->date_synced = sync_time; } -// Android autofill saves credential in a different format without trailing '/'. -std::string GetIncorrectAndroidSignonRealm(std::string android_autofill_realm) { - if (base::EndsWith(android_autofill_realm, "/", base::CompareCase::SENSITIVE)) - android_autofill_realm.erase(android_autofill_realm.size() - 1); - return android_autofill_realm; -} - -// The correct Android signon_realm should have a trailing '/'. -std::string GetCorrectAndroidSignonRealm(std::string android_realm) { - if (!base::EndsWith(android_realm, "/", base::CompareCase::SENSITIVE)) - android_realm += '/'; - return android_realm; -} - -// Android autofill saves credentials in a different format without trailing -// '/'. Return a sync tag for the style used by Android Autofill in GMS Core -// v12. -std::string AndroidAutofillSyncTag( - const sync_pb::PasswordSpecificsData& password) { - // realm has the same value as the origin. - std::string origin = GetIncorrectAndroidSignonRealm(password.origin()); - std::string signon_realm = - GetIncorrectAndroidSignonRealm(password.signon_realm()); - return (net::EscapePath(origin) + "|" + - net::EscapePath(password.username_element()) + "|" + - net::EscapePath(password.username_value()) + "|" + - net::EscapePath(password.password_element()) + "|" + - net::EscapePath(signon_realm)); -} - -// Return a sync tag for the correct format used by Android. -std::string AndroidCorrectSyncTag( - const sync_pb::PasswordSpecificsData& password) { - // realm has the same value as the origin. - std::string origin = GetCorrectAndroidSignonRealm(password.origin()); - std::string signon_realm = - GetCorrectAndroidSignonRealm(password.signon_realm()); - return (net::EscapePath(origin) + "|" + - net::EscapePath(password.username_element()) + "|" + - net::EscapePath(password.username_value()) + "|" + - net::EscapePath(password.password_element()) + "|" + - net::EscapePath(signon_realm)); -} - -void PasswordSpecificsFromPassword( - const autofill::PasswordForm& password_form, - sync_pb::PasswordSpecificsData* password_specifics) { -#define CopyField(field) password_specifics->set_##field(password_form.field) -#define CopyStringField(field) \ - password_specifics->set_##field(base::UTF16ToUTF8(password_form.field)) - CopyField(scheme); - CopyField(signon_realm); - password_specifics->set_origin(password_form.origin.spec()); - password_specifics->set_action(password_form.action.spec()); - CopyStringField(username_element); - CopyStringField(password_element); - CopyStringField(username_value); - CopyStringField(password_value); - CopyField(preferred); - password_specifics->set_date_created( - password_form.date_created.ToInternalValue()); - password_specifics->set_blacklisted(password_form.blacklisted_by_user); - CopyField(type); - CopyField(times_used); - CopyStringField(display_name); - password_specifics->set_avatar_url(password_form.icon_url.spec()); - password_specifics->set_federation_url( - password_form.federation_origin.unique() - ? std::string() - : password_form.federation_origin.Serialize()); -#undef CopyStringField -#undef CopyField -} - -struct AndroidMergeResult { - // New value for Android entry in the correct format. - base::Optional<syncer::SyncData> new_android_correct; - // New value for Android autofill entry. - base::Optional<syncer::SyncData> new_android_incorrect; - // New value for local entry in the correct format. - base::Optional<autofill::PasswordForm> new_local_correct; - // New value for local entry in the Android autofill format. - base::Optional<autofill::PasswordForm> new_local_incorrect; -}; - -// Perform deduplication of Android credentials saved in the wrong format. As -// the result all the four entries should be created and have the same value. -AndroidMergeResult Perform4WayMergeAndroidCredentials( - const sync_pb::PasswordSpecificsData* correct_android, - const sync_pb::PasswordSpecificsData* incorrect_android, - const autofill::PasswordForm* correct_local, - const autofill::PasswordForm* incorrect_local) { - AndroidMergeResult result; - - base::Optional<sync_pb::PasswordSpecificsData> local_correct_ps; - if (correct_local) { - local_correct_ps = sync_pb::PasswordSpecificsData(); - PasswordSpecificsFromPassword(*correct_local, &local_correct_ps.value()); - } - - base::Optional<sync_pb::PasswordSpecificsData> local_incorrect_ps; - if (incorrect_local) { - local_incorrect_ps = sync_pb::PasswordSpecificsData(); - PasswordSpecificsFromPassword(*incorrect_local, - &local_incorrect_ps.value()); - } - - const sync_pb::PasswordSpecificsData* all_data[4] = { - correct_android, incorrect_android, - local_correct_ps ? &local_correct_ps.value() : nullptr, - local_incorrect_ps ? &local_incorrect_ps.value() : nullptr}; - - // |newest_data| will point to the newest entry out of all 4. - const sync_pb::PasswordSpecificsData* newest_data = nullptr; - for (int i = 0; i < 4; ++i) { - if (newest_data && all_data[i]) { - if (all_data[i]->date_created() > newest_data->date_created()) - newest_data = all_data[i]; - } else if (all_data[i]) { - newest_data = all_data[i]; - } - } - DCHECK(newest_data); - - const std::string correct_tag = AndroidCorrectSyncTag(*newest_data); - const std::string incorrect_tag = AndroidAutofillSyncTag(*newest_data); - const std::string correct_signon_realm = - GetCorrectAndroidSignonRealm(newest_data->signon_realm()); - const std::string incorrect_signon_realm = - GetIncorrectAndroidSignonRealm(newest_data->signon_realm()); - const std::string correct_origin = - GetCorrectAndroidSignonRealm(newest_data->origin()); - const std::string incorrect_origin = - GetIncorrectAndroidSignonRealm(newest_data->origin()); - DCHECK_EQ(GURL(incorrect_origin).spec(), incorrect_origin); - - // Set the correct Sync entry if needed. - if (newest_data != correct_android && - (!correct_android || - !AreNonSyncTagFieldsEqual(*correct_android, *newest_data))) { - sync_pb::EntitySpecifics password_data; - sync_pb::PasswordSpecificsData* password_specifics = - password_data.mutable_password()->mutable_client_only_encrypted_data(); - *password_specifics = *newest_data; - password_specifics->set_origin(correct_origin); - password_specifics->set_signon_realm(correct_signon_realm); - result.new_android_correct = syncer::SyncData::CreateLocalData( - correct_tag, correct_tag, password_data); - } - - // Set the Andoroid Autofill Sync entry if needed. - if (newest_data != incorrect_android && - (!incorrect_android || - !AreNonSyncTagFieldsEqual(*incorrect_android, *newest_data))) { - sync_pb::EntitySpecifics password_data; - sync_pb::PasswordSpecificsData* password_specifics = - password_data.mutable_password()->mutable_client_only_encrypted_data(); - *password_specifics = *newest_data; - password_specifics->set_origin(incorrect_origin); - password_specifics->set_signon_realm(incorrect_signon_realm); - result.new_android_incorrect = syncer::SyncData::CreateLocalData( - incorrect_tag, incorrect_tag, password_data); - } - - // Set the correct local entry if needed. - if (!local_correct_ps || - (newest_data != &local_correct_ps.value() && - !AreNonSyncTagFieldsEqual(local_correct_ps.value(), *newest_data))) { - result.new_local_correct = PasswordFromSpecifics(*newest_data); - result.new_local_correct.value().origin = GURL(correct_origin); - result.new_local_correct.value().signon_realm = correct_signon_realm; - } - - // Set the incorrect local entry if needed. - if (!local_incorrect_ps || - (newest_data != &local_incorrect_ps.value() && - !AreNonSyncTagFieldsEqual(local_incorrect_ps.value(), *newest_data))) { - result.new_local_incorrect = PasswordFromSpecifics(*newest_data); - result.new_local_incorrect.value().origin = GURL(incorrect_origin); - result.new_local_incorrect.value().signon_realm = incorrect_signon_realm; - } - return result; -} - } // namespace struct PasswordSyncableService::SyncEntries { @@ -336,9 +124,8 @@ struct PasswordSyncableService::SyncEntries { PasswordSyncableService::PasswordSyncableService( PasswordStoreSync* password_store) - : password_store_(password_store), - clock_(new base::DefaultClock), - is_processing_sync_changes_(false) {} + : password_store_(password_store), is_processing_sync_changes_(false) { +} PasswordSyncableService::~PasswordSyncableService() = default; @@ -374,12 +161,17 @@ syncer::SyncMergeResult PasswordSyncableService::MergeDataAndStartSyncing( } merge_result.set_num_items_before_association(new_local_entries.size()); - // Changes from Sync to be applied locally. SyncEntries sync_entries; // Changes from password db that need to be propagated to sync. syncer::SyncChangeList updated_db_entries; - MergeSyncDataWithLocalData(initial_sync_data, &new_local_entries, - &sync_entries, &updated_db_entries); + for (syncer::SyncDataList::const_iterator sync_iter = + initial_sync_data.begin(); + sync_iter != initial_sync_data.end(); ++sync_iter) { + CreateOrUpdateEntry(*sync_iter, + &new_local_entries, + &sync_entries, + &updated_db_entries); + } for (PasswordEntryMap::iterator it = new_local_entries.begin(); it != new_local_entries.end(); ++it) { @@ -443,7 +235,7 @@ syncer::SyncError PasswordSyncableService::ProcessSyncChanges( DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::AutoReset<bool> processing_changes(&is_processing_sync_changes_, true); SyncEntries sync_entries; - base::Time time_now = clock_->Now(); + base::Time time_now = base::Time::Now(); for (syncer::SyncChangeList::const_iterator it = change_list.begin(); it != change_list.end(); ++it) { @@ -456,13 +248,6 @@ syncer::SyncError PasswordSyncableService::ProcessSyncChanges( } AppendPasswordFromSpecifics( specifics.password().client_only_encrypted_data(), time_now, entries); - if (IsValidAndroidFacetURI(entries->back()->signon_realm)) { - // Fix the Android Autofill credentials if needed. - entries->back()->signon_realm = - GetCorrectAndroidSignonRealm(entries->back()->signon_realm); - entries->back()->origin = - GURL(GetCorrectAndroidSignonRealm(entries->back()->origin.spec())); - } } WriteToPasswordStore(sync_entries); @@ -553,132 +338,21 @@ void PasswordSyncableService::WriteToPasswordStore(const SyncEntries& entries) { password_store_->NotifyLoginsChanged(changes); } -void PasswordSyncableService::MergeSyncDataWithLocalData( - const syncer::SyncDataList& sync_data, - PasswordEntryMap* unmatched_data_from_password_db, - SyncEntries* sync_entries, - syncer::SyncChangeList* updated_db_entries) { - std::map<std::string, const sync_pb::PasswordSpecificsData*> sync_data_map; - for (const auto& data : sync_data) { - const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); - const sync_pb::PasswordSpecificsData* password_specifics = - &specifics.password().client_only_encrypted_data(); - sync_data_map[MakePasswordSyncTag(*password_specifics)] = - password_specifics; - } - DCHECK_EQ(sync_data_map.size(), sync_data.size()); - - for (auto it = sync_data_map.begin(); it != sync_data_map.end();) { - if (IsValidAndroidFacetURI(it->second->signon_realm())) { - // Perform deduplication of Android credentials saved in the wrong format. - // For each incorrect entry, a duplicate of it is created in the correct - // format, so Chrome can make use of it. The incorrect sync entries are - // not deleted for now. - std::string incorrect_tag = AndroidAutofillSyncTag(*it->second); - std::string correct_tag = AndroidCorrectSyncTag(*it->second); - auto it_sync_incorrect = sync_data_map.find(incorrect_tag); - auto it_sync_correct = sync_data_map.find(correct_tag); - auto it_local_data_correct = - unmatched_data_from_password_db->find(correct_tag); - auto it_local_data_incorrect = - unmatched_data_from_password_db->find(incorrect_tag); - if ((it != it_sync_incorrect && it != it_sync_correct) || - (it_sync_incorrect == sync_data_map.end() && - it_local_data_incorrect == unmatched_data_from_password_db->end())) { - // The current credential is in an unexpected format or incorrect - // credential don't exist. Just do what Sync would normally do. - CreateOrUpdateEntry(*it->second, unmatched_data_from_password_db, - sync_entries, updated_db_entries); - ++it; - } else { - AndroidMergeResult result = Perform4WayMergeAndroidCredentials( - it_sync_correct == sync_data_map.end() ? nullptr - : it_sync_correct->second, - it_sync_incorrect == sync_data_map.end() - ? nullptr - : it_sync_incorrect->second, - it_local_data_correct == unmatched_data_from_password_db->end() - ? nullptr - : it_local_data_correct->second, - it_local_data_incorrect == unmatched_data_from_password_db->end() - ? nullptr - : it_local_data_incorrect->second); - // Add or update the correct local entry. - if (result.new_local_correct) { - auto* local_changes = sync_entries->EntriesForChangeType( - it_local_data_correct == unmatched_data_from_password_db->end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE); - local_changes->push_back(std::make_unique<autofill::PasswordForm>( - result.new_local_correct.value())); - local_changes->back()->date_synced = clock_->Now(); - } - // Add or update the incorrect local entry. - if (result.new_local_incorrect) { - auto* local_changes = sync_entries->EntriesForChangeType( - it_local_data_incorrect == unmatched_data_from_password_db->end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE); - local_changes->push_back(std::make_unique<autofill::PasswordForm>( - result.new_local_incorrect.value())); - local_changes->back()->date_synced = clock_->Now(); - } - if (it_local_data_correct != unmatched_data_from_password_db->end()) - unmatched_data_from_password_db->erase(it_local_data_correct); - if (it_local_data_incorrect != unmatched_data_from_password_db->end()) - unmatched_data_from_password_db->erase(it_local_data_incorrect); - // Add or update the correct sync entry. - if (result.new_android_correct) { - updated_db_entries->push_back( - syncer::SyncChange(FROM_HERE, - it_sync_correct == sync_data_map.end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE, - result.new_android_correct.value())); - } - // Add or update the Android Autofill sync entry. - if (result.new_android_incorrect) { - updated_db_entries->push_back( - syncer::SyncChange(FROM_HERE, - it_sync_incorrect == sync_data_map.end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE, - result.new_android_incorrect.value())); - } - bool increment = true; - for (auto sync_data_it : {it_sync_incorrect, it_sync_correct}) { - if (sync_data_it != sync_data_map.end()) { - if (sync_data_it == it) { - it = sync_data_map.erase(it); - increment = false; - } else { - sync_data_map.erase(sync_data_it); - } - } - } - if (increment) - ++it; - } - } else { - // Not Android. - CreateOrUpdateEntry(*it->second, unmatched_data_from_password_db, - sync_entries, updated_db_entries); - ++it; - } - } -} - +// static void PasswordSyncableService::CreateOrUpdateEntry( - const sync_pb::PasswordSpecificsData& password_specifics, + const syncer::SyncData& data, PasswordEntryMap* unmatched_data_from_password_db, SyncEntries* sync_entries, syncer::SyncChangeList* updated_db_entries) { + const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); + const sync_pb::PasswordSpecificsData& password_specifics( + specifics.password().client_only_encrypted_data()); std::string tag = MakePasswordSyncTag(password_specifics); // Check whether the data from sync is already in the password store. PasswordEntryMap::iterator existing_local_entry_iter = unmatched_data_from_password_db->find(tag); - base::Time time_now = clock_->Now(); + base::Time time_now = base::Time::Now(); if (existing_local_entry_iter == unmatched_data_from_password_db->end()) { // The sync data is not in the password store, so we need to create it in // the password store. Add the entry to the new_entries list. @@ -726,7 +400,31 @@ syncer::SyncData SyncDataFromPassword( sync_pb::EntitySpecifics password_data; sync_pb::PasswordSpecificsData* password_specifics = password_data.mutable_password()->mutable_client_only_encrypted_data(); - PasswordSpecificsFromPassword(password_form, password_specifics); +#define CopyField(field) password_specifics->set_##field(password_form.field) +#define CopyStringField(field) \ + password_specifics->set_##field(base::UTF16ToUTF8(password_form.field)) + CopyField(scheme); + CopyField(signon_realm); + password_specifics->set_origin(password_form.origin.spec()); + password_specifics->set_action(password_form.action.spec()); + CopyStringField(username_element); + CopyStringField(password_element); + CopyStringField(username_value); + CopyStringField(password_value); + CopyField(preferred); + password_specifics->set_date_created( + password_form.date_created.ToInternalValue()); + password_specifics->set_blacklisted(password_form.blacklisted_by_user); + CopyField(type); + CopyField(times_used); + CopyStringField(display_name); + password_specifics->set_avatar_url(password_form.icon_url.spec()); + password_specifics->set_federation_url( + password_form.federation_origin.unique() + ? std::string() + : password_form.federation_origin.Serialize()); +#undef CopyStringField +#undef CopyField std::string tag = MakePasswordSyncTag(*password_specifics); return syncer::SyncData::CreateLocalData(tag, tag, password_data); diff --git a/chromium/components/password_manager/core/browser/password_syncable_service.h b/chromium/components/password_manager/core/browser/password_syncable_service.h index e2fd572c4fb..d86daac1974 100644 --- a/chromium/components/password_manager/core/browser/password_syncable_service.h +++ b/chromium/components/password_manager/core/browser/password_syncable_service.h @@ -11,7 +11,6 @@ #include "base/macros.h" #include "base/sequence_checker.h" -#include "base/time/clock.h" #include "components/password_manager/core/browser/password_store_change.h" #include "components/sync/model/sync_change.h" #include "components/sync/model/sync_data.h" @@ -61,12 +60,6 @@ class PasswordSyncableService : public syncer::SyncableService { void InjectStartSyncFlare( const syncer::SyncableService::StartSyncFlare& flare); -#if defined(UNIT_TEST) - void set_clock(std::unique_ptr<base::Clock> clock) { - clock_ = std::move(clock); - } -#endif - private: // Map from password sync tag to password form. typedef std::map<std::string, autofill::PasswordForm*> PasswordEntryMap; @@ -87,23 +80,14 @@ class PasswordSyncableService : public syncer::SyncableService { // Uses the |PasswordStore| APIs to change entries. void WriteToPasswordStore(const SyncEntries& entries); - // Goes through |sync_data| and for each entry merges the data with - // |unmatched_data_from_password_db|. The result of merge is recorded in - // |sync_entries| or |updated_db_entries|. Successfully merged elements are - // removed from |unmatched_data_from_password_db|. - void MergeSyncDataWithLocalData( - const syncer::SyncDataList& sync_data, - PasswordEntryMap* unmatched_data_from_password_db, - SyncEntries* sync_entries, - syncer::SyncChangeList* updated_db_entries); - // Examines |data|, an entry in sync db, and updates |sync_entries| or // |updated_db_entries| accordingly. An element is removed from // |unmatched_data_from_password_db| if its tag is identical to |data|'s. - void CreateOrUpdateEntry(const sync_pb::PasswordSpecificsData& data, - PasswordEntryMap* unmatched_data_from_password_db, - SyncEntries* sync_entries, - syncer::SyncChangeList* updated_db_entries); + static void CreateOrUpdateEntry( + const syncer::SyncData& data, + PasswordEntryMap* unmatched_data_from_password_db, + SyncEntries* sync_entries, + syncer::SyncChangeList* updated_db_entries); // Calls |operation| for each element in |entries| and appends the changes to // |all_changes|. @@ -125,9 +109,6 @@ class PasswordSyncableService : public syncer::SyncableService { // A signal activated by this class to start sync as soon as possible. syncer::SyncableService::StartSyncFlare flare_; - // Clock for date_synced updates. - std::unique_ptr<base::Clock> clock_; - // True if processing sync changes is in progress. bool is_processing_sync_changes_; diff --git a/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc b/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc index 9f1975d0895..39c4499a730 100644 --- a/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc +++ b/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc @@ -15,9 +15,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" -#include "base/test/simple_test_clock.h" #include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/sync/model/sync_change_processor.h" #include "components/sync/model/sync_error.h" #include "components/sync/model/sync_error_factory_mock.h" @@ -54,8 +52,6 @@ namespace { // PasswordForm values for tests. constexpr autofill::PasswordForm::Type kArbitraryType = autofill::PasswordForm::TYPE_GENERATED; -constexpr char kAndroidAutofillRealm[] = "android://hash@com.magisto"; -constexpr char kAndroidCorrectRealm[] = "android://hash@com.magisto/"; constexpr char kIconUrl[] = "https://fb.com/Icon"; constexpr char kDisplayName[] = "Agent Smith"; constexpr char kFederationUrl[] = "https://fb.com/"; @@ -73,8 +69,8 @@ const sync_pb::PasswordSpecificsData& GetPasswordSpecifics( return sync_data.GetSpecifics().password().client_only_encrypted_data(); } -MATCHER_P(HasDateSynced, time, "") { - return arg.date_synced == time; +MATCHER(HasDateSynced, "") { + return !arg.date_synced.is_null() && !arg.date_synced.is_max(); } MATCHER_P(PasswordIs, form, "") { @@ -127,14 +123,6 @@ ACTION_P(AppendForm, form) { return true; } -// The argument is std::vector<autofill::PasswordForm*>*. The caller is -// responsible for the lifetime of all the password forms. -ACTION_P(AppendForms, forms) { - for (const autofill::PasswordForm& form : forms) - arg0->push_back(std::make_unique<autofill::PasswordForm>(form)); - return true; -} - // Creates a sync data consisting of password specifics. The sign on realm is // set to |signon_realm|. SyncData CreateSyncData(const std::string& signon_realm) { @@ -185,14 +173,12 @@ class PasswordSyncableServiceWrapper { password_store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr); service_.reset( new PasswordSyncableService(password_store_->GetSyncInterface())); - auto clock = std::make_unique<base::SimpleTestClock>(); - clock->SetNow(time()); - service_->set_clock(std::move(clock)); - ON_CALL(*password_store_, AddLoginImpl(HasDateSynced(time()))) + + ON_CALL(*password_store_, AddLoginImpl(HasDateSynced())) .WillByDefault(Return(PasswordStoreChangeList())); ON_CALL(*password_store_, RemoveLoginImpl(_)) .WillByDefault(Return(PasswordStoreChangeList())); - ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced(time()))) + ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced())) .WillByDefault(Return(PasswordStoreChangeList())); EXPECT_CALL(*password_store(), NotifyLoginsChanged(_)).Times(AnyNumber()); } @@ -203,8 +189,6 @@ class PasswordSyncableServiceWrapper { PasswordSyncableService* service() { return service_.get(); } - static base::Time time() { return base::Time::FromInternalValue(100000); } - // Returnes the scoped_ptr to |service_| thus NULLing out it. std::unique_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() { return std::move(service_); @@ -233,6 +217,7 @@ class PasswordSyncableServiceTest : public testing::Test { std::unique_ptr<MockSyncChangeProcessor> processor_; private: + // Used by the password store. base::test::ScopedTaskEnvironment scoped_task_environment_; PasswordSyncableServiceWrapper wrapper_; }; @@ -677,546 +662,6 @@ TEST_F(PasswordSyncableServiceTest, SerializeNonEmptyPasswordForm) { EXPECT_EQ("https://google.com", specifics.federation_url()); } -// Tests for Android Autofill credentials. Those are saved in the wrong format -// without trailing '/'. Nevertheless, password store should always contain the -// correct values. -class PasswordSyncableServiceAndroidAutofillTest : public testing::Test { - public: - PasswordSyncableServiceAndroidAutofillTest() = default; - - static PasswordFormData android_incorrect(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidAutofillRealm, - kAndroidAutofillRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"11111", - true, - creation_time}; - return data; - } - - static PasswordFormData android_correct(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidCorrectRealm, - kAndroidCorrectRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"22222", - true, - creation_time}; - return data; - } - - static PasswordFormData android_incorrect2(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidAutofillRealm, - kAndroidAutofillRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"33333", - false, - creation_time}; - return data; - } - - static PasswordFormData android_correct2(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidCorrectRealm, - kAndroidCorrectRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"444444", - false, - creation_time}; - return data; - } - - static autofill::PasswordForm FormWithCorrectTag(PasswordFormData data) { - autofill::PasswordForm form = *FillPasswordFormWithData(data); - form.signon_realm = kAndroidCorrectRealm; - form.origin = GURL(kAndroidCorrectRealm); - form.date_synced = PasswordSyncableServiceWrapper::time(); - return form; - } - - static autofill::PasswordForm FormWithAndroidAutofillTag( - PasswordFormData data) { - autofill::PasswordForm form = *FillPasswordFormWithData(data); - form.signon_realm = kAndroidAutofillRealm; - form.origin = GURL(kAndroidAutofillRealm); - form.date_synced = PasswordSyncableServiceWrapper::time(); - return form; - } - - // Transforms |val| into |count| numbers from 1 to |count| inclusive. - static std::vector<unsigned> ExtractTimestamps(unsigned val, unsigned count) { - std::vector<unsigned> result; - for (unsigned i = 0; i < count; ++i) { - result.push_back(val % count + 1); - val /= count; - } - return result; - } - - static testing::Message FormDataMessage(const std::string& prefix, - const PasswordFormData* data) { - testing::Message message; - message << prefix; - if (data) - message << *FillPasswordFormWithData(*data); - else - message << "NULL"; - return message; - } - - protected: - base::test::ScopedTaskEnvironment scoped_task_environment_; -}; - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, FourWayMerge) { - for (unsigned val = 0; val < 4 * 4 * 4 * 4; ++val) { - // Generate 4 creation timestamps for all the entries. - std::vector<unsigned> dates = ExtractTimestamps(val, 4); - ASSERT_EQ(4u, dates.size()); - const unsigned latest = *std::max_element(dates.begin(), dates.end()); - // Sync correct, Sync Android autofill, local correct, local incorrect. - const PasswordFormData data[4] = { - android_correct(dates[0]), android_incorrect(dates[1]), - android_correct2(dates[2]), android_incorrect2(dates[3])}; - const PasswordFormData* latest_data = - std::find_if(data, data + 4, [latest](const PasswordFormData& data) { - return data.creation_time == latest; - }); - ASSERT_TRUE(latest_data); - std::vector<autofill::PasswordForm> expected_sync_updates; - if (latest_data != &data[0]) - expected_sync_updates.push_back(FormWithCorrectTag(*latest_data)); - if (latest_data != &data[1]) - expected_sync_updates.push_back(FormWithAndroidAutofillTag(*latest_data)); - autofill::PasswordForm local_correct = *FillPasswordFormWithData(data[2]); - autofill::PasswordForm local_incorrect = *FillPasswordFormWithData(data[3]); - syncer::SyncData sync_correct = - SyncDataFromPassword(*FillPasswordFormWithData(data[0])); - syncer::SyncData sync_incorrect = - SyncDataFromPassword(*FillPasswordFormWithData(data[1])); - - SCOPED_TRACE(*FillPasswordFormWithData(data[0])); - SCOPED_TRACE(*FillPasswordFormWithData(data[1])); - SCOPED_TRACE(*FillPasswordFormWithData(data[2])); - SCOPED_TRACE(*FillPasswordFormWithData(data[3])); - - for (bool correct_sync_first : {true, false}) { - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - std::vector<autofill::PasswordForm> stored_forms = {local_correct, - local_incorrect}; - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForms(stored_forms)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - if (latest_data != &data[2]) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithCorrectTag(*latest_data))); - } - if (latest_data != &data[3]) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithAndroidAutofillTag(*latest_data))); - } - - if (expected_sync_updates.size() == 1) { - EXPECT_CALL(*processor, - ProcessSyncChanges(_, ElementsAre(SyncChangeIs( - SyncChange::ACTION_UPDATE, - expected_sync_updates[0])))); - } else { - EXPECT_CALL( - *processor, - ProcessSyncChanges(_, UnorderedElementsAre( - SyncChangeIs(SyncChange::ACTION_UPDATE, - expected_sync_updates[0]), - SyncChangeIs(SyncChange::ACTION_UPDATE, - expected_sync_updates[1])))); - } - - SyncDataList sync_list = {sync_correct, sync_incorrect}; - if (!correct_sync_first) - std::swap(sync_list[0], sync_list[1]); - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, ThreeWayMerge) { - for (int j = 0; j < 4; ++j) { - // Whether the entry exists: Sync correct, Sync Android autofill, - // local correct, local incorrect. - bool entry_present[4] = {true, true, true, true}; - entry_present[j] = false; - for (unsigned val = 0; val < 3 * 3 * 3; ++val) { - // Generate 3 creation timestamps for all the entries. - std::vector<unsigned> dates = ExtractTimestamps(val, 3); - ASSERT_EQ(3u, dates.size()); - const unsigned latest = *std::max_element(dates.begin(), dates.end()); - - // Sync correct, Sync Android autofill, local correct, local incorrect. - std::vector<std::unique_ptr<PasswordFormData>> data; - int date_index = 0; - data.push_back(entry_present[0] - ? std::make_unique<PasswordFormData>( - android_correct(dates[date_index++])) - : nullptr); - data.push_back(entry_present[1] - ? std::make_unique<PasswordFormData>( - android_incorrect(dates[date_index++])) - : nullptr); - data.push_back(entry_present[2] - ? std::make_unique<PasswordFormData>( - android_correct2(dates[date_index++])) - : nullptr); - data.push_back(entry_present[3] - ? std::make_unique<PasswordFormData>( - android_incorrect2(dates[date_index++])) - : nullptr); - - SCOPED_TRACE(val); - SCOPED_TRACE(j); - SCOPED_TRACE(FormDataMessage("data[0]=", data[0].get())); - SCOPED_TRACE(FormDataMessage("data[1]=", data[1].get())); - SCOPED_TRACE(FormDataMessage("data[2]=", data[2].get())); - SCOPED_TRACE(FormDataMessage("data[3]=", data[3].get())); - - const PasswordFormData* latest_data = - std::find_if(data.begin(), data.end(), - [latest](const std::unique_ptr<PasswordFormData>& data) { - return data && data->creation_time == latest; - }) - ->get(); - ASSERT_TRUE(latest_data); - std::vector<std::pair<SyncChange::SyncChangeType, autofill::PasswordForm>> - expected_sync_updates; - for (int i = 0; i < 2; ++i) { - if (latest_data != data[i].get()) { - expected_sync_updates.push_back(std::make_pair( - data[i] ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD, - i == 0 ? FormWithCorrectTag(*latest_data) - : FormWithAndroidAutofillTag(*latest_data))); - } - } - - std::vector<autofill::PasswordForm> stored_forms; - for (int i = 2; i < 4; ++i) { - if (data[i]) - stored_forms.push_back(*FillPasswordFormWithData(*data[i])); - } - - SyncDataList sync_list; - for (int i = 0; i < 2; ++i) { - if (data[i]) { - sync_list.push_back( - SyncDataFromPassword(*FillPasswordFormWithData(*data[i]))); - } - } - - for (bool swap_sync_list : {false, true}) { - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForms(stored_forms)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - for (int i = 2; i < 4; ++i) { - if (latest_data != data[i].get()) { - autofill::PasswordForm latest_form = - i == 2 ? FormWithCorrectTag(*latest_data) - : FormWithAndroidAutofillTag(*latest_data); - if (data[i]) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(latest_form)); - } else { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(latest_form)); - } - } - } - - if (expected_sync_updates.size() == 0) { - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - } else if (expected_sync_updates.size() == 1) { - EXPECT_CALL( - *processor, - ProcessSyncChanges(_, ElementsAre(SyncChangeIs( - expected_sync_updates[0].first, - expected_sync_updates[0].second)))); - } else if (expected_sync_updates.size() == 2) { - EXPECT_CALL( - *processor, - ProcessSyncChanges( - _, UnorderedElementsAre( - SyncChangeIs(expected_sync_updates[0].first, - expected_sync_updates[0].second), - SyncChangeIs(expected_sync_updates[1].first, - expected_sync_updates[1].second)))); - } - - if (swap_sync_list && sync_list.size() == 2) - std::swap(sync_list[0], sync_list[1]); - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations - // on it are checked. - scoped_task_environment_.RunUntilIdle(); - } - } - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, TwoWayServerAndLocalMerge) { - for (unsigned i = 0; i < 2 * 2; ++i) { - // Generate 4 different combinations for local/server entries. - std::vector<unsigned> combination = ExtractTimestamps(i, 2); - ASSERT_EQ(2u, combination.size()); - const bool sync_data_correct = !!combination[0]; - const bool local_data_correct = !!combination[1]; - - for (unsigned val = 0; val < 2 * 2; ++val) { - std::vector<unsigned> dates = ExtractTimestamps(val, 2); - ASSERT_EQ(2u, dates.size()); - - const PasswordFormData sync_data = sync_data_correct - ? android_correct(dates[0]) - : android_incorrect(dates[0]); - const PasswordFormData local_data = local_data_correct - ? android_correct2(dates[1]) - : android_incorrect2(dates[1]); - - const PasswordFormData* latest_data = - dates[1] > dates[0] ? &local_data : &sync_data; - - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForm(*FillPasswordFormWithData(local_data))); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - if (!local_data_correct || latest_data == &sync_data) { - if (local_data_correct) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithCorrectTag(*latest_data))); - } else { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithCorrectTag(*latest_data))); - } - } - if (!local_data_correct && latest_data == &sync_data) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithAndroidAutofillTag(*latest_data))); - } else if (local_data_correct && !sync_data_correct) { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithAndroidAutofillTag(*latest_data))); - } - - std::vector<std::pair<SyncChange::SyncChangeType, autofill::PasswordForm>> - expected_sync_updates; - // Deal with the correct sync entry and incorrect one. - if (sync_data_correct) { - if (latest_data != &sync_data) { - expected_sync_updates.push_back(std::make_pair( - SyncChange::ACTION_UPDATE, FormWithCorrectTag(*latest_data))); - } - if (!local_data_correct) { - expected_sync_updates.push_back( - std::make_pair(SyncChange::ACTION_ADD, - FormWithAndroidAutofillTag(*latest_data))); - } - } else { - expected_sync_updates.push_back(std::make_pair( - SyncChange::ACTION_ADD, FormWithCorrectTag(*latest_data))); - if (latest_data != &sync_data) { - expected_sync_updates.push_back( - std::make_pair(SyncChange::ACTION_UPDATE, - FormWithAndroidAutofillTag(*latest_data))); - } - } - - // Set expectation on |processor|. - if (expected_sync_updates.size() == 0) { - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - } else if (expected_sync_updates.size() == 1) { - EXPECT_CALL( - *processor, - ProcessSyncChanges( - _, ElementsAre(SyncChangeIs(expected_sync_updates[0].first, - expected_sync_updates[0].second)))); - } else if (expected_sync_updates.size() == 2) { - EXPECT_CALL(*processor, - ProcessSyncChanges( - _, UnorderedElementsAre( - SyncChangeIs(expected_sync_updates[0].first, - expected_sync_updates[0].second), - SyncChangeIs(expected_sync_updates[1].first, - expected_sync_updates[1].second)))); - } - - SyncDataList sync_list = { - SyncDataFromPassword(*FillPasswordFormWithData(sync_data))}; - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, OneEntryOnly) { - for (int i = 0; i < 3; ++i) { - // The case when only local incorrect entry exists is excluded. It's very - // exotic because a local incorrect entry can come only from the server. - // In such a case a copy will be uploaded to the server and next - // MergeDataAndStartSyncing will do a proper migration. - SCOPED_TRACE(i); - // Whether the entry exists: Sync correct, Sync Android autofill, - // local correct, local incorrect. - const bool entry_is_correct = i == 0 || i == 2; - const bool entry_is_local = i >= 2; - PasswordFormData data = - entry_is_correct ? android_correct(100) : android_incorrect(100); - - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - if (entry_is_local) { - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForm(*FillPasswordFormWithData(data))); - } else { - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(Return(true)); - } - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - if (!entry_is_local && !entry_is_correct) { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithAndroidAutofillTag(data))); - } - if (!entry_is_local) { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithCorrectTag(data))); - } - - if (entry_is_correct && !entry_is_local) { - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - } else { - EXPECT_CALL(*processor, - ProcessSyncChanges( - _, ElementsAre(SyncChangeIs(SyncChange::ACTION_ADD, - FormWithCorrectTag(data))))); - } - - SyncDataList sync_list; - if (!entry_is_local) { - sync_list.push_back( - SyncDataFromPassword(*FillPasswordFormWithData(data))); - } - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, FourEqualEntries) { - // Sync correct, Sync Android autofill, local correct, local incorrect with - // the same content. Nothing should happen. - const PasswordFormData data = android_correct(100); - autofill::PasswordForm local_correct = FormWithCorrectTag(data); - autofill::PasswordForm local_incorrect = FormWithAndroidAutofillTag(data); - syncer::SyncData sync_correct = SyncDataFromPassword(local_correct); - syncer::SyncData sync_incorrect = SyncDataFromPassword(local_incorrect); - - for (bool correct_sync_first : {true, false}) { - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - std::vector<autofill::PasswordForm> stored_forms = {local_correct, - local_incorrect}; - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForms(stored_forms)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - - SyncDataList sync_list = {sync_correct, sync_incorrect}; - if (!correct_sync_first) - std::swap(sync_list[0], sync_list[1]); - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, AndroidCorrectEqualEntries) { - // Sync correct, local correct with the same content. Nothing should happen. - const PasswordFormData data = android_correct(100); - autofill::PasswordForm local_correct = FormWithCorrectTag(data); - syncer::SyncData sync_correct = SyncDataFromPassword(local_correct); - - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForm(local_correct)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, {sync_correct}, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); -} - } // namespace } // namespace password_manager |