Commit 0d91c6b9 authored by Matthias Körber's avatar Matthias Körber Committed by Commit Bot

[Autofill][Slimshady] BridgeUtils merging and tests for structured names

Adds logic to merge the names stored in a local and remote profile.
Adepts the bridge util tests to work with structured names.

Change-Id: Ide42931f3f36809b9f72a666e2941ce1418f040d
Bug: 1099202
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2358672
Commit-Queue: Matthias Körber <koerber@google.com>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798703}
parent 9af7e14d
...@@ -568,7 +568,18 @@ void AutofillProfile::OverwriteDataFrom(const AutofillProfile& profile) { ...@@ -568,7 +568,18 @@ void AutofillProfile::OverwriteDataFrom(const AutofillProfile& profile) {
// values. // values.
std::string language_code_value = language_code(); std::string language_code_value = language_code();
std::string origin_value = origin(); std::string origin_value = origin();
base::string16 name_full_value = GetRawInfo(NAME_FULL);
// Structured names should not be simply overwritten but it should be
// attempted to merge the names.
bool use_structured_name = base::FeatureList::IsEnabled(
features::kAutofillEnableSupportForMoreStructureInNames);
bool is_structured_name_mergeable = false;
NameInfo name_info = GetNameInfo();
if (use_structured_name) {
is_structured_name_mergeable =
name_info.IsStructuredNameMergeable(profile.GetNameInfo());
name_info.MergeStructuredName(profile.GetNameInfo());
}
*this = profile; *this = profile;
...@@ -576,8 +587,23 @@ void AutofillProfile::OverwriteDataFrom(const AutofillProfile& profile) { ...@@ -576,8 +587,23 @@ void AutofillProfile::OverwriteDataFrom(const AutofillProfile& profile) {
set_origin(origin_value); set_origin(origin_value);
if (language_code().empty()) if (language_code().empty())
set_language_code(language_code_value); set_language_code(language_code_value);
if (!HasRawInfo(NAME_FULL))
SetRawInfo(NAME_FULL, name_full_value); // For structured names, use the merged name if possible.
if (is_structured_name_mergeable) {
name_ = name_info;
return;
}
// For structured names, if the full name of |profile| is empty, maintain the
// complete name structure. Note, this should only happen if the complete name
// is empty. For the legacy implementation, set the full name if |profile|
// does not contain a full name.
if (!HasRawInfo(NAME_FULL)) {
if (use_structured_name) {
name_ = name_info;
} else {
SetRawInfo(NAME_FULL, name_info.GetRawInfo(NAME_FULL));
}
}
} }
bool AutofillProfile::MergeDataFrom(const AutofillProfile& profile, bool AutofillProfile::MergeDataFrom(const AutofillProfile& profile,
...@@ -1209,31 +1235,53 @@ bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const { ...@@ -1209,31 +1235,53 @@ bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
} }
std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) { std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
return os << (profile.record_type() == AutofillProfile::LOCAL_PROFILE return os
? profile.guid() << (profile.record_type() == AutofillProfile::LOCAL_PROFILE
: base::HexEncode(profile.server_id().data(), ? profile.guid()
profile.server_id().size())) : base::HexEncode(profile.server_id().data(),
<< " " << profile.origin() << " " profile.server_id().size()))
<< UTF16ToUTF8(profile.GetRawInfo(NAME_FULL)) << " " << " " << profile.origin() << " "
<< UTF16ToUTF8(profile.GetRawInfo(NAME_FIRST)) << " " << UTF16ToUTF8(profile.GetRawInfo(NAME_FULL)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(NAME_MIDDLE)) << " " << "("
<< UTF16ToUTF8(profile.GetRawInfo(NAME_LAST)) << " " << base::NumberToString(profile.GetVerificationStatusInt(NAME_FULL))
<< UTF16ToUTF8(profile.GetRawInfo(EMAIL_ADDRESS)) << " " << ") " << UTF16ToUTF8(profile.GetRawInfo(NAME_FIRST)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME)) << " " << "("
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1)) << " " << base::NumberToString(profile.GetVerificationStatusInt(NAME_FIRST))
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2)) << " " << ") " << UTF16ToUTF8(profile.GetRawInfo(NAME_MIDDLE)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE3)) << " " << "("
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)) << base::NumberToString(profile.GetVerificationStatusInt(NAME_MIDDLE))
<< " " << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY)) << " " << ") " << UTF16ToUTF8(profile.GetRawInfo(NAME_LAST)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE)) << " " << "("
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP)) << " " << base::NumberToString(profile.GetVerificationStatusInt(NAME_LAST))
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)) << " " << ") " << UTF16ToUTF8(profile.GetRawInfo(NAME_LAST_FIRST)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) << " " << "("
<< profile.language_code() << " " << base::NumberToString(
<< UTF16ToUTF8(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)) << " " profile.GetVerificationStatusInt(NAME_LAST_FIRST))
<< profile.GetClientValidityBitfieldValue() << " " << ") " << UTF16ToUTF8(profile.GetRawInfo(NAME_LAST_CONJUNCTION))
<< profile.has_converted() << " " << profile.use_count() << " " << " "
<< profile.use_date(); << "("
<< base::NumberToString(
profile.GetVerificationStatusInt(NAME_LAST_CONJUNCTION))
<< ") " << UTF16ToUTF8(profile.GetRawInfo(NAME_LAST_SECOND)) << " "
<< "("
<< base::NumberToString(
profile.GetVerificationStatusInt(NAME_LAST_SECOND))
<< ") " << UTF16ToUTF8(profile.GetRawInfo(EMAIL_ADDRESS)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE3)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))
<< " " << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) << " "
<< profile.language_code() << " "
<< UTF16ToUTF8(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)) << " "
<< profile.GetClientValidityBitfieldValue() << " "
<< profile.has_converted() << " " << profile.use_count() << " "
<< profile.use_date();
} }
bool AutofillProfile::FinalizeAfterImport() { bool AutofillProfile::FinalizeAfterImport() {
......
...@@ -48,12 +48,24 @@ AutofillProfileSyncDifferenceTracker::IncorporateRemoteProfile( ...@@ -48,12 +48,24 @@ AutofillProfileSyncDifferenceTracker::IncorporateRemoteProfile(
return base::nullopt; return base::nullopt;
} }
updated->OverwriteDataFrom(*remote); updated->OverwriteDataFrom(*remote);
// TODO(jkrcal): if |updated| deviates from |remote|, we should sync it back // TODO(crbug.com/1117022l): if |updated| deviates from |remote|, we should
// up. The only way |updated| can differ is having some extra fields // sync it back up. The only way |updated| can differ is having some extra
// compared to |remote|. Thus, this cannot lead to an infinite loop of // fields compared to |remote|. Thus, this cannot lead to an infinite loop
// commits from two clients as each commit decreases the set of empty // of commits from two clients as each commit decreases the set of empty
// fields. This invariant depends on the implementation of // fields. This invariant depends on the implementation of
// OverwriteDataFrom() and thus should be enforced by a DCHECK. // OverwriteDataFrom() and thus should be enforced by a DCHECK.
//
// With structured names the situation changes a bit,
// but maintains its character.
// If the name stored in |remote| is mergeable with the local |name|, the
// merge operation is performed. Otherwise the name structure of |local| is
// maintained iff |remote| contains an empty name.
// A merge operations manipulates the name towards a better total
// verification status of the stored tokens. Consequently, it is not
// possible to get into a merging loop of two competing clients.
// As in the legacy implementation, |OverwriteDataForm()| can change the
// profile in a deterministic way and a direct sync-back would be
// reasonable.
if (!updated->EqualsForSyncPurposes(*local_with_same_storage_key)) { if (!updated->EqualsForSyncPurposes(*local_with_same_storage_key)) {
// We need to write back locally new changes in this entry. // We need to write back locally new changes in this entry.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment