Commit 5b6eafb8 authored by Danyao Wang's avatar Danyao Wang Committed by Commit Bot

[Web Payments] Add a PaymentAppServiceBridge JNI interface.

The bridge implements PaymentAppFactoryInterface on the Java side and
acts as a PaymentAppFactory::Delegate on the C++ side to allow Java to
invoke C++ PaymentAppService.

This patch sets up the basic scaffolding. A subsequent CL will fill in
the actual onPaymentAppCreated() callback, which is the most substantial
part of the bridge.

Bug: 1063118
Change-Id: Ie3b93b719712b9b95865ee769415c4cd91d35392
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2133120Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Danyao Wang <danyao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756257}
parent 3acc9549
......@@ -1302,6 +1302,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryInterface.java",
"java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java",
"java/src/org/chromium/chrome/browser/payments/PaymentAppService.java",
"java/src/org/chromium/chrome/browser/payments/PaymentAppServiceBridge.java",
"java/src/org/chromium/chrome/browser/payments/PaymentManifestVerifier.java",
"java/src/org/chromium/chrome/browser/payments/PaymentManifestWebDataService.java",
"java/src/org/chromium/chrome/browser/payments/PaymentPreferencesUtil.java",
......
// 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.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.content_public.browser.RenderFrameHost;
import java.nio.ByteBuffer;
/**
* Native bridge for finding payment apps.
*/
public class PaymentAppServiceBridge implements PaymentAppFactoryInterface {
/* package */ PaymentAppServiceBridge() {}
// PaymentAppFactoryInterface implementation.
@Override
public void create(PaymentAppFactoryDelegate delegate) {
assert (delegate.getParams().getRenderFrameHost().getLastCommittedURL().equals(
delegate.getParams().getPaymentRequestOrigin()));
PaymentAppServiceCallback callback = new PaymentAppServiceCallback(delegate);
PaymentAppServiceBridgeJni.get().create(delegate.getParams().getRenderFrameHost(),
delegate.getParams().getTopLevelOrigin(),
delegate.getParams()
.getMethodData()
.values()
.stream()
.map(data -> data.serialize())
.toArray(ByteBuffer[] ::new),
delegate.getParams().getMayCrawl(), callback);
}
/** Handles callbacks from native PaymentAppService and creates PaymentApps. */
public class PaymentAppServiceCallback {
private final PaymentAppFactoryDelegate mDelegate;
private boolean mCanMakePayment;
private PaymentAppServiceCallback(PaymentAppFactoryDelegate delegate) {
mDelegate = delegate;
mCanMakePayment = false;
}
@CalledByNative("PaymentAppServiceCallback")
private void onPaymentAppCreated() {
ThreadUtils.assertOnUiThread();
mCanMakePayment = true;
// TODO(crbug.com/1063118): call mDelegate.onPaymentAppCreated().
}
@CalledByNative("PaymentAppServiceCallback")
private void onPaymentAppCreationError(String errorMessage) {
ThreadUtils.assertOnUiThread();
mDelegate.onPaymentAppCreationError(errorMessage);
}
// Expect to be called exactly once
@CalledByNative("PaymentAppServiceCallback")
private void onDoneCreatingPaymentApps() {
ThreadUtils.assertOnUiThread();
mDelegate.onCanMakePaymentCalculated(mCanMakePayment);
mDelegate.onDoneCreatingPaymentApps(PaymentAppServiceBridge.this);
}
}
@NativeMethods
/* package */ interface Natives {
void create(RenderFrameHost initiatorRenderFrameHost, String topOrigin,
ByteBuffer[] methodData, boolean mayCrawlForInstallablePaymentApps,
PaymentAppServiceCallback callback);
}
}
......@@ -2924,6 +2924,8 @@ jumbo_static_library("browser") {
"payments/android/can_make_payment_query_android.cc",
"payments/android/journey_logger_android.cc",
"payments/android/journey_logger_android.h",
"payments/android/payment_app_service_bridge.cc",
"payments/android/payment_app_service_bridge.h",
"payments/android/payment_manifest_web_data_service_android.cc",
"payments/android/payment_manifest_web_data_service_android.h",
"payments/android/service_worker_payment_app_bridge.cc",
......
......@@ -72,9 +72,13 @@ source_set("unittests") {
if (is_android) {
sources += [
"android/android_payment_app_finder_unittest.cc",
"android/payment_app_service_bridge_unittest.cc",
"android/payment_manifest_verifier_unittest.cc",
]
deps += [ "//chrome/android:native_j_unittests_jni_headers" ]
deps += [
"//chrome/android:native_j_unittests_jni_headers",
"//components/payments/content:utils",
]
}
}
......@@ -12,6 +12,7 @@ generate_jni("jni_headers") {
sources = [
"../../../android/java/src/org/chromium/chrome/browser/payments/CanMakePaymentQuery.java",
"../../../android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java",
"../../../android/java/src/org/chromium/chrome/browser/payments/PaymentAppServiceBridge.java",
"../../../android/java/src/org/chromium/chrome/browser/payments/PaymentManifestWebDataService.java",
"../../../android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java",
"../../../android/java/src/org/chromium/chrome/browser/payments/SslValidityChecker.java",
......
This diff is collapsed.
// 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.
#ifndef CHROME_BROWSER_PAYMENTS_ANDROID_PAYMENT_APP_SERVICE_BRIDGE_H_
#define CHROME_BROWSER_PAYMENTS_ANDROID_PAYMENT_APP_SERVICE_BRIDGE_H_
#include <map>
#include <memory>
#include <vector>
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "components/payments/content/payment_app_factory.h"
#include "url/gurl.h"
#include "url/origin.h"
class GURL;
namespace autofill {
class AutofillProfile;
} // namespace autofill
namespace content {
class RenderFrameHost;
class WebContents;
} // namespace content
namespace payments {
// A bridge that holds parameters needed by PaymentAppService and redirects
// callbacks from PaymentAppFactory to callbacks set by the caller.
class PaymentAppServiceBridge : public PaymentAppFactory::Delegate {
public:
// TODO(crbug.com/1063118): add more parameter to this callback to actually
// pass payment app data back to Java side.
using PaymentAppCreatedCallback = base::RepeatingCallback<void()>;
using PaymentAppCreationErrorCallback =
base::RepeatingCallback<void(const std::string&)>;
// Creates a new PaymentAppServiceBridge. This object is self-deleting; its
// memory is freed when OnDoneCreatingPaymentApps() is called
// |number_of_factories| times.
static PaymentAppServiceBridge* Create(
size_t number_of_factories,
content::RenderFrameHost* render_frame_host,
const GURL& top_origin,
std::vector<mojom::PaymentMethodDataPtr> request_method_data,
scoped_refptr<PaymentManifestWebDataService> web_data_service,
bool may_crawl_for_installable_payment_apps,
PaymentAppCreatedCallback payment_app_created_callback,
PaymentAppCreationErrorCallback payment_app_creation_error_callback,
base::OnceClosure done_creating_payment_apps_callback);
~PaymentAppServiceBridge() override;
// Not copiable or movable.
PaymentAppServiceBridge(const PaymentAppServiceBridge&) = delete;
PaymentAppServiceBridge& operator=(const PaymentAppServiceBridge&) = delete;
base::WeakPtr<PaymentAppServiceBridge> GetWeakPtr();
// PaymentAppFactory::Delegate
content::WebContents* GetWebContents() override;
const GURL& GetTopOrigin() override;
const GURL& GetFrameOrigin() override;
const url::Origin& GetFrameSecurityOrigin() override;
content::RenderFrameHost* GetInitiatorRenderFrameHost() const override;
const std::vector<mojom::PaymentMethodDataPtr>& GetMethodData()
const override;
scoped_refptr<PaymentManifestWebDataService>
GetPaymentManifestWebDataService() const override;
bool MayCrawlForInstallablePaymentApps() override;
const std::vector<autofill::AutofillProfile*>& GetBillingProfiles() override;
bool IsRequestedAutofillDataAvailable() override;
ContentPaymentRequestDelegate* GetPaymentRequestDelegate() const override;
PaymentRequestSpec* GetSpec() const override;
void OnPaymentAppInstalled(const url::Origin& origin,
int64_t registration_id) override;
void OnPaymentAppCreated(std::unique_ptr<PaymentApp> app) override;
void OnPaymentAppCreationError(const std::string& error_message) override;
bool SkipCreatingNativePaymentApps() const override;
void OnCreatingNativePaymentAppsSkipped(
const content::PaymentAppProvider::PaymentApps& apps,
const ServiceWorkerPaymentAppFinder::InstallablePaymentApps&
installable_apps) override;
void OnDoneCreatingPaymentApps() override;
private:
// Prevents direct instantiation. Callers should use Create() instead.
PaymentAppServiceBridge(
size_t number_of_factories,
content::RenderFrameHost* render_frame_host,
const GURL& top_origin,
std::vector<mojom::PaymentMethodDataPtr> request_method_data,
scoped_refptr<PaymentManifestWebDataService> web_data_service,
bool may_crawl_for_installable_payment_apps,
PaymentAppCreatedCallback payment_app_created_callback,
PaymentAppCreationErrorCallback payment_app_creation_error_callback,
base::OnceClosure done_creating_payment_apps_callback);
size_t number_of_pending_factories_;
content::WebContents* web_contents_;
content::RenderFrameHost* render_frame_host_;
const GURL top_origin_;
const GURL frame_origin_;
const url::Origin frame_security_origin_;
std::vector<mojom::PaymentMethodDataPtr> request_method_data_;
scoped_refptr<PaymentManifestWebDataService>
payment_manifest_web_data_service_;
bool may_crawl_for_installable_payment_apps_;
std::vector<autofill::AutofillProfile*> dummy_profiles_;
PaymentAppCreatedCallback payment_app_created_callback_;
PaymentAppCreationErrorCallback payment_app_creation_error_callback_;
base::OnceClosure done_creating_payment_apps_callback_;
base::WeakPtrFactory<PaymentAppServiceBridge> weak_ptr_factory_{this};
};
} // namespace payments
#endif // CHROME_BROWSER_PAYMENTS_ANDROID_PAYMENT_APP_SERVICE_BRIDGE_H_
// 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 "chrome/browser/payments/android/payment_app_service_bridge.h"
#include <vector>
#include "base/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/test/base/testing_profile.h"
#include "components/payments/content/payment_manifest_web_data_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/navigation_simulator.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 "third_party/blink/public/mojom/payments/payment_app.mojom.h"
namespace payments {
class MockCallback {
public:
MockCallback() = default;
MOCK_METHOD0(NotifyPaymentAppCreated, void(void));
MOCK_METHOD1(NotifyPaymentAppCreationError, void(const std::string& error));
MOCK_METHOD0(NotifyDoneCreatingPaymentApps, void(void));
};
class PaymentAppServiceBridgeUnitTest : public ::testing::Test {
public:
PaymentAppServiceBridgeUnitTest()
: top_origin_("https://shop.example"),
frame_origin_("https://merchant.example") {
web_contents_ =
test_web_contents_factory_.CreateWebContents(&browser_context_);
content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents_,
frame_origin_);
}
mojom::PaymentMethodDataPtr MakePaymentMethodData(
const std::string& supported_method) {
mojom::PaymentMethodDataPtr out = mojom::PaymentMethodData::New();
out->supported_method = supported_method;
return out;
}
protected:
content::BrowserTaskEnvironment task_environment_;
TestingProfile browser_context_;
content::TestWebContentsFactory test_web_contents_factory_;
content::WebContents* web_contents_;
GURL top_origin_;
GURL frame_origin_;
scoped_refptr<PaymentManifestWebDataService> web_data_service_;
};
TEST_F(PaymentAppServiceBridgeUnitTest, Smoke) {
std::vector<mojom::PaymentMethodDataPtr> method_data;
method_data.push_back(MakePaymentMethodData("basic-card"));
method_data.push_back(MakePaymentMethodData("https://ph.example"));
MockCallback mock_callback;
base::WeakPtr<PaymentAppServiceBridge> bridge =
PaymentAppServiceBridge::Create(
/* number_of_factories= */ 3, web_contents_->GetMainFrame(),
top_origin_, std::move(method_data), web_data_service_,
/* may_crawl_for_installable_payment_apps= */ true,
base::BindRepeating(&MockCallback::NotifyPaymentAppCreated,
base::Unretained(&mock_callback)),
base::BindRepeating(&MockCallback::NotifyPaymentAppCreationError,
base::Unretained(&mock_callback)),
base::BindOnce(&MockCallback::NotifyDoneCreatingPaymentApps,
base::Unretained(&mock_callback)))
->GetWeakPtr();
EXPECT_TRUE(bridge->SkipCreatingNativePaymentApps());
EXPECT_EQ(web_contents_, bridge->GetWebContents());
EXPECT_EQ(top_origin_, bridge->GetTopOrigin());
EXPECT_EQ(frame_origin_, bridge->GetFrameOrigin());
EXPECT_EQ("https://merchant.example",
bridge->GetFrameSecurityOrigin().Serialize());
EXPECT_EQ(web_contents_->GetMainFrame(),
bridge->GetInitiatorRenderFrameHost());
EXPECT_EQ(2U, bridge->GetMethodData().size());
EXPECT_EQ("basic-card", bridge->GetMethodData()[0]->supported_method);
EXPECT_EQ("https://ph.example", bridge->GetMethodData()[1]->supported_method);
EXPECT_TRUE(bridge->MayCrawlForInstallablePaymentApps());
content::PaymentAppProvider::PaymentApps apps;
ServiceWorkerPaymentAppFinder::InstallablePaymentApps installables;
EXPECT_CALL(mock_callback, NotifyPaymentAppCreated());
bridge->OnCreatingNativePaymentAppsSkipped(apps, installables);
EXPECT_CALL(mock_callback, NotifyPaymentAppCreationError("some error"));
bridge->OnPaymentAppCreationError("some error");
// NotifyDoneCreatingPaymentApps() is only called after
// OnDoneCreatingPaymentApps() is called for each payment factories in
// |bridge|.
bridge->OnDoneCreatingPaymentApps();
bridge->OnDoneCreatingPaymentApps();
EXPECT_CALL(mock_callback, NotifyDoneCreatingPaymentApps());
bridge->OnDoneCreatingPaymentApps();
// |bridge| cleans itself up after NotifyDoneCreatingPaymentApps().
CHECK_EQ(nullptr, bridge.get());
}
} // namespace payments
......@@ -6,8 +6,18 @@ import("//build/config/jumbo.gni")
jumbo_static_library("content") {
sources = [
"autofill_payment_app_factory.cc",
"autofill_payment_app_factory.h",
"can_make_payment_query_factory.cc",
"can_make_payment_query_factory.h",
"initialization_task.cc",
"initialization_task.h",
"payment_app_factory.cc",
"payment_app_factory.h",
"payment_app_service.cc",
"payment_app_service.h",
"payment_app_service_factory.cc",
"payment_app_service_factory.h",
"payment_details_converter.cc",
"payment_details_converter.h",
"payment_event_response_util.cc",
......@@ -16,6 +26,12 @@ jumbo_static_library("content") {
"payment_handler_host.h",
"payment_request_converter.cc",
"payment_request_converter.h",
"payment_request_spec.cc",
"payment_request_spec.h",
"service_worker_payment_app.cc",
"service_worker_payment_app.h",
"service_worker_payment_app_factory.cc",
"service_worker_payment_app_factory.h",
]
deps = [
......@@ -26,6 +42,7 @@ jumbo_static_library("content") {
"//components/payments/content/utility",
"//components/payments/core",
"//components/payments/core:error_strings",
"//components/payments/core:method_strings",
"//components/payments/mojom",
"//components/prefs",
"//components/strings:components_strings_grit",
......@@ -38,37 +55,19 @@ jumbo_static_library("content") {
if (!is_android) {
sources += [
"autofill_payment_app_factory.cc",
"autofill_payment_app_factory.h",
"content_payment_request_delegate.h",
"initialization_task.cc",
"initialization_task.h",
"payment_app_factory.cc",
"payment_app_factory.h",
"payment_app_service.cc",
"payment_app_service.h",
"payment_app_service_factory.cc",
"payment_app_service_factory.h",
"payment_request.cc",
"payment_request.h",
"payment_request_dialog.h",
"payment_request_display_manager.cc",
"payment_request_display_manager.h",
"payment_request_spec.cc",
"payment_request_spec.h",
"payment_request_state.cc",
"payment_request_state.h",
"payment_request_web_contents_manager.cc",
"payment_request_web_contents_manager.h",
"payment_response_helper.cc",
"payment_response_helper.h",
"service_worker_payment_app.cc",
"service_worker_payment_app.h",
"service_worker_payment_app_factory.cc",
"service_worker_payment_app_factory.h",
]
deps += [ "//components/payments/core:method_strings" ]
}
}
......
......@@ -6,6 +6,12 @@ import("//build/config/jumbo.gni")
jumbo_static_library("core") {
sources = [
"autofill_card_validation.cc",
"autofill_card_validation.h",
"autofill_payment_app.cc",
"autofill_payment_app.h",
"basic_card_response.cc",
"basic_card_response.h",
"can_make_payment_query.cc",
"can_make_payment_query.h",
"currency_formatter.cc",
......@@ -18,6 +24,8 @@ jumbo_static_library("core") {
"features.h",
"journey_logger.cc",
"journey_logger.h",
"payer_data.cc",
"payer_data.h",
"payment_address.cc",
"payment_address.h",
"payment_app.cc",
......@@ -38,6 +46,8 @@ jumbo_static_library("core") {
"payment_method_data.h",
"payment_prefs.cc",
"payment_prefs.h",
"payment_request_data_util.cc",
"payment_request_data_util.h",
"payment_shipping_option.cc",
"payment_shipping_option.h",
"payments_experimental_features.cc",
......@@ -50,20 +60,10 @@ jumbo_static_library("core") {
if (!is_android) {
sources += [
"autofill_card_validation.cc",
"autofill_card_validation.h",
"autofill_payment_app.cc",
"autofill_payment_app.h",
"basic_card_response.cc",
"basic_card_response.h",
"payer_data.cc",
"payer_data.h",
"payment_options.cc",
"payment_options.h",
"payment_options_provider.h",
"payment_request_base_delegate.h",
"payment_request_data_util.cc",
"payment_request_data_util.h",
"payment_request_delegate.h",
"payment_response.cc",
"payment_response.h",
......
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