Commit 85beea0a authored by Rouslan Solomakhin's avatar Rouslan Solomakhin Committed by Commit Bot

[Web Payment] Simple Android payment app factory.

Before this patch, the Android payment apps installed on Chrome OS would
not be available in Web Payment.

This patch queries the list of installed Android payment apps and
returns all of them to Web Payment, if
chrome://flags/#enable-web-payments-experimental-features is enabled.

After this patch, the Android payment apps installed on Chrome OS are
available in Web Payment.

Bug: 1061503
Change-Id: Ifb11741377a0a21166d77c547dbbad21b6daffeb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2302269
Commit-Queue: Rouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: default avatarDanyao Wang <danyao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798488}
parent 211b5b7b
...@@ -7,6 +7,7 @@ source_set("browsertests") { ...@@ -7,6 +7,7 @@ source_set("browsertests") {
sources = [ sources = [
"abort_payment_handler_browsertest.cc", "abort_payment_handler_browsertest.cc",
"android_payment_app_factory_browsertest.cc",
"colocated_payment_manifests_browsertest.cc", "colocated_payment_manifests_browsertest.cc",
"empty_parameters_browsertest.cc", "empty_parameters_browsertest.cc",
"has_enrolled_instrument_browsertest.cc", "has_enrolled_instrument_browsertest.cc",
......
// 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 "base/test/scoped_feature_list.h"
#include "chrome/test/payments/payment_request_platform_browsertest_base.h"
#include "components/payments/core/features.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 AndroidPaymentAppFactoryTest
: public PaymentRequestPlatformBrowserTestBase {
public:
AndroidPaymentAppFactoryTest() {
feature_list_.InitAndEnableFeature(features::kAppStoreBilling);
}
~AndroidPaymentAppFactoryTest() override = default;
private:
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(AndroidPaymentAppFactoryTest, SmokeTest) {
NavigateTo("a.com", "/app_store_billing_tests/index.html");
ASSERT_EQ("success", content::EvalJs(GetActiveWebContents(),
content::JsReplace(
"addSupportedMethod($1)",
"https://play.google.com/billing")));
ASSERT_EQ("success",
content::EvalJs(GetActiveWebContents(), "createPaymentRequest()"));
ASSERT_EQ("false",
content::EvalJs(GetActiveWebContents(), "canMakePayment()"));
}
} // namespace
} // namespace payments
...@@ -157,6 +157,7 @@ source_set("unit_tests") { ...@@ -157,6 +157,7 @@ source_set("unit_tests") {
sources = [ sources = [
"android_app_communication_test_support.h", "android_app_communication_test_support.h",
"android_app_communication_unittest.cc", "android_app_communication_unittest.cc",
"android_payment_app_factory_unittest.cc",
"android_payment_app_unittest.cc", "android_payment_app_unittest.cc",
"payment_method_manifest_table_unittest.cc", "payment_method_manifest_table_unittest.cc",
"service_worker_payment_app_finder_unittest.cc", "service_worker_payment_app_finder_unittest.cc",
......
...@@ -4,12 +4,28 @@ ...@@ -4,12 +4,28 @@
#include "components/payments/content/android_payment_app_factory.h" #include "components/payments/content/android_payment_app_factory.h"
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility> #include <utility>
#include <vector>
#include "base/bind.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/stl_util.h"
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "components/payments/content/android_app_communication.h"
#include "components/payments/content/android_payment_app.h"
#include "components/payments/content/payment_request_spec.h"
#include "components/payments/core/android_app_description.h"
#include "components/payments/core/android_app_description_tools.h"
#include "components/payments/core/method_strings.h"
#include "components/payments/core/native_error_strings.h"
#include "components/payments/core/payment_request_data_util.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_document_host_user_data.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
namespace payments { namespace payments {
...@@ -34,17 +50,69 @@ class AppFinder : public base::SupportsUserData::Data { ...@@ -34,17 +50,69 @@ class AppFinder : public base::SupportsUserData::Data {
AppFinder(const AppFinder& other) = delete; AppFinder(const AppFinder& other) = delete;
AppFinder& operator=(const AppFinder& other) = delete; AppFinder& operator=(const AppFinder& other) = delete;
void FindApps(base::WeakPtr<PaymentAppFactory::Delegate> delegate) { void FindApps(base::WeakPtr<AndroidAppCommunication> communication,
base::WeakPtr<PaymentAppFactory::Delegate> delegate) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK_EQ(nullptr, delegate_.get()); DCHECK_EQ(nullptr, delegate_.get());
DCHECK_NE(nullptr, delegate.get()); DCHECK_NE(nullptr, delegate.get());
DCHECK_EQ(nullptr, communication_.get());
DCHECK_NE(nullptr, communication.get());
DCHECK(delegate->GetSpec()->details().id.has_value());
delegate_ = delegate; delegate_ = delegate;
communication_ = communication;
OnDoneCreatingPaymentApps(); communication_->GetAppDescriptions(
delegate_->GetTwaPackageName(),
base::BindOnce(&AppFinder::OnGetAppDescriptions,
weak_ptr_factory_.GetWeakPtr()));
} }
private: private:
void OnGetAppDescriptions(
const base::Optional<std::string>& error_message,
std::vector<std::unique_ptr<AndroidAppDescription>> app_descriptions) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// The browser could be shutting down.
if (!communication_ || !delegate_)
return;
if (error_message.has_value()) {
delegate_->OnPaymentAppCreationError(error_message.value());
OnDoneCreatingPaymentApps();
return;
}
std::vector<std::unique_ptr<AndroidAppDescription>> single_activity_apps;
for (size_t i = 0; i < app_descriptions.size(); ++i) {
auto app = std::move(app_descriptions[i]);
SplitPotentiallyMultipleActivities(std::move(app), &single_activity_apps);
}
for (size_t i = 0; i < single_activity_apps.size(); ++i) {
auto app = std::move(single_activity_apps[i]);
const std::string& default_method =
app->activities.front()->default_payment_method;
DCHECK_EQ(methods::kGooglePlayBilling, default_method);
std::set<std::string> supported_payment_methods = {default_method};
delegate_->OnPaymentAppCreated(std::make_unique<AndroidPaymentApp>(
base::STLSetIntersection<std::set<std::string>>(
delegate_->GetSpec()->payment_method_identifiers_set(),
supported_payment_methods),
data_util::FilterStringifiedMethodData(
delegate_->GetSpec()->stringified_method_data(),
supported_payment_methods),
delegate_->GetTopOrigin(), delegate_->GetFrameOrigin(),
delegate_->GetSpec()->details().id.value(), std::move(app),
communication_));
}
OnDoneCreatingPaymentApps();
}
void OnDoneCreatingPaymentApps() { void OnDoneCreatingPaymentApps() {
if (delegate_) if (delegate_)
delegate_->OnDoneCreatingPaymentApps(); delegate_->OnDoneCreatingPaymentApps();
...@@ -54,20 +122,25 @@ class AppFinder : public base::SupportsUserData::Data { ...@@ -54,20 +122,25 @@ class AppFinder : public base::SupportsUserData::Data {
base::SupportsUserData* owner_; base::SupportsUserData* owner_;
base::WeakPtr<PaymentAppFactory::Delegate> delegate_; base::WeakPtr<PaymentAppFactory::Delegate> delegate_;
base::WeakPtr<AndroidAppCommunication> communication_;
base::WeakPtrFactory<AppFinder> weak_ptr_factory_{this}; base::WeakPtrFactory<AppFinder> weak_ptr_factory_{this};
}; };
} // namespace } // namespace
AndroidPaymentAppFactory::AndroidPaymentAppFactory() AndroidPaymentAppFactory::AndroidPaymentAppFactory(
: PaymentAppFactory(PaymentApp::Type::NATIVE_MOBILE_APP) {} base::WeakPtr<AndroidAppCommunication> communication)
: PaymentAppFactory(PaymentApp::Type::NATIVE_MOBILE_APP),
communication_(communication) {
DCHECK(communication_);
}
AndroidPaymentAppFactory::~AndroidPaymentAppFactory() = default; AndroidPaymentAppFactory::~AndroidPaymentAppFactory() = default;
void AndroidPaymentAppFactory::Create(base::WeakPtr<Delegate> delegate) { void AndroidPaymentAppFactory::Create(base::WeakPtr<Delegate> delegate) {
auto app_finder = AppFinder::CreateAndSetOwnedBy(delegate->GetWebContents()); auto app_finder = AppFinder::CreateAndSetOwnedBy(delegate->GetWebContents());
app_finder->FindApps(delegate); app_finder->FindApps(communication_, delegate);
} }
} // namespace payments } // namespace payments
...@@ -5,14 +5,20 @@ ...@@ -5,14 +5,20 @@
#ifndef COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_APP_FACTORY_H_ #ifndef COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_APP_FACTORY_H_
#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_APP_FACTORY_H_ #define COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_APP_FACTORY_H_
#include "base/memory/weak_ptr.h"
#include "components/payments/content/payment_app_factory.h" #include "components/payments/content/payment_app_factory.h"
namespace payments { namespace payments {
class AndroidAppCommunication;
// Retrieves Android payment apps. // Retrieves Android payment apps.
class AndroidPaymentAppFactory : public PaymentAppFactory { class AndroidPaymentAppFactory : public PaymentAppFactory {
public: public:
AndroidPaymentAppFactory(); // The given |communication| is used for communication with Android payment
// apps.
explicit AndroidPaymentAppFactory(
base::WeakPtr<AndroidAppCommunication> communication);
~AndroidPaymentAppFactory() override; ~AndroidPaymentAppFactory() override;
AndroidPaymentAppFactory(const AndroidPaymentAppFactory& other) = delete; AndroidPaymentAppFactory(const AndroidPaymentAppFactory& other) = delete;
...@@ -21,6 +27,9 @@ class AndroidPaymentAppFactory : public PaymentAppFactory { ...@@ -21,6 +27,9 @@ class AndroidPaymentAppFactory : public PaymentAppFactory {
// PaymentAppFactory: // PaymentAppFactory:
void Create(base::WeakPtr<Delegate> delegate) override; void Create(base::WeakPtr<Delegate> delegate) override;
private:
base::WeakPtr<AndroidAppCommunication> communication_;
}; };
} // namespace payments } // namespace payments
......
// 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 "components/payments/content/android_payment_app_factory.h"
#include <utility>
#include "base/memory/weak_ptr.h"
#include "base/stl_util.h"
#include "components/payments/content/android_app_communication.h"
#include "components/payments/content/android_app_communication_test_support.h"
#include "components/payments/content/payment_app_factory.h"
#include "components/payments/content/payment_manifest_web_data_service.h"
#include "components/payments/content/payment_request_spec.h"
#include "components/payments/core/android_app_description.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_web_contents_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
class BrowserContext;
} // namespace content
namespace payments {
namespace {
// A mock delegate for payment app factories.
class MockPaymentAppFactoryDelegate : public PaymentAppFactory::Delegate {
public:
explicit MockPaymentAppFactoryDelegate(content::BrowserContext* context)
: web_contents_(web_contents_factory_.CreateWebContents(context)),
top_origin_("https://top-origin.test"),
frame_origin_("https://frame-origin.test") {
auto details = mojom::PaymentDetails::New();
details->id = "id";
std::vector<mojom::PaymentMethodDataPtr> methods;
methods.emplace_back(mojom::PaymentMethodData::New());
methods.back()->supported_method = "https://play.google.com/billing";
methods.back()->stringified_data = "{}";
spec_ = std::make_unique<PaymentRequestSpec>(
mojom::PaymentOptions::New(), std::move(details), std::move(methods),
/*observer=*/nullptr, /*app_locale=*/"en-US");
}
~MockPaymentAppFactoryDelegate() override = default;
// PaymentAppFactory::Delegate implementation:
content::WebContents* GetWebContents() override { return web_contents_; }
const GURL& GetTopOrigin() override { return top_origin_; }
const GURL& GetFrameOrigin() override { return frame_origin_; }
MOCK_METHOD0(GetFrameSecurityOrigin, const url::Origin&());
MOCK_CONST_METHOD0(GetInitiatorRenderFrameHost, content::RenderFrameHost*());
MOCK_CONST_METHOD0(GetMethodData,
const std::vector<mojom::PaymentMethodDataPtr>&());
MOCK_CONST_METHOD0(GetPaymentManifestWebDataService,
scoped_refptr<PaymentManifestWebDataService>());
MOCK_METHOD0(MayCrawlForInstallablePaymentApps, bool());
MOCK_CONST_METHOD0(IsOffTheRecord, bool());
PaymentRequestSpec* GetSpec() const override { return spec_.get(); }
MOCK_CONST_METHOD0(GetTwaPackageName, std::string());
MOCK_METHOD0(ShowProcessingSpinner, void());
MOCK_METHOD0(GetBillingProfiles,
const std::vector<autofill::AutofillProfile*>&());
MOCK_METHOD0(IsRequestedAutofillDataAvailable, bool());
MOCK_CONST_METHOD0(GetPaymentRequestDelegate,
ContentPaymentRequestDelegate*());
MOCK_METHOD1(OnPaymentAppCreated, void(std::unique_ptr<PaymentApp> app));
MOCK_METHOD1(OnPaymentAppCreationError,
void(const std::string& error_message));
MOCK_CONST_METHOD0(SkipCreatingNativePaymentApps, bool());
MOCK_METHOD0(OnDoneCreatingPaymentApps, void());
base::WeakPtr<PaymentAppFactory::Delegate> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private:
content::TestWebContentsFactory web_contents_factory_;
content::WebContents* web_contents_;
GURL top_origin_;
GURL frame_origin_;
std::unique_ptr<PaymentRequestSpec> spec_;
base::WeakPtrFactory<PaymentAppFactory::Delegate> weak_ptr_factory_{this};
};
// The scaffolding for testing the Android payment app factory.
class AndroidPaymentAppFactoryTest : public testing::Test {
public:
AndroidPaymentAppFactoryTest()
: support_(AndroidAppCommunicationTestSupport::Create()),
delegate_(support_->context()),
factory_(GetCommunication(support_->context())) {}
std::unique_ptr<AndroidAppCommunicationTestSupport> support_;
MockPaymentAppFactoryDelegate delegate_;
AndroidPaymentAppFactory factory_;
private:
// Returns the Android app communication that can be used in unit tests.
static base::WeakPtr<AndroidAppCommunication> GetCommunication(
content::BrowserContext* context) {
base::WeakPtr<AndroidAppCommunication> communication =
AndroidAppCommunication::GetForBrowserContext(context);
communication->SetForTesting();
return communication;
}
};
// The payment app factory should return an error if it's unable to invoke
// Aneroid payment apps on a platform that supports such apps, e.g, when ARC is
// disabled on Chrome OS.
TEST_F(AndroidPaymentAppFactoryTest, NoArc) {
EXPECT_CALL(delegate_, GetTwaPackageName())
.WillRepeatedly(testing::Return("com.example.app"));
EXPECT_CALL(delegate_, OnDoneCreatingPaymentApps());
EXPECT_CALL(delegate_,
OnPaymentAppCreationError("Unable to invoke Android apps."))
.Times(support_->AreAndroidAppsSupportedOnThisPlatform() ? 1 : 0);
EXPECT_CALL(delegate_, OnPaymentAppCreated(testing::_)).Times(0);
support_->ExpectNoListOfPaymentAppsQuery();
factory_.Create(delegate_.GetWeakPtr());
}
// The payment app factory should not return any errors when there're no Android
// payment apps available.
TEST_F(AndroidPaymentAppFactoryTest, NoApps) {
// Enable invoking Android payment apps on those platforms that support it.
auto scoped_initialization_ = support_->CreateScopedInitialization();
EXPECT_CALL(delegate_, GetTwaPackageName())
.WillRepeatedly(testing::Return("com.example.app"));
EXPECT_CALL(delegate_, OnDoneCreatingPaymentApps());
EXPECT_CALL(delegate_, OnPaymentAppCreationError(testing::_)).Times(0);
EXPECT_CALL(delegate_, OnPaymentAppCreated(testing::_)).Times(0);
support_->ExpectQueryListOfPaymentAppsAndRespond({});
factory_.Create(delegate_.GetWeakPtr());
}
// The |arg| is of type std::unique_ptr<PaymentApp>.
MATCHER_P3(PaymentAppMatches, type, package, method, "") {
return arg->type() == type && arg->GetId() == package &&
base::Contains(arg->GetAppMethodNames(), method);
}
// The payment app factory should return the TWA payment app when running in TWA
// mode.
TEST_F(AndroidPaymentAppFactoryTest, TheOnlyTwaPaymentAppWhenRunningInTwaMode) {
// Enable invoking Android payment apps on those platforms that support it.
auto scoped_initialization_ = support_->CreateScopedInitialization();
EXPECT_CALL(delegate_, GetTwaPackageName())
.WillRepeatedly(testing::Return("com.twa.app"));
EXPECT_CALL(delegate_, OnDoneCreatingPaymentApps());
EXPECT_CALL(delegate_, OnPaymentAppCreationError(testing::_)).Times(0);
EXPECT_CALL(delegate_, OnPaymentAppCreated(PaymentAppMatches(
PaymentApp::Type::NATIVE_MOBILE_APP, "com.twa.app",
"https://play.google.com/billing")))
.Times(support_->AreAndroidAppsSupportedOnThisPlatform() ? 1 : 0);
std::vector<std::unique_ptr<AndroidAppDescription>> apps;
apps.emplace_back(std::make_unique<AndroidAppDescription>());
apps.back()->package = "com.twa.app";
apps.back()->service_names.push_back("com.twa.app.Service");
apps.back()->activities.emplace_back(
std::make_unique<AndroidActivityDescription>());
apps.back()->activities.back()->name = "com.twa.app.Activity";
apps.back()->activities.back()->default_payment_method =
"https://play.google.com/billing";
support_->ExpectQueryListOfPaymentAppsAndRespond(std::move(apps));
factory_.Create(delegate_.GetWeakPtr());
}
// The payment app factory should return the correct TWA payment app out of two
// installed TWA payment apps, when running in TWA mode.
TEST_F(AndroidPaymentAppFactoryTest, CorrectTwaPaymentAppWhenRunningInTwaMode) {
// Enable invoking Android payment apps on those platforms that support it.
auto scoped_initialization_ = support_->CreateScopedInitialization();
EXPECT_CALL(delegate_, GetTwaPackageName())
.WillRepeatedly(testing::Return("com.correct-twa.app"));
EXPECT_CALL(delegate_, OnDoneCreatingPaymentApps());
EXPECT_CALL(delegate_, OnPaymentAppCreationError(testing::_)).Times(0);
EXPECT_CALL(delegate_,
OnPaymentAppCreated(PaymentAppMatches(
PaymentApp::Type::NATIVE_MOBILE_APP, "com.correct-twa.app",
"https://play.google.com/billing")))
.Times(support_->AreAndroidAppsSupportedOnThisPlatform() ? 1 : 0);
EXPECT_CALL(delegate_,
OnPaymentAppCreated(PaymentAppMatches(
PaymentApp::Type::NATIVE_MOBILE_APP, "com.different-twa.app",
"https://play.google.com/billing")))
.Times(0);
std::vector<std::unique_ptr<AndroidAppDescription>> apps;
apps.emplace_back(std::make_unique<AndroidAppDescription>());
apps.back()->package = "com.correct-twa.app";
apps.back()->service_names.push_back("com.correct-twa.app.Service");
apps.back()->activities.emplace_back(
std::make_unique<AndroidActivityDescription>());
apps.back()->activities.back()->name = "com.correct-twa.app.Activity";
apps.back()->activities.back()->default_payment_method =
"https://play.google.com/billing";
apps.emplace_back(std::make_unique<AndroidAppDescription>());
apps.back()->package = "com.different-twa.app";
apps.back()->service_names.push_back("com.different-twa.app.Service");
apps.back()->activities.emplace_back(
std::make_unique<AndroidActivityDescription>());
apps.back()->activities.back()->name = "com.different-twa.app.Activity";
apps.back()->activities.back()->default_payment_method =
"https://play.google.com/billing";
support_->ExpectQueryListOfPaymentAppsAndRespond(std::move(apps));
factory_.Create(delegate_.GetWeakPtr());
}
// The payment app factory does not return non-TWA payment apps when running in
// TWA mode.
TEST_F(AndroidPaymentAppFactoryTest, NonTwaPaymentAppWhenRunningInTwaMode) {
// Enable invoking Android payment apps on those platforms that support it.
auto scoped_initialization_ = support_->CreateScopedInitialization();
EXPECT_CALL(delegate_, GetTwaPackageName())
.WillRepeatedly(testing::Return("com.twa.app"));
EXPECT_CALL(delegate_, OnDoneCreatingPaymentApps());
EXPECT_CALL(delegate_, OnPaymentAppCreationError(testing::_)).Times(0);
EXPECT_CALL(delegate_, OnPaymentAppCreated(testing::_)).Times(0);
std::vector<std::unique_ptr<AndroidAppDescription>> apps;
apps.emplace_back(std::make_unique<AndroidAppDescription>());
apps.back()->package = "com.non-twa.app";
apps.back()->service_names.push_back("com.non-twa.app.Service");
apps.back()->activities.emplace_back(
std::make_unique<AndroidActivityDescription>());
apps.back()->activities.back()->name = "com.non-twa.app.Activity";
apps.back()->activities.back()->default_payment_method =
"https://play.google.com/billing";
support_->ExpectQueryListOfPaymentAppsAndRespond(std::move(apps));
factory_.Create(delegate_.GetWeakPtr());
}
// The payment app factory does not return any payment apps when not running
// inside of TWA.
TEST_F(AndroidPaymentAppFactoryTest, NonTwaPaymentAppWhenNotRunningInTwaMode) {
// Enable invoking Android payment apps on those platforms that support it.
auto scoped_initialization_ = support_->CreateScopedInitialization();
EXPECT_CALL(delegate_, GetTwaPackageName())
.WillRepeatedly(testing::Return(""));
EXPECT_CALL(delegate_, OnDoneCreatingPaymentApps());
EXPECT_CALL(delegate_, OnPaymentAppCreationError(testing::_)).Times(0);
EXPECT_CALL(delegate_, OnPaymentAppCreated(testing::_)).Times(0);
support_->ExpectNoListOfPaymentAppsQuery();
factory_.Create(delegate_.GetWeakPtr());
}
} // namespace
} // namespace payments
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "components/payments/content/payment_app_service.h" #include "components/payments/content/payment_app_service.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "components/payments/content/android_app_communication.h"
#include "components/payments/content/android_payment_app_factory.h" #include "components/payments/content/android_payment_app_factory.h"
#include "components/payments/content/autofill_payment_app_factory.h" #include "components/payments/content/autofill_payment_app_factory.h"
#include "components/payments/content/payment_app.h" #include "components/payments/content/payment_app.h"
...@@ -15,7 +16,7 @@ ...@@ -15,7 +16,7 @@
namespace payments { namespace payments {
PaymentAppService::PaymentAppService() { PaymentAppService::PaymentAppService(content::BrowserContext* context) {
factories_.emplace_back(std::make_unique<AutofillPaymentAppFactory>()); factories_.emplace_back(std::make_unique<AutofillPaymentAppFactory>());
if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) { if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
...@@ -27,7 +28,8 @@ PaymentAppService::PaymentAppService() { ...@@ -27,7 +28,8 @@ PaymentAppService::PaymentAppService() {
// apps. (Currently it works only on Chrome OS with app store billing payment // apps. (Currently it works only on Chrome OS with app store billing payment
// methods.) // methods.)
if (PaymentsExperimentalFeatures::IsEnabled(features::kAppStoreBilling)) { if (PaymentsExperimentalFeatures::IsEnabled(features::kAppStoreBilling)) {
factories_.emplace_back(std::make_unique<AndroidPaymentAppFactory>()); factories_.emplace_back(std::make_unique<AndroidPaymentAppFactory>(
AndroidAppCommunication::GetForBrowserContext(context)));
} }
} }
......
...@@ -14,12 +14,17 @@ ...@@ -14,12 +14,17 @@
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "components/payments/content/payment_app_factory.h" #include "components/payments/content/payment_app_factory.h"
namespace content {
class BrowserContext;
} // namespace content
namespace payments { namespace payments {
// Retrieves payment apps of all types. // Retrieves payment apps of all types.
class PaymentAppService : public KeyedService { class PaymentAppService : public KeyedService {
public: public:
PaymentAppService(); // The |context| pointer is not being saved.
explicit PaymentAppService(content::BrowserContext* context);
~PaymentAppService() override; ~PaymentAppService() override;
// Returns the number of payment app factories, which is the number of times // Returns the number of payment app factories, which is the number of times
......
...@@ -43,7 +43,7 @@ PaymentAppServiceFactory::~PaymentAppServiceFactory() = default; ...@@ -43,7 +43,7 @@ PaymentAppServiceFactory::~PaymentAppServiceFactory() = default;
KeyedService* PaymentAppServiceFactory::BuildServiceInstanceFor( KeyedService* PaymentAppServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const { content::BrowserContext* context) const {
return new PaymentAppService(); return new PaymentAppService(context);
} }
content::BrowserContext* PaymentAppServiceFactory::GetBrowserContextToUse( content::BrowserContext* PaymentAppServiceFactory::GetBrowserContextToUse(
......
...@@ -78,7 +78,7 @@ class PaymentRequestStateTest : public testing::Test, ...@@ -78,7 +78,7 @@ class PaymentRequestStateTest : public testing::Test,
std::move(options), std::move(details), std::move(method_data), std::move(options), std::move(details), std::move(method_data),
/*observer=*/nullptr, "en-US"); /*observer=*/nullptr, "en-US");
PaymentAppServiceFactory::SetForTesting( PaymentAppServiceFactory::SetForTesting(
std::make_unique<PaymentAppService>()); std::make_unique<PaymentAppService>(/*context=*/nullptr));
state_ = std::make_unique<PaymentRequestState>( state_ = std::make_unique<PaymentRequestState>(
/*web_contents=*/nullptr, /*web_contents=*/nullptr,
/*render_frame_host=*/nullptr, GURL("https://example.com"), /*render_frame_host=*/nullptr, GURL("https://example.com"),
......
...@@ -69,6 +69,21 @@ function createPaymentRequest() { // eslint-disable-line no-unused-vars ...@@ -69,6 +69,21 @@ function createPaymentRequest() { // eslint-disable-line no-unused-vars
return 'success'; return 'success';
} }
/**
* Check whether payments can be made.
* @return {string} - "true", "false", or an error message.
*/
async function canMakePayment() { // eslint-disable-line no-unused-vars
info('canMakePayment');
try {
const result = await request.canMakePayment();
return (result ? 'true' : 'false');
} catch (e) {
info('canMakePayment error: ' + e.toString());
return e.toString();
}
}
/** /**
* Show the payment sheet. * Show the payment sheet.
* @return {string} - a message indicating whether the operation is successful. * @return {string} - a message indicating whether the operation is successful.
......
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