Commit 80b39e86 authored by Rouslan Solomakhin's avatar Rouslan Solomakhin Committed by Commit Bot

[Web Payment] Do not lookup payment handler for Google Play Billing

Before this patch, creating a Payment Request for
"https://play.google.com/billing" would attempt to find installed or JIT
installable service worker payment handlers.

This patch removes "https://play.google.com/billing" from the list of
payment methods for which service worker payment handlers should be
looked up.

After this patch, Chrome does not attempt to download manifests for the
Google Play Billing payment method.

Bug: 1062372
Change-Id: Ie16e1d0bcd5480677240a8551c8072258a266572
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2108849
Commit-Queue: Rouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: default avatarDanyao Wang <danyao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754955}
parent b5adc5a6
......@@ -10,6 +10,7 @@ source_set("browsertests") {
"has_enrolled_instrument_browsertest.cc",
"has_enrolled_instrument_query_quota_browsertest.cc",
"iframe_csp_browsertest.cc",
"ignore_payment_method_browsertest.cc",
"journey_logger_browsertest.cc",
"payment_handler_change_shipping_address_option_browsertest.cc",
"payment_handler_enable_delegations_browsertest.cc",
......@@ -28,6 +29,7 @@ source_set("browsertests") {
"//chrome/test:test_support",
"//chrome/test/payments:test_support",
"//components/payments/content",
"//components/payments/content:utils",
"//components/payments/core:test_support",
"//components/ukm:test_support",
]
......
// 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.
#include <string>
#include "build/build_config.h"
#include "chrome/test/payments/payment_request_platform_browsertest_base.h"
#include "components/payments/content/service_worker_payment_app_finder.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace payments {
namespace {
class IgnorePaymentMethodTest : public PaymentRequestPlatformBrowserTestBase {
protected:
void SetUpOnMainThread() override {
PaymentRequestPlatformBrowserTestBase::SetUpOnMainThread();
method_name_ = https_server()->GetURL("a.com", "/nickpay.com/pay").spec();
ASSERT_NE('/', method_name_[method_name_.length() - 1]);
}
void InstallTestPaymentHandler(const std::string& file_name) {
NavigateTo("a.com", "/payment_handler_installer.html");
ASSERT_EQ("success",
content::EvalJs(GetActiveWebContents(),
content::JsReplace("install($1, [$2], false)",
file_name, method_name_)));
}
void VerifyFunctionOutput(const std::string& expected_return_value,
const std::string& function_name) {
EXPECT_EQ(expected_return_value,
content::EvalJs(GetActiveWebContents(),
content::JsReplace(function_name, method_name_)));
}
std::string method_name_;
};
IN_PROC_BROWSER_TEST_F(IgnorePaymentMethodTest, InstalledPHCannotMakePayments) {
InstallTestPaymentHandler("can_make_payment_true_responder.js");
NavigateTo("b.com", "/can_make_payment_checker.html");
VerifyFunctionOutput("true", "canMakePayment($1)");
ServiceWorkerPaymentAppFinder::GetInstance()->IgnorePaymentMethodForTest(
method_name_);
VerifyFunctionOutput("false", "canMakePayment($1)");
}
IN_PROC_BROWSER_TEST_F(IgnorePaymentMethodTest,
InstalledPHHasNoEnrolledInstruments) {
InstallTestPaymentHandler("can_make_payment_true_responder.js");
NavigateTo("b.com", "/has_enrolled_instrument_checker.html");
VerifyFunctionOutput("true", "hasEnrolledInstrument($1)");
ServiceWorkerPaymentAppFinder::GetInstance()->IgnorePaymentMethodForTest(
method_name_);
VerifyFunctionOutput("false", "hasEnrolledInstrument($1)");
}
IN_PROC_BROWSER_TEST_F(IgnorePaymentMethodTest, InstalledPHCannotBeLaunched) {
InstallTestPaymentHandler("payment_request_success_responder.js");
NavigateTo("b.com", "/payment_handler_status.html");
VerifyFunctionOutput("success", "getStatus($1)");
ServiceWorkerPaymentAppFinder::GetInstance()->IgnorePaymentMethodForTest(
method_name_);
VerifyFunctionOutput(
"The payment method \"" + method_name_ + "\" is not supported.",
"getStatus($1)");
}
IN_PROC_BROWSER_TEST_F(IgnorePaymentMethodTest,
JITInstallablePHCannotMakePayments) {
NavigateTo("b.com", "/can_make_payment_checker.html");
VerifyFunctionOutput("true", "canMakePayment($1)");
ServiceWorkerPaymentAppFinder::GetInstance()->IgnorePaymentMethodForTest(
method_name_);
VerifyFunctionOutput("false", "canMakePayment($1)");
}
IN_PROC_BROWSER_TEST_F(IgnorePaymentMethodTest,
JITInstallablePHHasNoEnrolledInstruments) {
NavigateTo("b.com", "/has_enrolled_instrument_checker.html");
VerifyFunctionOutput(
#if defined(OS_ANDROID)
// TODO(crbug.com/994799#c2): Android should return "false" for
// hasEnrolledInstrument() of a JIT installable service worker payment
// handler.
"true",
#else
"false",
#endif
"hasEnrolledInstrument($1)");
ServiceWorkerPaymentAppFinder::GetInstance()->IgnorePaymentMethodForTest(
method_name_);
VerifyFunctionOutput("false", "hasEnrolledInstrument($1)");
}
IN_PROC_BROWSER_TEST_F(IgnorePaymentMethodTest,
JITInstallablePHCanBeInstalledAndLaunchedByDefault) {
NavigateTo("b.com", "/payment_handler_status.html");
VerifyFunctionOutput("success", "getStatus($1)");
}
IN_PROC_BROWSER_TEST_F(
IgnorePaymentMethodTest,
JITInstallablePHCannotBeInstalledAndLaunchedWhenIgnored) {
NavigateTo("b.com", "/payment_handler_status.html");
ServiceWorkerPaymentAppFinder::GetInstance()->IgnorePaymentMethodForTest(
method_name_);
VerifyFunctionOutput(
"The payment method \"" + method_name_ + "\" is not supported.",
"getStatus($1)");
}
} // namespace
} // namespace payments
......@@ -190,7 +190,7 @@ class ServiceWorkerPaymentAppFinderBrowserTest : public InProcessBrowserTest {
WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
Profile::FromBrowserContext(context),
ServiceAccessType::EXPLICIT_ACCESS),
method_data,
std::move(method_data),
/*may_crawl_for_installable_payment_apps=*/true,
base::BindOnce(
&ServiceWorkerPaymentAppFinderBrowserTest::OnGotAllPaymentApps,
......
......@@ -17,6 +17,18 @@
#include "content/public/browser/web_contents.h"
namespace payments {
namespace {
std::vector<mojom::PaymentMethodDataPtr> Clone(
const std::vector<mojom::PaymentMethodDataPtr>& original) {
std::vector<mojom::PaymentMethodDataPtr> clone(original.size());
std::transform(
original.begin(), original.end(), clone.begin(),
[](const mojom::PaymentMethodDataPtr& item) { return item.Clone(); });
return clone;
}
} // namespace
class ServiceWorkerPaymentAppCreator {
public:
......@@ -125,11 +137,12 @@ void ServiceWorkerPaymentAppFactory::Create(base::WeakPtr<Delegate> delegate) {
/*owner=*/this, delegate);
ServiceWorkerPaymentAppCreator* creator_raw_pointer = creator.get();
creators_[creator_raw_pointer] = std::move(creator);
ServiceWorkerPaymentAppFinder::GetInstance()->GetAllPaymentApps(
delegate->GetFrameSecurityOrigin(),
delegate->GetInitiatorRenderFrameHost(), delegate->GetWebContents(),
delegate->GetPaymentRequestDelegate()->GetPaymentManifestWebDataService(),
delegate->GetSpec()->method_data(),
Clone(delegate->GetSpec()->method_data()),
delegate->MayCrawlForInstallablePaymentApps(),
base::BindOnce(&ServiceWorkerPaymentAppCreator::CreatePaymentApps,
creator_raw_pointer->GetWeakPtr()),
......
......@@ -289,13 +289,27 @@ void ServiceWorkerPaymentAppFinder::GetAllPaymentApps(
content::RenderFrameHost* initiator_render_frame_host,
content::WebContents* web_contents,
scoped_refptr<PaymentManifestWebDataService> cache,
const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
std::vector<mojom::PaymentMethodDataPtr> requested_method_data,
bool may_crawl_for_installable_payment_apps,
GetAllPaymentAppsCallback callback,
base::OnceClosure finished_writing_cache_callback_for_testing) {
DCHECK(!requested_method_data.empty());
// Do not look up payment handlers for ignored payment methods.
base::EraseIf(requested_method_data,
[&](const mojom::PaymentMethodDataPtr& method_data) {
return base::Contains(ignored_methods_,
method_data->supported_method);
});
if (requested_method_data.empty()) {
std::move(callback).Run(
content::PaymentAppProvider::PaymentApps(),
std::map<GURL, std::unique_ptr<WebAppInstallationInfo>>(),
/*error_message=*/"");
return;
}
SelfDeletingServiceWorkerPaymentAppFinder* self_delete_factory =
new SelfDeletingServiceWorkerPaymentAppFinder();
std::unique_ptr<PaymentManifestDownloader> downloader;
if (test_downloader_ != nullptr) {
downloader = std::move(test_downloader_);
......@@ -329,10 +343,16 @@ void ServiceWorkerPaymentAppFinder::RemoveAppsWithoutMatchingMethodData(
}
}
void ServiceWorkerPaymentAppFinder::IgnorePaymentMethodForTest(
const std::string& method) {
ignored_methods_.insert(method);
}
ServiceWorkerPaymentAppFinder::ServiceWorkerPaymentAppFinder()
: test_downloader_(nullptr) {}
: ignored_methods_({methods::kGooglePlayBilling}),
test_downloader_(nullptr) {}
ServiceWorkerPaymentAppFinder::~ServiceWorkerPaymentAppFinder() {}
ServiceWorkerPaymentAppFinder::~ServiceWorkerPaymentAppFinder() = default;
void ServiceWorkerPaymentAppFinder::
SetDownloaderAndIgnorePortInOriginComparisonForTesting(
......
......@@ -74,7 +74,7 @@ class ServiceWorkerPaymentAppFinder {
content::RenderFrameHost* initiator_render_frame_host,
content::WebContents* web_contents,
scoped_refptr<PaymentManifestWebDataService> cache,
const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
std::vector<mojom::PaymentMethodDataPtr> requested_method_data,
bool may_crawl_for_installable_payment_apps,
GetAllPaymentAppsCallback callback,
base::OnceClosure finished_writing_cache_callback_for_testing);
......@@ -85,6 +85,11 @@ class ServiceWorkerPaymentAppFinder {
const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
content::PaymentAppProvider::PaymentApps* apps);
// Ignore the given |method|, so that no installed or installable service
// workers would ever be looked up in GetAllPaymentApps(). Calling this
// multiple times will union the new payment methods with the existing set.
void IgnorePaymentMethodForTest(const std::string& method);
private:
friend struct base::DefaultSingletonTraits<ServiceWorkerPaymentAppFinder>;
friend class PaymentRequestPaymentAppTest;
......@@ -100,6 +105,7 @@ class ServiceWorkerPaymentAppFinder {
void SetDownloaderAndIgnorePortInOriginComparisonForTesting(
std::unique_ptr<PaymentManifestDownloader> downloader);
std::set<std::string> ignored_methods_;
std::unique_ptr<PaymentManifestDownloader> test_downloader_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPaymentAppFinder);
......
<!DOCTYPE html>
<!--
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.
-->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
<title>Can Make Payment Checker</title>
</head>
<body>
<script src="can_make_payment_checker.js"></script>
</body>
</html>
/*
* 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.
*/
/**
* Checks whether the given payment method can make payments.
* @param {string} method - The payment method identifier to check.
* @return {string} - 'true', 'false', or error message on failure.
*/
async function canMakePayment(method) { // eslint-disable-line no-unused-vars, max-len
try {
const request = new PaymentRequest(
[{supportedMethods: method}],
{total: {label: 'TEST', amount: {currency: 'USD', value: '0.01'}}});
const result = await request.canMakePayment();
return result ? 'true' : 'false';
} catch (e) {
return e.message;
}
}
Just-in-time installable payment handler that serves the payment method manifest
directly at the payment method identifier URL
https://a.com:<port>/nickpay.com/pay and has a relative URL in
"default_applications". This payment handler always can make payments and
responds to a payment request with {"status": "success"}.
/*
* 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.
*/
self.addEventListener('canmakepayment', (event) => {
event.respondWith(true);
});
self.addEventListener('paymentrequest', (event) => {
event.respondWith({
methodName: event.methodData[0].supportedMethods,
details: {status: 'success'},
});
});
{
"name": "Nick Pay",
"icons": [{
"src": "icon.png",
"sizes": "40x40",
"type": "image/png"
}],
"serviceworker": {
"src": "app.js"
}
}
{
"default_applications": ["app.json"]
}
/*
* 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.
*/
self.addEventListener('canmakepayment', (evt) => {
evt.respondWith(true);
});
self.addEventListener('paymentrequest', (evt) => {
evt.respondWith({
methodName: evt.methodData[0].supportedMethods,
details: {status: 'success'},
});
});
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