forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PRImpl] Move PaymentAppComparator into its own file
Before: * The implementation of PaymentAppComparator lived in PaymentRequestImpl. * Its internal methods were visible to the whole PaymentRequestImpl. * Although it only requires 4 parameters of PaymentRequestImpl, it depends on the whole PaymentRequestImpl. After: * The implementation of PaymentAppComparator lived in a separate file. * Its internal methods are not visible to PaymentRequestImpl. * Its dependencies on PaymentRequestImpl are explicitly passed in through the constructor. Bug: 1102522 Change-Id: Ia8cb0611de83a2ef5b7d97943e3334156d2bb08f Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2299857 Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org> Reviewed-by: Rouslan Solomakhin <rouslan@chromium.org> Cr-Commit-Position: refs/heads/master@{#789068}
- Loading branch information
Showing
3 changed files
with
157 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppComparator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
// Copyright 2020 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. | ||
|
||
package org.chromium.chrome.browser.payments; | ||
|
||
import org.chromium.components.autofill.Completable; | ||
import org.chromium.components.payments.PaymentApp; | ||
|
||
import java.util.Comparator; | ||
|
||
/** A comparator that is used to rank the payment apps to be listed in the payment sheet. */ | ||
/* package */ class PaymentAppComparator implements Comparator<PaymentApp> { | ||
private final ParamsProvider mParamsProvider; | ||
|
||
/** The provider of the parameters needed by this class. */ | ||
/* package */ interface ParamsProvider { | ||
/** @return The requestShipping set by the merchant. */ | ||
boolean requestShipping(); | ||
/** @return The requestPayerName set by the merchant. */ | ||
boolean requestPayerName(); | ||
/** @return The requestPayerEmail set by the merchant. */ | ||
boolean requestPayerEmail(); | ||
/** @return The requestPayerPhone set by the merchant. */ | ||
boolean requestPayerPhone(); | ||
} | ||
|
||
/** | ||
* Create an instance of PaymentAppComparator. | ||
* @param paramsProvider The provider of the params needed by this class. | ||
*/ | ||
/* package */ PaymentAppComparator(ParamsProvider paramsProvider) { | ||
mParamsProvider = paramsProvider; | ||
} | ||
|
||
/** | ||
* Compares two payment apps by frecency. | ||
* Return negative value if a has strictly lower frecency score than b. | ||
* Return zero if a and b have the same frecency score. | ||
* Return positive value if a has strictly higher frecency score than b. | ||
*/ | ||
private static int compareAppsByFrecency(PaymentApp a, PaymentApp b) { | ||
int aCount = PaymentPreferencesUtil.getPaymentAppUseCount(a.getIdentifier()); | ||
int bCount = PaymentPreferencesUtil.getPaymentAppUseCount(b.getIdentifier()); | ||
long aDate = PaymentPreferencesUtil.getPaymentAppLastUseDate(a.getIdentifier()); | ||
long bDate = PaymentPreferencesUtil.getPaymentAppLastUseDate(a.getIdentifier()); | ||
|
||
return Double.compare(getFrecencyScore(aCount, aDate), getFrecencyScore(bCount, bDate)); | ||
} | ||
|
||
/** | ||
* Compares two Completable by completeness score. | ||
* Return negative value if a has strictly lower completeness score than b. | ||
* Return zero if a and b have the same completeness score. | ||
* Return positive value if a has strictly higher completeness score than b. | ||
*/ | ||
/* package */ static int compareCompletablesByCompleteness(Completable a, Completable b) { | ||
return Integer.compare(a.getCompletenessScore(), b.getCompletenessScore()); | ||
} | ||
|
||
/** | ||
* The frecency score is calculated according to use count and last use date. The formula is | ||
* the same as the one used in GetFrecencyScore in autofill_data_model.cc. | ||
*/ | ||
private static double getFrecencyScore(int count, long date) { | ||
long currentTime = System.currentTimeMillis(); | ||
return -Math.log((currentTime - date) / (24 * 60 * 60 * 1000) + 2) / Math.log(count + 2); | ||
} | ||
|
||
/** | ||
* Sorts the payment apps by several rules: | ||
* Rule 1: Non-autofill before autofill. | ||
* Rule 2: Complete apps before incomplete apps. | ||
* Rule 3: When shipping address is requested, apps which will handle shipping address before | ||
* others. | ||
* Rule 4: When payer's contact information is requested, apps which will handle more required | ||
* contact fields (name, email, phone) come before others. | ||
* Rule 5: Preselectable apps before non-preselectable apps. | ||
* Rule 6: Frequently and recently used apps before rarely and non-recently used apps. | ||
*/ | ||
@Override | ||
public int compare(PaymentApp a, PaymentApp b) { | ||
// Non-autofill apps first. | ||
int autofill = (a.isAutofillInstrument() ? 1 : 0) - (b.isAutofillInstrument() ? 1 : 0); | ||
if (autofill != 0) return autofill; | ||
|
||
// Complete cards before cards with missing information. | ||
int completeness = compareCompletablesByCompleteness(b, a); | ||
if (completeness != 0) return completeness; | ||
|
||
// Payment apps which handle shipping address before others. | ||
if (mParamsProvider.requestShipping()) { | ||
int canHandleShipping = | ||
(b.handlesShippingAddress() ? 1 : 0) - (a.handlesShippingAddress() ? 1 : 0); | ||
if (canHandleShipping != 0) return canHandleShipping; | ||
} | ||
|
||
// Payment apps which handle more contact information fields come first. | ||
int aSupportedContactDelegationsNum = 0; | ||
int bSupportedContactDelegationsNum = 0; | ||
if (mParamsProvider.requestPayerName()) { | ||
if (a.handlesPayerName()) aSupportedContactDelegationsNum++; | ||
if (b.handlesPayerName()) bSupportedContactDelegationsNum++; | ||
} | ||
if (mParamsProvider.requestPayerEmail()) { | ||
if (a.handlesPayerEmail()) aSupportedContactDelegationsNum++; | ||
if (b.handlesPayerEmail()) bSupportedContactDelegationsNum++; | ||
} | ||
if (mParamsProvider.requestPayerPhone()) { | ||
if (a.handlesPayerPhone()) aSupportedContactDelegationsNum++; | ||
if (b.handlesPayerPhone()) bSupportedContactDelegationsNum++; | ||
} | ||
if (bSupportedContactDelegationsNum != aSupportedContactDelegationsNum) { | ||
return bSupportedContactDelegationsNum - aSupportedContactDelegationsNum > 0 ? 1 : -1; | ||
} | ||
|
||
// Preselectable apps before non-preselectable apps. | ||
// Note that this only affects service worker payment apps' apps for now | ||
// since autofill cards have already been sorted by preselect after sorting by completeness. | ||
// And the other payment apps can always be preselected. | ||
int canPreselect = (b.canPreselect() ? 1 : 0) - (a.canPreselect() ? 1 : 0); | ||
if (canPreselect != 0) return canPreselect; | ||
|
||
// More frequently and recently used apps first. | ||
return compareAppsByFrecency(b, a); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters