blob: 1e1f8a55210c0c83af0dd88d85f6fce775bb1848 [file] [log] [blame]
// Copyright 2019 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 "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/test/payments/payment_request_platform_browsertest_base.h"
#include "components/payments/core/features.h"
#include "components/payments/core/journey_logger.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace payments {
class PaymentHandlerJustInTimeInstallationTest
: public PaymentRequestPlatformBrowserTestBase {
protected:
PaymentHandlerJustInTimeInstallationTest()
: kylepay_server_(net::EmbeddedTestServer::TYPE_HTTPS),
henrypay_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
~PaymentHandlerJustInTimeInstallationTest() override = default;
void SetUpOnMainThread() override {
PaymentRequestPlatformBrowserTestBase::SetUpOnMainThread();
kylepay_server_.ServeFilesFromSourceDirectory(
"components/test/data/payments/kylepay.com/");
ASSERT_TRUE(kylepay_server_.Start());
henrypay_server_.ServeFilesFromSourceDirectory(
"components/test/data/payments/henrypay.com");
ASSERT_TRUE(henrypay_server_.Start());
NavigateTo("/payment_request_bobpay_and_cards_test.html");
// Set up test manifest downloader that knows how to fake origin.
const std::string kyle_method_name = "kylepay.com";
const std::string henry_method_name = "henrypay.com";
SetDownloaderAndIgnorePortInOriginComparisonForTesting(
{{kyle_method_name, &kylepay_server_},
{henry_method_name, &henrypay_server_}});
}
private:
net::EmbeddedTestServer kylepay_server_;
net::EmbeddedTestServer henrypay_server_;
};
// kylepay.com hosts an installable payment app which handles both shipping
// address and payer's contact information.
IN_PROC_BROWSER_TEST_F(PaymentHandlerJustInTimeInstallationTest,
InstallPaymentAppAndPay) {
ResetEventWaiterForSingleEvent(TestEvent::kPaymentCompleted);
EXPECT_TRUE(content::ExecJs(
GetActiveWebContents(),
"testPaymentMethods([{supportedMethods: 'https://kylepay.com/webpay'}], "
"false/*= requestShippingContact */);"));
WaitForObservedEvent();
// kylepay should be installed just-in-time and used for testing.
ExpectBodyContains("kylepay.com/webpay");
}
IN_PROC_BROWSER_TEST_F(PaymentHandlerJustInTimeInstallationTest,
InstallPaymentAppAndPayWithDelegation) {
ResetEventWaiterForSingleEvent(TestEvent::kPaymentCompleted);
EXPECT_TRUE(content::ExecJs(
GetActiveWebContents(),
"testPaymentMethods([{supportedMethods: 'https://kylepay.com/webpay'}], "
"true/*= requestShippingContact */);"));
WaitForObservedEvent();
// kylepay should be installed just-in-time and used for testing.
ExpectBodyContains("kylepay.com/webpay");
}
IN_PROC_BROWSER_TEST_F(PaymentHandlerJustInTimeInstallationTest,
DoNotInstallPaymentAppWithInvalidPaymentMethod) {
ResetEventWaiterForSingleEvent(TestEvent::kNotSupportedError);
EXPECT_TRUE(content::ExecJs(GetActiveWebContents(),
"testPaymentMethods([{supportedMethods: "
"'https://henrypay.com/webpay'}])"));
WaitForObservedEvent();
// show() should get rejected since the JIT installable app
// that uses invalid payment method.
ExpectBodyContains(
"\nBob Pay and Cards Test\nInstallable App\nThe payment method "
"\"https://henrypay.com/webpay\" is not supported.\n\n\n\n\n");
}
using PaymentHandlerSkipSheetTest = PaymentHandlerJustInTimeInstallationTest;
IN_PROC_BROWSER_TEST_F(PaymentHandlerSkipSheetTest, SkipWithUserGesture) {
base::HistogramTester histogram_tester;
ResetEventWaiterForSingleEvent(TestEvent::kPaymentCompleted);
EXPECT_TRUE(
content::ExecJs(GetActiveWebContents(),
"testPaymentMethods([ "
" {supportedMethods: 'https://kylepay.com/webpay'}])"));
WaitForObservedEvent();
ExpectBodyContains("kylepay.com/webpay");
std::vector<base::Bucket> buckets =
histogram_tester.GetAllSamples("PaymentRequest.Events");
ASSERT_EQ(1U, buckets.size());
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_SKIPPED_SHOW);
EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_SHOWN);
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER);
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_SELECTED_OTHER);
}
IN_PROC_BROWSER_TEST_F(PaymentHandlerSkipSheetTest, NoSkipWithoutUserGesture) {
// When shipping is not requested, kylepay.com cannot leverage skip-the-sheet
// for being the only payment app that can fulfill all delegation requests. So
// if there is no user gesture, the request should stop at the payment sheet
// waiting for user action.
base::HistogramTester histogram_tester;
ResetEventWaiterForSingleEvent(TestEvent::kAppListReady);
EXPECT_TRUE(
content::ExecJs(GetActiveWebContents(),
"testPaymentMethods([ "
" {supportedMethods: 'https://kylepay.com/webpay'}])",
content::EXECUTE_SCRIPT_NO_USER_GESTURE));
WaitForObservedEvent();
EXPECT_TRUE(content::ExecJs(GetActiveWebContents(), "abort()"));
std::vector<base::Bucket> buckets =
histogram_tester.GetAllSamples("PaymentRequest.Events");
ASSERT_EQ(1U, buckets.size());
// TODO(crbug.com/1122198): EVENT_SHOWN is not always logged on Android.
#if !defined(OS_ANDROID)
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_SHOWN);
#endif
EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_SKIPPED_SHOW);
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER);
EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_SELECTED_OTHER);
}
class SecurePaymentConfirmationSkipSheetTest
: public PaymentHandlerJustInTimeInstallationTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
PaymentHandlerJustInTimeInstallationTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
}
};
// TODO(crbug.com/825270): Remove this special case user gesture exception is
// removed.
IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationSkipSheetTest,
SkipWithoutUserGesture) {
base::HistogramTester histogram_tester;
ResetEventWaiterForSingleEvent(TestEvent::kPaymentCompleted);
EXPECT_TRUE(
content::ExecJs(GetActiveWebContents(),
"testPaymentMethods([ "
" {supportedMethods: 'https://kylepay.com/webpay'}])",
content::EXECUTE_SCRIPT_NO_USER_GESTURE));
WaitForObservedEvent();
ExpectBodyContains("kylepay.com/webpay");
std::vector<base::Bucket> buckets =
histogram_tester.GetAllSamples("PaymentRequest.Events");
ASSERT_EQ(1U, buckets.size());
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_SKIPPED_SHOW);
EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_SHOWN);
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER);
EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_SELECTED_OTHER);
}
class AlwaysAllowJustInTimePaymentAppTest
: public PaymentHandlerJustInTimeInstallationTest,
public testing::WithParamInterface<bool> {
protected:
AlwaysAllowJustInTimePaymentAppTest() {
scoped_feature_list_.InitWithFeatureState(
features::kAlwaysAllowJustInTimePaymentApp, GetParam());
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_P(AlwaysAllowJustInTimePaymentAppTest,
HybridRequest_NoCreditCard) {
base::HistogramTester histogram_tester;
ResetEventWaiterForSingleEvent(GetParam() ? TestEvent::kPaymentCompleted
: TestEvent::kAppListReady);
EXPECT_TRUE(
content::ExecJs(GetActiveWebContents(),
"testPaymentMethods([ "
" {supportedMethods: 'basic-card'}, "
" {supportedMethods: 'https://kylepay.com/webpay'}])"));
WaitForObservedEvent();
if (GetParam()) {
// If AlwaysAllowJIT is enabled, kylepay should be installed just-in-time
// and used for testing.
ExpectBodyContains("kylepay.com/webpay");
} else {
// With AlwaysJIT disabled, the request is expected to stop at the payment
// sheet waiting for user action.
EXPECT_TRUE(content::ExecJs(GetActiveWebContents(), "abort()"));
}
std::vector<base::Bucket> buckets =
histogram_tester.GetAllSamples("PaymentRequest.Events");
ASSERT_EQ(1U, buckets.size());
EXPECT_FALSE(buckets[0].min &
JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD);
EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_GOOGLE);
EXPECT_EQ(GetParam(),
(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER) > 0);
}
IN_PROC_BROWSER_TEST_P(AlwaysAllowJustInTimePaymentAppTest,
HybridRequest_HasCompleteCreditCard) {
CreateAndAddCreditCardForProfile(CreateAndAddAutofillProfile());
base::HistogramTester histogram_tester;
ResetEventWaiterForSingleEvent(TestEvent::kAppListReady);
EXPECT_TRUE(
content::ExecJs(GetActiveWebContents(),
"testPaymentMethods([ "
" {supportedMethods: 'basic-card'}, "
" {supportedMethods: 'https://kylepay.com/webpay'}])"));
WaitForObservedEvent();
// Regardless whether AlwaysJIT is disabled, beceause there is a complete
// basic card, the request is expected to stop at the payment sheet waiting
// for user action.
EXPECT_TRUE(content::ExecJs(GetActiveWebContents(), "abort()"));
std::vector<base::Bucket> buckets =
histogram_tester.GetAllSamples("PaymentRequest.Events");
ASSERT_EQ(1U, buckets.size());
EXPECT_TRUE(buckets[0].min &
JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD);
EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_GOOGLE);
EXPECT_EQ(GetParam(),
(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER) > 0);
}
INSTANTIATE_TEST_SUITE_P(All,
AlwaysAllowJustInTimePaymentAppTest,
::testing::Values(true, false));
} // namespace payments