Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Unified Diff: components/payments/core/profile_util.cc

Issue 2775553004: [WebPayments] Implementing Profile filter and dedupe (Closed)
Patch Set: include algo Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/payments/core/profile_util.cc
diff --git a/components/payments/core/profile_util.cc b/components/payments/core/profile_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..083719003b174ba246f9c1ee0c19af24ec732a06
--- /dev/null
+++ b/components/payments/core/profile_util.cc
@@ -0,0 +1,123 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/payments/core/profile_util.h"
+
+#include <algorithm>
+
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/payments/core/payment_options_provider.h"
+
+namespace payments {
+namespace profile_util {
+
+std::vector<autofill::AutofillProfile*> FilterProfilesForContact(
+ const std::vector<autofill::AutofillProfile*>& profiles,
+ const std::string& app_locale,
+ PaymentOptionsProvider* options) {
+ // We will be removing profiles, so we operate on a copy.
+ std::vector<autofill::AutofillProfile*> processed = profiles;
+
+ PaymentsProfileComparator comparator(app_locale, options);
+
+ // Stable sort, since profiles are expected to be passed in frecency order.
+ std::stable_sort(
+ processed.begin(), processed.end(),
+ std::bind(&PaymentsProfileComparator::IsContactMoreComplete, &comparator,
+ std::placeholders::_1, std::placeholders::_2));
+
+ auto it = processed.begin();
+ while (it != processed.end()) {
+ if (comparator.GetContactCompletenessScore(*it) == 0) {
+ // Since profiles are sorted by completeness, this and any further
+ // profiles can be discarded.
+ processed.erase(it, processed.end());
+ break;
+ }
+
+ // Attempt to find a matching element in the vector before the current.
+ // This is quadratic, but the number of elements is generally small
+ // (< 10), so a more complicated algorithm would be overkill.
+ if (std::find_if(processed.begin(), it,
+ [&](autofill::AutofillProfile* prior) {
+ return comparator.IsContactEqualOrSuperset(prior, *it);
+ }) != it) {
+ // Remove the subset profile. |it| will point to the next element after
+ // erasure.
+ it = processed.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ return processed;
+}
+
+PaymentsProfileComparator::PaymentsProfileComparator(
+ const std::string& app_locale,
+ PaymentOptionsProvider* options)
+ : autofill::AutofillProfileComparator(app_locale), options_(options) {}
+
+PaymentsProfileComparator::~PaymentsProfileComparator() {}
+
+bool PaymentsProfileComparator::IsContactEqualOrSuperset(
+ autofill::AutofillProfile* super,
+ autofill::AutofillProfile* sub) {
+ if (options_->request_payer_name()) {
+ if (sub->HasInfo(autofill::NAME_FULL) &&
+ !super->HasInfo(autofill::NAME_FULL)) {
+ return false;
+ }
+ if (!HaveMergeableNames(*super, *sub))
+ return false;
+ }
+ if (options_->request_payer_phone()) {
+ if (sub->HasInfo(autofill::PHONE_HOME_WHOLE_NUMBER) &&
+ !super->HasInfo(autofill::PHONE_HOME_WHOLE_NUMBER)) {
+ return false;
+ }
+ if (!HaveMergeablePhoneNumbers(*super, *sub))
+ return false;
+ }
+ if (options_->request_payer_email()) {
+ if (sub->HasInfo(autofill::EMAIL_ADDRESS) &&
+ !super->HasInfo(autofill::EMAIL_ADDRESS)) {
+ return false;
+ }
+ if (!HaveMergeableEmailAddresses(*super, *sub))
+ return false;
+ }
+ return true;
+}
+
+int PaymentsProfileComparator::GetContactCompletenessScore(
+ autofill::AutofillProfile* profile) {
Mathieu 2017/04/03 19:11:53 const ref?
tmartino 2017/04/04 21:00:22 I thought about it, but considering the need to us
Mathieu 2017/04/05 13:43:10 I think as much as possible we should use const re
+ if (!profile)
+ return 0;
+
+ return (options_->request_payer_name() &&
+ profile->HasInfo(autofill::NAME_FULL)) +
+ (options_->request_payer_phone() &&
+ profile->HasInfo(autofill::PHONE_HOME_WHOLE_NUMBER)) +
+ (options_->request_payer_email() &&
+ profile->HasInfo(autofill::EMAIL_ADDRESS));
+}
+
+bool PaymentsProfileComparator::IsContactInfoComplete(
+ autofill::AutofillProfile* profile) {
+ int desired_score = options_->request_payer_name() +
+ options_->request_payer_phone() +
+ options_->request_payer_email();
+ return GetContactCompletenessScore(profile) == desired_score;
+}
+
+bool PaymentsProfileComparator::IsContactMoreComplete(
+ autofill::AutofillProfile* p1,
+ autofill::AutofillProfile* p2) {
+ return GetContactCompletenessScore(p1) > GetContactCompletenessScore(p2);
+}
+
+} // namespace profile_util
+} // namespace payments
« components/payments/core/profile_util.h ('K') | « components/payments/core/profile_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698