Commit 157f3995 authored by Mathieu Perreault's avatar Mathieu Perreault Committed by Commit Bot

[Payments] Add feature to control Google Pay cards returned in basic-card

Bug: 856604
Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: Ie75cdf7ccb3743f09632a305fec0bca00a78e19b
Reviewed-on: https://chromium-review.googlesource.com/1114687Reviewed-by: default avatarSebastien Seguin-Gagnon <sebsg@chromium.org>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Commit-Queue: Mathieu Perreault <mathp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#571569}
parent 6bc00679
......@@ -269,6 +269,8 @@ public abstract class ChromeFeatureList {
public static final String WEB_PAYMENTS_METHOD_SECTION_ORDER_V2 =
"WebPaymentsMethodSectionOrderV2";
public static final String WEB_PAYMENTS_MODIFIERS = "WebPaymentsModifiers";
public static final String WEB_PAYMENTS_RETURN_GOOGLE_PAY_IN_BASIC_CARD =
"ReturnGooglePayInBasicCard";
public static final String WEB_PAYMENTS_SINGLE_APP_UI_SKIP = "WebPaymentsSingleAppUiSkip";
public static final String WEBVR_AUTOPRESENT_FROM_INTENT = "WebVrAutopresentFromIntent";
public static final String WEBVR_CARDBOARD_SUPPORT = "WebVrCardboardSupport";
......
......@@ -685,10 +685,12 @@ public class PersonalDataManager {
/**
* Gets the credit cards to suggest when filling a form or completing a transaction. The cards
* will have been processed to be more relevant to the user.
* @param includeServerCards Whether server cards should be included in the response.
*/
public List<CreditCard> getCreditCardsToSuggest() {
public List<CreditCard> getCreditCardsToSuggest(boolean includeServerCards) {
ThreadUtils.assertOnUiThread();
return getCreditCards(nativeGetCreditCardGUIDsToSuggest(mPersonalDataManagerAndroid));
return getCreditCards(
nativeGetCreditCardGUIDsToSuggest(mPersonalDataManagerAndroid, includeServerCards));
}
private List<CreditCard> getCreditCards(String[] creditCardGUIDs) {
......@@ -983,7 +985,7 @@ public class PersonalDataManager {
private native String[] nativeGetCreditCardGUIDsForSettings(
long nativePersonalDataManagerAndroid);
private native String[] nativeGetCreditCardGUIDsToSuggest(
long nativePersonalDataManagerAndroid);
long nativePersonalDataManagerAndroid, boolean includeServerCards);
private native CreditCard nativeGetCreditCardByGUID(long nativePersonalDataManagerAndroid,
String guid);
private native CreditCard nativeGetCreditCardForNumber(long nativePersonalDataManagerAndroid,
......
......@@ -8,6 +8,7 @@ import android.os.Handler;
import android.text.TextUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.autofill.CardType;
import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
......@@ -47,7 +48,9 @@ public class AutofillPaymentApp implements PaymentApp {
String unusedIFRameOrigin, byte[][] unusedCertificateChain,
Map<String, PaymentDetailsModifier> modifiers, final InstrumentsCallback callback) {
PersonalDataManager pdm = PersonalDataManager.getInstance();
List<CreditCard> cards = pdm.getCreditCardsToSuggest();
List<CreditCard> cards =
pdm.getCreditCardsToSuggest(/*includeServerCards=*/ChromeFeatureList.isEnabled(
ChromeFeatureList.WEB_PAYMENTS_RETURN_GOOGLE_PAY_IN_BASIC_CARD));
final List<PaymentInstrument> instruments = new ArrayList<>(cards.size());
if (methodDataMap.containsKey(BasicCardUtils.BASIC_CARD_METHOD_NAME)) {
......
......@@ -1870,6 +1870,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBlobUrlTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentGooglePayTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java",
......
......@@ -83,7 +83,9 @@ public class AutofillTestHelper {
List<CreditCard> getCreditCardsToSuggest() throws ExecutionException {
return ThreadUtils.runOnUiThreadBlocking(
() -> PersonalDataManager.getInstance().getCreditCardsToSuggest());
()
-> PersonalDataManager.getInstance().getCreditCardsToSuggest(
/*includeServerCards=*/true));
}
List<CreditCard> getCreditCardsForSettings() throws ExecutionException {
......
// Copyright 2018 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 android.support.test.filters.MediumTest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.autofill.AutofillTestHelper;
import org.chromium.chrome.browser.autofill.CardType;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
/**
* A payment integration test for checking whether user can make a payment via a credit card,
* depending on whether Google Pay cards are returned in basic-card.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class PaymentRequestCanMakePaymentGooglePayTest implements MainActivityStartCallback {
@Rule
public PaymentRequestTestRule mPaymentRequestTestRule =
new PaymentRequestTestRule("payment_request_can_make_payment_query_test.html", this);
@Override
public void onMainActivityStarted()
throws InterruptedException, ExecutionException, TimeoutException {
// The user has a valid server credit card with a billing address on file. This is
// sufficient for canMakePayment() to return true.
AutofillTestHelper helper = new AutofillTestHelper();
String billingAddressId = helper.setProfile(new AutofillProfile("", "https://example.com",
true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
"US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
helper.addServerCreditCard(new CreditCard("4754d21d-8773-40b6-b4be-5f7486be834f",
"https://example.com", false /* isLocal */, true /* isCached */, "Jon Doe",
"4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
CardType.UNKNOWN, billingAddressId, "" /* serverId */));
}
@Test
@MediumTest
@Feature({"Payments"})
@CommandLineFlags.
Add("enable-features=" + ChromeFeatureList.WEB_PAYMENTS_RETURN_GOOGLE_PAY_IN_BASIC_CARD)
public void testGooglePayServerCardsAllowed()
throws InterruptedException, ExecutionException, TimeoutException {
mPaymentRequestTestRule.openPageAndClickBuyAndWait(
mPaymentRequestTestRule.getCanMakePaymentQueryResponded());
mPaymentRequestTestRule.expectResultContains(new String[] {"true"});
}
@Test
@MediumTest
@Feature({"Payments"})
@CommandLineFlags.
Add("disable-features=" + ChromeFeatureList.WEB_PAYMENTS_RETURN_GOOGLE_PAY_IN_BASIC_CARD)
public void testGooglePayServerCardsNotAllowed()
throws InterruptedException, ExecutionException, TimeoutException {
mPaymentRequestTestRule.openPageAndClickBuyAndWait(
mPaymentRequestTestRule.getCanMakePaymentQueryResponded());
mPaymentRequestTestRule.expectResultContains(new String[] {"false"});
}
}
......@@ -131,6 +131,7 @@ const base::Feature* kFeaturesExposedToJava[] = {
&kVrBrowsingFeedback,
&kVrBrowsingInCustomTab,
&kVrBrowsingNativeAndroidUi,
&payments::features::kReturnGooglePayInBasicCard,
&payments::features::kWebPaymentsMethodSectionOrderV2,
&payments::features::kWebPaymentsModifiers,
&payments::features::kWebPaymentsSingleAppUiSkip,
......
......@@ -475,10 +475,11 @@ PersonalDataManagerAndroid::GetCreditCardGUIDsForSettings(
base::android::ScopedJavaLocalRef<jobjectArray>
PersonalDataManagerAndroid::GetCreditCardGUIDsToSuggest(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& unused_obj) {
return GetCreditCardGUIDs(env,
personal_data_manager_->GetCreditCardsToSuggest(
/*include_server_cards=*/true));
const base::android::JavaParamRef<jobject>& unused_obj,
bool include_server_cards) {
return GetCreditCardGUIDs(
env,
personal_data_manager_->GetCreditCardsToSuggest(include_server_cards));
}
ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetCreditCardByGUID(
......
......@@ -126,7 +126,8 @@ class PersonalDataManagerAndroid : public PersonalDataManagerObserver {
// PersonalDataManager::GetCreditCardsToSuggest for more details.
base::android::ScopedJavaLocalRef<jobjectArray> GetCreditCardGUIDsToSuggest(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& unused_obj);
const base::android::JavaParamRef<jobject>& unused_obj,
bool include_server_cards);
// Returns the credit card with the specified |jguid|, or NULL if there is
// no credit card with the specified |jguid|.
......
......@@ -12,6 +12,7 @@
#include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/payments/core/features.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test_utils.h"
......@@ -67,6 +68,48 @@ IN_PROC_BROWSER_TEST_F(PaymentRequestCanMakePaymentQueryTest,
ExpectBodyContains({"false"});
}
// Visa is required, and user has a masked visa instrument, and Google Pay cards
// in basic-card is disabled.
IN_PROC_BROWSER_TEST_F(PaymentRequestCanMakePaymentQueryTest,
CanMakePayment_Supported_GooglePayCardsDisabled) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndDisableFeature(
payments::features::kReturnGooglePayInBasicCard);
NavigateTo("/payment_request_can_make_payment_query_test.html");
autofill::CreditCard card = autofill::test::GetMaskedServerCard();
card.SetNumber(base::ASCIIToUTF16("4111111111111111")); // We need a visa.
card.SetNetworkForMaskedCard(autofill::kVisaCard);
autofill::AutofillProfile billing_address = autofill::test::GetFullProfile();
AddAutofillProfile(billing_address);
card.set_billing_address_id(billing_address.guid());
AddCreditCard(card);
CallCanMakePayment();
ExpectBodyContains({"false"});
}
// Visa is required, and user has a masked visa instrument, and Google Pay cards
// in basic-card is enabled.
IN_PROC_BROWSER_TEST_F(PaymentRequestCanMakePaymentQueryTest,
CanMakePayment_Supported_GooglePayCardsEnabled) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
payments::features::kReturnGooglePayInBasicCard);
NavigateTo("/payment_request_can_make_payment_query_test.html");
autofill::CreditCard card = autofill::test::GetMaskedServerCard();
card.SetNumber(base::ASCIIToUTF16("4111111111111111")); // We need a visa.
card.SetNetworkForMaskedCard(autofill::kVisaCard);
autofill::AutofillProfile billing_address = autofill::test::GetFullProfile();
AddAutofillProfile(billing_address);
card.set_billing_address_id(billing_address.guid());
AddCreditCard(card);
CallCanMakePayment();
ExpectBodyContains({"true"});
}
// Pages without a valid SSL certificate always get "false" from
// .canMakePayment().
IN_PROC_BROWSER_TEST_F(PaymentRequestCanMakePaymentQueryTest,
......@@ -368,7 +411,8 @@ IN_PROC_BROWSER_TEST_F(PaymentRequestCanMakePaymentQueryPMITest,
QueryQuotaForPaymentAppsInIncognitoMode) {
NavigateTo("/payment_request_payment_method_identifier_test.html");
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kServiceWorkerPaymentApps);
scoped_feature_list.InitAndEnableFeature(
::features::kServiceWorkerPaymentApps);
SetIncognito();
......
......@@ -1259,6 +1259,25 @@ bool PersonalDataManager::IsAutofillWalletImportEnabled() const {
return pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled);
}
bool PersonalDataManager::ShouldSuggestServerCards() const {
if (!IsAutofillWalletImportEnabled())
return false;
if (is_syncing_for_test_)
return true;
// Check if the feature to offer server cards on auth error is enabled.
if (base::FeatureList::IsEnabled(
features::kAutofillEnablePaymentsInteractionsOnAuthError)) {
return true;
}
// Server cards should be suggested if the sync service active.
return syncer::GetUploadToGoogleState(
sync_service_, syncer::ModelType::AUTOFILL_WALLET_DATA) ==
syncer::UploadState::ACTIVE;
}
std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
return base::CountryCodeForCurrentTimezone();
}
......@@ -2283,25 +2302,6 @@ bool PersonalDataManager::DeleteDisusedAddresses() {
return true;
}
bool PersonalDataManager::ShouldSuggestServerCards() const {
if (!IsAutofillWalletImportEnabled())
return false;
if (is_syncing_for_test_)
return true;
// Check if the feature to offer server cards on auth error is enabled.
if (base::FeatureList::IsEnabled(
features::kAutofillEnablePaymentsInteractionsOnAuthError)) {
return true;
}
// Server cards should be suggested if the sync service active.
return syncer::GetUploadToGoogleState(
sync_service_, syncer::ModelType::AUTOFILL_WALLET_DATA) ==
syncer::UploadState::ACTIVE;
}
void PersonalDataManager::ApplyAddressFixesAndCleanups() {
RemoveOrphanAutofillTableRows(); // One-time fix, otherwise NOP.
ApplyDedupingRoutine(); // Once per major version, otherwise NOP.
......
......@@ -451,6 +451,9 @@ class PersonalDataManager : public KeyedService,
// Returns the value of the AutofillWalletImportEnabled pref.
virtual bool IsAutofillWalletImportEnabled() const;
// Whether the server cards are enabled and should be suggested to the user.
virtual bool ShouldSuggestServerCards() const;
// Overrideable for testing.
virtual std::string CountryCodeForCurrentTimezone() const;
......@@ -608,9 +611,6 @@ class PersonalDataManager : public KeyedService,
// manually using the UI.
void MaybeCreateTestCreditCards();
// Whether the server cards are enabled and should be suggested to the user.
bool ShouldSuggestServerCards() const;
// Applies various fixes and cleanups on autofill addresses.
void ApplyAddressFixesAndCleanups();
......
......@@ -191,6 +191,10 @@ bool TestPersonalDataManager::IsAutofillWalletImportEnabled() const {
return PersonalDataManager::IsAutofillWalletImportEnabled();
}
bool TestPersonalDataManager::ShouldSuggestServerCards() const {
return IsAutofillCreditCardEnabled() && IsAutofillWalletImportEnabled();
}
std::string TestPersonalDataManager::CountryCodeForCurrentTimezone()
const {
return timezone_country_code_;
......
......@@ -46,6 +46,7 @@ class TestPersonalDataManager : public PersonalDataManager {
bool IsAutofillEnabled() const override;
bool IsAutofillCreditCardEnabled() const override;
bool IsAutofillWalletImportEnabled() const override;
bool ShouldSuggestServerCards() const override;
std::string CountryCodeForCurrentTimezone() const override;
bool IsDataLoaded() const override;
......
......@@ -20,6 +20,7 @@
#include "components/payments/content/payment_response_helper.h"
#include "components/payments/content/service_worker_payment_instrument.h"
#include "components/payments/core/autofill_payment_instrument.h"
#include "components/payments/core/features.h"
#include "components/payments/core/journey_logger.h"
#include "components/payments/core/payment_instrument.h"
#include "components/payments/core/payment_request_data_util.h"
......@@ -53,7 +54,7 @@ PaymentRequestState::PaymentRequestState(
payment_request_delegate_(payment_request_delegate),
profile_comparator_(app_locale, *spec),
weak_ptr_factory_(this) {
if (base::FeatureList::IsEnabled(features::kServiceWorkerPaymentApps)) {
if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
get_all_instruments_finished_ = false;
ServiceWorkerPaymentAppFactory::GetInstance()->GetAllPaymentApps(
web_contents,
......@@ -415,7 +416,8 @@ void PaymentRequestState::PopulateProfileCache() {
// by their respective AutofillPaymentInstrument.
const std::vector<autofill::CreditCard*>& cards =
personal_data_manager_->GetCreditCardsToSuggest(
/*include_server_cards=*/true);
/*include_server_cards=*/base::FeatureList::IsEnabled(
payments::features::kReturnGooglePayInBasicCard));
for (autofill::CreditCard* card : cards)
AddAutofillPaymentInstrument(/*selected=*/false, *card);
}
......
......@@ -7,6 +7,9 @@
namespace payments {
namespace features {
const base::Feature kReturnGooglePayInBasicCard{
"ReturnGooglePayInBasicCard", base::FEATURE_ENABLED_BY_DEFAULT};
#if defined(OS_IOS)
const base::Feature kWebPayments{"WebPayments",
base::FEATURE_ENABLED_BY_DEFAULT};
......
......@@ -11,6 +11,9 @@
namespace payments {
namespace features {
// Used to control whether Google Pay cards are returned for basic-card.
extern const base::Feature kReturnGooglePayInBasicCard;
#if defined(OS_IOS)
// Used to control the state of the Payment Request API feature.
extern const base::Feature kWebPayments;
......
......@@ -522,7 +522,8 @@ void PaymentRequest::PopulatePaymentMethodCache(
std::vector<std::unique_ptr<IOSPaymentInstrument>> native_app_instruments) {
const std::vector<autofill::CreditCard*>& credit_cards_to_suggest =
personal_data_manager_->GetCreditCardsToSuggest(
/*include_server_cards=*/true);
/*include_server_cards=*/base::FeatureList::IsEnabled(
payments::features::kReturnGooglePayInBasicCard));
// Return early if the user has no stored credit cards or installed payment
// apps.
......
......@@ -319,6 +319,64 @@ TEST_F(PaymentRequestTest, SupportedMethods_BasicCard_WithSupportedNetworks) {
EXPECT_EQ("unionpay", payment_request.supported_card_networks()[1]);
}
TEST_F(PaymentRequestTest, GooglePayCardsInBasicCard_Allowed) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(features::kReturnGooglePayInBasicCard);
WebPaymentRequest web_payment_request;
PaymentMethodData method_datum;
method_datum.supported_methods.push_back("basic-card");
method_datum.supported_networks.push_back("mastercard");
web_payment_request.method_data.push_back(method_datum);
// Add a mastercard with billing address.
autofill::AutofillProfile address = autofill::test::GetFullProfile();
test_personal_data_manager_.AddProfile(address);
autofill::CreditCard credit_card = autofill::test::GetMaskedServerCard();
credit_card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT);
credit_card.set_billing_address_id(address.guid());
test_personal_data_manager_.AddServerCreditCard(credit_card);
TestPaymentRequest payment_request(web_payment_request,
chrome_browser_state_.get(), &web_state_,
&test_personal_data_manager_);
// The card is available in the payment request, and added to the
// PersonalDataManager.
EXPECT_EQ(1U, payment_request.payment_methods().size());
// The card is expected to have been added to the PersonalDataManager.
EXPECT_EQ(1U, test_personal_data_manager_.GetCreditCards().size());
}
TEST_F(PaymentRequestTest, GooglePayCardsInBasicCard_NotAllowed) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(features::kReturnGooglePayInBasicCard);
WebPaymentRequest web_payment_request;
PaymentMethodData method_datum;
method_datum.supported_methods.push_back("basic-card");
method_datum.supported_networks.push_back("mastercard");
web_payment_request.method_data.push_back(method_datum);
// Add a mastercard with billing address.
autofill::AutofillProfile address = autofill::test::GetFullProfile();
test_personal_data_manager_.AddProfile(address);
autofill::CreditCard credit_card = autofill::test::GetMaskedServerCard();
credit_card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT);
credit_card.set_billing_address_id(address.guid());
test_personal_data_manager_.AddServerCreditCard(credit_card);
TestPaymentRequest payment_request(web_payment_request,
chrome_browser_state_.get(), &web_state_,
&test_personal_data_manager_);
// The card is not available in the payment request, but added to the
// PersonalDataManager.
EXPECT_TRUE(payment_request.payment_methods().empty());
// The card is expected to have been added to the PersonalDataManager.
EXPECT_EQ(1U, test_personal_data_manager_.GetCreditCards().size());
}
// Tests that an autofill payment instrumnt e.g., credit cards can be added
// to the list of available payment methods.
TEST_F(PaymentRequestTest, CreateAndAddAutofillPaymentInstrument) {
......@@ -1150,7 +1208,7 @@ TEST_F(PaymentRequestTest,
autofill::CreditCard credit_card = autofill::test::GetMaskedServerCardAmex();
credit_card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT);
credit_card.set_billing_address_id(address.guid());
test_personal_data_manager_.AddCreditCard(credit_card);
test_personal_data_manager_.AddServerCreditCard(credit_card);
WebPaymentRequest web_payment_request =
payment_request_test_util::CreateTestWebPaymentRequest();
......
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