Commit 6b08491c authored by Danyao Wang's avatar Danyao Wang Committed by Commit Bot

Revert "[Web Payments] Use PaymentAppServiceBridge JNI in PaymentAppService."

This reverts commit b666bbd0.

Reason for revert: broke tests: https://test-results.appspot.com/dashboards/flakiness_dashboard.html#testType=chrome_public_test_apk&tests=org.chromium.chrome.browser.payments.ExpandablePaymentHandlerChangePaymentMethodTest%23testThrowBasicCard

Original change's description:
> [Web Payments] Use PaymentAppServiceBridge JNI in PaymentAppService.
> 
> This CL contains the final steps to make the Java PaymentAppService
> invoke the C++ PaymentAppService:
> - Moved remaining PaymentHandlerFinder functionality, namely,
>   onInstalledPaymentHandlerFounder() and onInstallablePaymentHandler()
>   from ServiceWorkerPaymentAppBridge to PaymentAppServiceBridge.
> - Exposed the native method fireCanMakePaymentEvent() via a static
>   method on ServiceWorkerPaymentAppBridge so it can be used by
>   PaymentAppServiceBridge.
> - Proxied ServiceWorkerPaymentAppBridge.setCanMakePaymentForTesting
>   to PaymentAppServiceBridge. This will be cleaned up in a subsequent
>   CL.
> - Fixed a bug from a previous CL to pass payment apps to callbacks by
>   value instead of by reference.
> 
> Bug: 1063118
> Change-Id: I87e254d6dc11e12f890353c9a0a6dde6cca73c9f
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2141436
> Reviewed-by: Rouslan Solomakhin <rouslan@chromium.org>
> Commit-Queue: Danyao Wang <danyao@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#757827}

TBR=rouslan@chromium.org,danyao@chromium.org,maxlg@chromium.org

Change-Id: I73fda6a9cf222a684d05e1b24229cfc26ae3630c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1063118
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2144682Reviewed-by: default avatarDanyao Wang <danyao@chromium.org>
Commit-Queue: Danyao Wang <danyao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#758013}
parent c8838b99
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.payments; package org.chromium.chrome.browser.payments;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
...@@ -25,7 +27,9 @@ public class PaymentAppService implements PaymentAppFactoryInterface { ...@@ -25,7 +27,9 @@ public class PaymentAppService implements PaymentAppFactoryInterface {
/** Prevent instantiation. */ /** Prevent instantiation. */
private PaymentAppService() { private PaymentAppService() {
mFactories.add(new AutofillPaymentAppFactory()); mFactories.add(new AutofillPaymentAppFactory());
mFactories.add(new PaymentAppServiceBridge()); if (ChromeFeatureList.isEnabled(ChromeFeatureList.SERVICE_WORKER_PAYMENT_APPS)) {
mFactories.add(new ServiceWorkerPaymentAppBridge());
}
mFactories.add(new AndroidPaymentAppFactory()); mFactories.add(new AndroidPaymentAppFactory());
} }
......
...@@ -4,282 +4,68 @@ ...@@ -4,282 +4,68 @@
package org.chromium.chrome.browser.payments; package org.chromium.chrome.browser.payments;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.components.payments.MethodStrings;
import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.content_public.browser.WebContents;
import org.chromium.payments.mojom.PaymentDetailsModifier;
import org.chromium.payments.mojom.PaymentMethodData;
import org.chromium.url.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/** /**
* Native bridge for finding payment apps. * Native bridge for finding payment apps.
*/ */
public class PaymentAppServiceBridge implements PaymentAppFactoryInterface { public class PaymentAppServiceBridge implements PaymentAppFactoryInterface {
private static final String TAG = "cr_PaymentAppService"; /* package */ PaymentAppServiceBridge() {}
private static boolean sCanMakePaymentForTesting;
private final Set<String> mStandardizedPaymentMethods = new HashSet<>();
/* package */ PaymentAppServiceBridge() {
mStandardizedPaymentMethods.add(MethodStrings.BASIC_CARD);
mStandardizedPaymentMethods.add(MethodStrings.INTERLEDGER);
mStandardizedPaymentMethods.add(MethodStrings.PAYEE_CREDIT_TRANSFER);
mStandardizedPaymentMethods.add(MethodStrings.PAYER_CREDIT_TRANSFER);
mStandardizedPaymentMethods.add(MethodStrings.TOKENIZED_CARD);
}
/**
* Make canMakePayment() return true always for testing purpose.
*
* @param canMakePayment Indicates whether a SW payment app can make payment.
*/
@VisibleForTesting
public static void setCanMakePaymentForTesting(boolean canMakePayment) {
sCanMakePaymentForTesting = canMakePayment;
}
// PaymentAppFactoryInterface implementation. // PaymentAppFactoryInterface implementation.
@Override @Override
public void create(PaymentAppFactoryDelegate delegate) { public void create(PaymentAppFactoryDelegate delegate) {
assert delegate.getParams().getPaymentRequestOrigin().equals( assert (delegate.getParams().getRenderFrameHost().getLastCommittedURL().equals(
UrlFormatter.formatUrlForSecurityDisplay( delegate.getParams().getPaymentRequestOrigin()));
delegate.getParams().getRenderFrameHost().getLastCommittedURL()));
PaymentAppServiceCallback callback = new PaymentAppServiceCallback(delegate); PaymentAppServiceCallback callback = new PaymentAppServiceCallback(delegate);
ByteBuffer[] serializedMethodData =
new ByteBuffer[delegate.getParams().getMethodData().values().size()];
int i = 0;
for (PaymentMethodData methodData : delegate.getParams().getMethodData().values()) {
serializedMethodData[i++] = methodData.serialize();
}
PaymentAppServiceBridgeJni.get().create(delegate.getParams().getRenderFrameHost(), PaymentAppServiceBridgeJni.get().create(delegate.getParams().getRenderFrameHost(),
delegate.getParams().getTopLevelOrigin(), serializedMethodData, delegate.getParams().getTopLevelOrigin(),
delegate.getParams()
.getMethodData()
.values()
.stream()
.map(data -> data.serialize())
.toArray(ByteBuffer[] ::new),
delegate.getParams().getMayCrawl(), callback); delegate.getParams().getMayCrawl(), callback);
} }
/** Handles callbacks from native PaymentAppService and creates PaymentApps. */ /** Handles callbacks from native PaymentAppService and creates PaymentApps. */
public class PaymentAppServiceCallback { public class PaymentAppServiceCallback {
private final PaymentAppFactoryDelegate mDelegate; private final PaymentAppFactoryDelegate mDelegate;
private boolean mPaymentHandlerWithMatchingMethodFound; private boolean mCanMakePayment;
private int mNumberOfPendingCanMakePaymentEvents;
private boolean mDoneCreatingPaymentApps;
private PaymentAppServiceCallback(PaymentAppFactoryDelegate delegate) { private PaymentAppServiceCallback(PaymentAppFactoryDelegate delegate) {
mDelegate = delegate; mDelegate = delegate;
mCanMakePayment = false;
} }
/** Called when an installed payment handler is found. */
@CalledByNative("PaymentAppServiceCallback") @CalledByNative("PaymentAppServiceCallback")
private void onInstalledPaymentHandlerFound(long registrationId, String scope, private void onPaymentAppCreated() {
@Nullable String name, @Nullable String userHint, String origin,
@Nullable Bitmap icon, String[] methodNameArray, boolean explicitlyVerified,
Object[] capabilities, String[] preferredRelatedApplications,
Object supportedDelegations) {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
mCanMakePayment = true;
WebContents webContents = mDelegate.getParams().getWebContents(); // TODO(crbug.com/1063118): call mDelegate.onPaymentAppCreated().
ChromeActivity activity = ChromeActivity.fromWebContents(webContents);
ServiceWorkerPaymentApp app = createInstalledServiceWorkerPaymentApp(webContents,
registrationId, scope, name, userHint, origin, icon, methodNameArray,
explicitlyVerified, (ServiceWorkerPaymentApp.Capabilities[]) capabilities,
preferredRelatedApplications, (SupportedDelegations) supportedDelegations);
if (app == null) return;
mPaymentHandlerWithMatchingMethodFound = true;
mNumberOfPendingCanMakePaymentEvents++;
ServiceWorkerPaymentAppBridge.CanMakePaymentEventCallback canMakePaymentEventCallback =
new ServiceWorkerPaymentAppBridge.CanMakePaymentEventCallback() {
@Override
public void onCanMakePaymentEventResponse(String errorMessage,
boolean canMakePayment, boolean readyForMinimalUI,
@Nullable String accountBalance) {
if (canMakePayment) mDelegate.onPaymentAppCreated(app);
if (!TextUtils.isEmpty(errorMessage)) {
mDelegate.onPaymentAppCreationError(errorMessage);
}
app.setIsReadyForMinimalUI(readyForMinimalUI);
app.setAccountBalance(accountBalance);
if (--mNumberOfPendingCanMakePaymentEvents == 0
&& mDoneCreatingPaymentApps) {
notifyFinished();
}
}
};
if (sCanMakePaymentForTesting || activity.getCurrentTabModel().isIncognito()
|| mStandardizedPaymentMethods.containsAll(Arrays.asList(methodNameArray))
|| !explicitlyVerified) {
canMakePaymentEventCallback.onCanMakePaymentEventResponse(/*errorMessage=*/null,
/*canMakePayment=*/true,
/*readyForMinimalUI=*/false, /*accountBalance=*/null);
return;
}
Set<PaymentMethodData> supportedRequestedMethodData = new HashSet<>();
for (String methodName : methodNameArray) {
if (mDelegate.getParams().getMethodData().containsKey(methodName)) {
supportedRequestedMethodData.add(
mDelegate.getParams().getMethodData().get(methodName));
}
}
Set<PaymentDetailsModifier> supportedRequestedModifiers = new HashSet<>();
for (String methodName : methodNameArray) {
if (mDelegate.getParams().getModifiers().containsKey(methodName)) {
supportedRequestedModifiers.add(
mDelegate.getParams().getModifiers().get(methodName));
}
}
ServiceWorkerPaymentAppBridge.fireCanMakePaymentEvent(webContents, registrationId,
scope, mDelegate.getParams().getId(), mDelegate.getParams().getTopLevelOrigin(),
mDelegate.getParams().getPaymentRequestOrigin(),
supportedRequestedMethodData.toArray(new PaymentMethodData[0]),
supportedRequestedModifiers.toArray(new PaymentDetailsModifier[0]),
ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MINIMAL_UI)
? mDelegate.getParams().getTotalAmountCurrency()
: null,
canMakePaymentEventCallback);
} }
/** Called when an installable payment handler is found. */
@CalledByNative("PaymentAppServiceCallback")
private void onInstallablePaymentHandlerFound(@Nullable String name, String swUrl,
String scope, boolean useCache, @Nullable Bitmap icon, String methodName,
String[] preferredRelatedApplications, Object supportedDelegations) {
ThreadUtils.assertOnUiThread();
ServiceWorkerPaymentApp installableApp = createInstallableServiceWorkerPaymentApp(
mDelegate.getParams().getWebContents(), name, swUrl, scope, useCache, icon,
methodName, preferredRelatedApplications,
(SupportedDelegations) supportedDelegations);
if (installableApp == null) return;
mDelegate.onPaymentAppCreated(installableApp);
mPaymentHandlerWithMatchingMethodFound = true;
if (mNumberOfPendingCanMakePaymentEvents == 0 && mDoneCreatingPaymentApps) {
notifyFinished();
}
}
/**
* Called when an error has occurred.
* @param errorMessage Developer facing error message.
*/
@CalledByNative("PaymentAppServiceCallback") @CalledByNative("PaymentAppServiceCallback")
private void onPaymentAppCreationError(String errorMessage) { private void onPaymentAppCreationError(String errorMessage) {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
mDelegate.onPaymentAppCreationError(errorMessage); mDelegate.onPaymentAppCreationError(errorMessage);
} }
/** // Expect to be called exactly once
* Called when the factory is finished creating payment apps. Expects to be called exactly
* once and after all onPaymentAppCreated() calls.
*/
@CalledByNative("PaymentAppServiceCallback") @CalledByNative("PaymentAppServiceCallback")
private void onDoneCreatingPaymentApps() { private void onDoneCreatingPaymentApps() {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
mDoneCreatingPaymentApps = true; mDelegate.onCanMakePaymentCalculated(mCanMakePayment);
if (mNumberOfPendingCanMakePaymentEvents == 0) {
notifyFinished();
}
}
/**
* Signal completion of payment app lookup.
*/
private void notifyFinished() {
assert mDoneCreatingPaymentApps;
assert mNumberOfPendingCanMakePaymentEvents == 0;
mDelegate.onCanMakePaymentCalculated(mPaymentHandlerWithMatchingMethodFound);
mDelegate.onDoneCreatingPaymentApps(PaymentAppServiceBridge.this); mDelegate.onDoneCreatingPaymentApps(PaymentAppServiceBridge.this);
} }
} }
@CalledByNative
private static Object[] createCapabilities(int count) {
return new ServiceWorkerPaymentApp.Capabilities[count];
}
@CalledByNative
private static void addCapabilities(
Object[] capabilities, int index, int[] supportedCardNetworks) {
assert index < capabilities.length;
capabilities[index] = new ServiceWorkerPaymentApp.Capabilities(supportedCardNetworks);
}
@CalledByNative
private static Object createSupportedDelegations(
boolean shippingAddress, boolean payerName, boolean payerPhone, boolean payerEmail) {
return new SupportedDelegations(shippingAddress, payerName, payerPhone, payerEmail);
}
private static @Nullable ServiceWorkerPaymentApp createInstalledServiceWorkerPaymentApp(
WebContents webContents, long registrationId, String scope, @Nullable String name,
@Nullable String userHint, String origin, @Nullable Bitmap icon,
String[] methodNameArray, boolean explicitlyVerified,
ServiceWorkerPaymentApp.Capabilities[] capabilities,
String[] preferredRelatedApplications, SupportedDelegations supportedDelegations) {
ChromeActivity activity = ChromeActivity.fromWebContents(webContents);
if (activity == null) return null;
URI scopeUri = UriUtils.parseUriFromString(scope);
if (scopeUri == null) {
Log.e(TAG, "%s service worker scope is not a valid URI", scope);
return null;
}
return new ServiceWorkerPaymentApp(webContents, registrationId, scopeUri, name, userHint,
origin, icon == null ? null : new BitmapDrawable(activity.getResources(), icon),
methodNameArray, capabilities, preferredRelatedApplications, supportedDelegations);
}
private static @Nullable ServiceWorkerPaymentApp createInstallableServiceWorkerPaymentApp(
WebContents webContents, @Nullable String name, String swUrl, String scope,
boolean useCache, @Nullable Bitmap icon, String methodName,
String[] preferredRelatedApplications, SupportedDelegations supportedDelegations) {
Context context = ChromeActivity.fromWebContents(webContents);
if (context == null) return null;
URI swUri = UriUtils.parseUriFromString(swUrl);
if (swUri == null) {
Log.e(TAG, "%s service worker installation url is not a valid URI", swUrl);
return null;
}
URI scopeUri = UriUtils.parseUriFromString(scope);
if (scopeUri == null) {
Log.e(TAG, "%s service worker scope is not a valid URI", scope);
return null;
}
return new ServiceWorkerPaymentApp(webContents, name, scopeUri.getHost(), swUri, scopeUri,
useCache, icon == null ? null : new BitmapDrawable(context.getResources(), icon),
methodName, preferredRelatedApplications, supportedDelegations);
}
@NativeMethods @NativeMethods
/* package */ interface Natives { /* package */ interface Natives {
void create(RenderFrameHost initiatorRenderFrameHost, String topOrigin, void create(RenderFrameHost initiatorRenderFrameHost, String topOrigin,
......
...@@ -4,24 +4,30 @@ ...@@ -4,24 +4,30 @@
package org.chromium.chrome.browser.payments; package org.chromium.chrome.browser.payments;
import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Pair; import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNIAdditionalImport; import org.chromium.base.annotations.JNIAdditionalImport;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.task.PostTask; import org.chromium.base.task.PostTask;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.components.payments.MethodStrings;
import org.chromium.components.payments.PayerData; import org.chromium.components.payments.PayerData;
import org.chromium.components.payments.PaymentHandlerHost; import org.chromium.components.payments.PaymentHandlerHost;
import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.payments.mojom.PaymentAddress; import org.chromium.payments.mojom.PaymentAddress;
...@@ -32,9 +38,12 @@ import org.chromium.payments.mojom.PaymentItem; ...@@ -32,9 +38,12 @@ import org.chromium.payments.mojom.PaymentItem;
import org.chromium.payments.mojom.PaymentMethodData; import org.chromium.payments.mojom.PaymentMethodData;
import org.chromium.payments.mojom.PaymentOptions; import org.chromium.payments.mojom.PaymentOptions;
import org.chromium.payments.mojom.PaymentShippingOption; import org.chromium.payments.mojom.PaymentShippingOption;
import org.chromium.url.Origin;
import org.chromium.url.URI; import org.chromium.url.URI;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -43,8 +52,10 @@ import java.util.Set; ...@@ -43,8 +52,10 @@ import java.util.Set;
* Native bridge for interacting with service worker based payment apps. * Native bridge for interacting with service worker based payment apps.
*/ */
@JNIAdditionalImport({PaymentApp.class}) @JNIAdditionalImport({PaymentApp.class})
public class ServiceWorkerPaymentAppBridge { public class ServiceWorkerPaymentAppBridge implements PaymentAppFactoryInterface {
private static final String TAG = "SWPaymentApp"; private static final String TAG = "SWPaymentApp";
private static boolean sCanMakePaymentForTesting;
private final Set<String> mStandardizedPaymentMethods = new HashSet<>();
/** The interface for checking whether there is an installed SW payment app. */ /** The interface for checking whether there is an installed SW payment app. */
public static interface HasServiceWorkerPaymentAppsCallback { public static interface HasServiceWorkerPaymentAppsCallback {
...@@ -66,11 +77,161 @@ public class ServiceWorkerPaymentAppBridge { ...@@ -66,11 +77,161 @@ public class ServiceWorkerPaymentAppBridge {
public void onGetServiceWorkerPaymentAppsInfo(Map<String, Pair<String, Bitmap>> appsInfo); public void onGetServiceWorkerPaymentAppsInfo(Map<String, Pair<String, Bitmap>> appsInfo);
} }
/** The interface for checking "canmakepayment" response in an installed SW payment app. */ /* package */ ServiceWorkerPaymentAppBridge() {
public static interface CanMakePaymentEventCallback { mStandardizedPaymentMethods.add(MethodStrings.BASIC_CARD);
mStandardizedPaymentMethods.add(MethodStrings.INTERLEDGER);
mStandardizedPaymentMethods.add(MethodStrings.PAYEE_CREDIT_TRANSFER);
mStandardizedPaymentMethods.add(MethodStrings.PAYER_CREDIT_TRANSFER);
mStandardizedPaymentMethods.add(MethodStrings.TOKENIZED_CARD);
}
// PaymentAppFactoryInterface implementation:
@Override
public void create(PaymentAppFactoryDelegate delegate) {
PaymentHandlerFinder finder = new PaymentHandlerFinder(delegate);
ServiceWorkerPaymentAppBridgeJni.get().getAllPaymentApps(
delegate.getParams().getPaymentRequestSecurityOrigin(),
delegate.getParams().getRenderFrameHost(),
delegate.getParams().getMethodData().values().toArray(
new PaymentMethodData[delegate.getParams().getMethodData().size()]),
delegate.getParams().getMayCrawl(),
/*callback=*/finder);
}
/** Finds the payment handlers and checks their "canmakepayment" response. */
public class PaymentHandlerFinder {
private final PaymentAppFactoryDelegate mDelegate;
private int mNumberOfPendingCanMakePaymentEvents;
private boolean mAreAllPaymentAppsCreated;
/** /**
* Called to return "canmakepayment" result. * True if at least one payment handler with matching payment methods is found, regardless
* * of its reply to the "canmakepayment" event.
*/
private boolean mPaymentHandlerWithMatchingMethodFound;
private PaymentHandlerFinder(PaymentAppFactoryDelegate delegate) {
mDelegate = delegate;
}
/** Called when an installed payment handler is found. */
@CalledByNative("PaymentHandlerFinder")
private void onInstalledPaymentHandlerFound(long registrationId, String scope,
@Nullable String name, @Nullable String userHint, String origin,
@Nullable Bitmap icon, String[] methodNameArray, boolean explicitlyVerified,
Object[] capabilities, String[] preferredRelatedApplications,
Object supportedDelegations) {
ThreadUtils.assertOnUiThread();
WebContents webContents = mDelegate.getParams().getWebContents();
ChromeActivity activity = ChromeActivity.fromWebContents(webContents);
if (activity == null) return;
URI scopeUri = UriUtils.parseUriFromString(scope);
if (scopeUri == null) {
Log.e(TAG, "%s service worker scope is not a valid URI", scope);
return;
}
ServiceWorkerPaymentApp app = new ServiceWorkerPaymentApp(webContents, registrationId,
scopeUri, name, userHint, origin,
icon == null ? null : new BitmapDrawable(activity.getResources(), icon),
methodNameArray, (ServiceWorkerPaymentApp.Capabilities[]) capabilities,
preferredRelatedApplications, (SupportedDelegations) supportedDelegations);
mPaymentHandlerWithMatchingMethodFound = true;
mNumberOfPendingCanMakePaymentEvents++;
if (sCanMakePaymentForTesting || activity.getCurrentTabModel().isIncognito()
|| mStandardizedPaymentMethods.containsAll(Arrays.asList(methodNameArray))
|| !explicitlyVerified) {
onCanMakePaymentEventResponse(app, /*errorMessage=*/null, /*canMakePayment=*/true,
/*readyForMinimalUI=*/false, /*accountBalance=*/null);
return;
}
Set<PaymentMethodData> supportedRequestedMethodData = new HashSet<>();
for (String methodName : methodNameArray) {
if (mDelegate.getParams().getMethodData().containsKey(methodName)) {
supportedRequestedMethodData.add(
mDelegate.getParams().getMethodData().get(methodName));
}
}
Set<PaymentDetailsModifier> supportedRequestedModifiers = new HashSet<>();
for (String methodName : methodNameArray) {
if (mDelegate.getParams().getModifiers().containsKey(methodName)) {
supportedRequestedModifiers.add(
mDelegate.getParams().getModifiers().get(methodName));
}
}
ServiceWorkerPaymentAppBridgeJni.get().fireCanMakePaymentEvent(webContents,
registrationId, scope, mDelegate.getParams().getId(),
mDelegate.getParams().getTopLevelOrigin(),
mDelegate.getParams().getPaymentRequestOrigin(),
supportedRequestedMethodData.toArray(new PaymentMethodData[0]),
supportedRequestedModifiers.toArray(new PaymentDetailsModifier[0]),
ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MINIMAL_UI)
? mDelegate.getParams().getTotalAmountCurrency()
: null,
/*callback=*/this, app);
}
/** Called when an installable payment handler is found. */
@CalledByNative("PaymentHandlerFinder")
private void onInstallablePaymentHandlerFound(@Nullable String name, String swUrl,
String scope, boolean useCache, @Nullable Bitmap icon, String methodName,
String[] preferredRelatedApplications, Object supportedDelegations) {
ThreadUtils.assertOnUiThread();
WebContents webContents = mDelegate.getParams().getWebContents();
Context context = ChromeActivity.fromWebContents(webContents);
if (context == null) return;
URI swUri = UriUtils.parseUriFromString(swUrl);
if (swUri == null) {
Log.e(TAG, "%s service worker installation url is not a valid URI", swUrl);
return;
}
URI scopeUri = UriUtils.parseUriFromString(scope);
if (scopeUri == null) {
Log.e(TAG, "%s service worker scope is not a valid URI", scope);
return;
}
mDelegate.onPaymentAppCreated(new ServiceWorkerPaymentApp(webContents, name,
scopeUri.getHost(), swUri, scopeUri, useCache,
icon == null ? null : new BitmapDrawable(context.getResources(), icon),
methodName, preferredRelatedApplications,
(SupportedDelegations) supportedDelegations));
mPaymentHandlerWithMatchingMethodFound = true;
if (mNumberOfPendingCanMakePaymentEvents == 0 && mAreAllPaymentAppsCreated) {
notifyFinished();
}
}
/**
* Called when an error has occurred.
* @param errorMessage Developer facing error message.
*/
@CalledByNative("PaymentHandlerFinder")
private void onGetPaymentAppsError(String errorMessage) {
ThreadUtils.assertOnUiThread();
mDelegate.onPaymentAppCreationError(errorMessage);
}
/** Called when the factory is finished creating payment apps. */
@CalledByNative("PaymentHandlerFinder")
private void onAllPaymentAppsCreated() {
ThreadUtils.assertOnUiThread();
mAreAllPaymentAppsCreated = true;
if (mNumberOfPendingCanMakePaymentEvents == 0 && mAreAllPaymentAppsCreated) {
notifyFinished();
}
}
/**
* Called when a service worker responds to the "canmakepayment" event.
* @param app The service worker that has responded to the "canmakepayment" event. * @param app The service worker that has responded to the "canmakepayment" event.
* @param errorMessage An optional error message about any problems encountered while firing * @param errorMessage An optional error message about any problems encountered while firing
* the "canmakepayment" event. * the "canmakepayment" event.
...@@ -78,11 +239,25 @@ public class ServiceWorkerPaymentAppBridge { ...@@ -78,11 +239,25 @@ public class ServiceWorkerPaymentAppBridge {
* @param readyForMinimalUI Whether minimal UI should be used. * @param readyForMinimalUI Whether minimal UI should be used.
* @param accountBalance The account balance to display in the minimal UI. * @param accountBalance The account balance to display in the minimal UI.
*/ */
public void onCanMakePaymentEventResponse(String errorMessage, boolean canMakePayment, @CalledByNative("PaymentHandlerFinder")
boolean readyForMinimalUI, @Nullable String accountBalance); private void onCanMakePaymentEventResponse(ServiceWorkerPaymentApp app, String errorMessage,
} boolean canMakePayment, boolean readyForMinimalUI,
@Nullable String accountBalance) {
if (canMakePayment) mDelegate.onPaymentAppCreated(app);
if (!TextUtils.isEmpty(errorMessage)) mDelegate.onPaymentAppCreationError(errorMessage);
app.setIsReadyForMinimalUI(readyForMinimalUI);
app.setAccountBalance(accountBalance);
if (--mNumberOfPendingCanMakePaymentEvents == 0 && mAreAllPaymentAppsCreated) {
notifyFinished();
}
}
/* package */ ServiceWorkerPaymentAppBridge() {} private void notifyFinished() {
mDelegate.onCanMakePaymentCalculated(mPaymentHandlerWithMatchingMethodFound);
mDelegate.onDoneCreatingPaymentApps(ServiceWorkerPaymentAppBridge.this);
}
}
/** /**
* Checks whether there is a installed SW payment app. * Checks whether there is a installed SW payment app.
...@@ -133,20 +308,7 @@ public class ServiceWorkerPaymentAppBridge { ...@@ -133,20 +308,7 @@ public class ServiceWorkerPaymentAppBridge {
*/ */
@VisibleForTesting @VisibleForTesting
public static void setCanMakePaymentForTesting(boolean canMakePayment) { public static void setCanMakePaymentForTesting(boolean canMakePayment) {
PaymentAppServiceBridge.setCanMakePaymentForTesting(canMakePayment); sCanMakePaymentForTesting = canMakePayment;
}
/**
* Fires a "canmakepayment" event for the payment app with the registration ID.
*/
public static void fireCanMakePaymentEvent(WebContents webContents, long registrationId,
String serviceWorkerScope, String paymentRequestId, String topOrigin,
String paymentRequestOrigin, PaymentMethodData[] methodData,
PaymentDetailsModifier[] modifiers, @Nullable String currency,
CanMakePaymentEventCallback callback) {
ServiceWorkerPaymentAppBridgeJni.get().fireCanMakePaymentEvent(webContents, registrationId,
serviceWorkerScope, paymentRequestId, topOrigin, paymentRequestOrigin, methodData,
modifiers, currency, callback);
} }
/** /**
...@@ -307,24 +469,6 @@ public class ServiceWorkerPaymentAppBridge { ...@@ -307,24 +469,6 @@ public class ServiceWorkerPaymentAppBridge {
swScope.toString()); swScope.toString());
} }
/**
* Called when a service worker responds to the "canmakepayment" event.
* @param app The service worker that has responded to the "canmakepayment" event.
* @param errorMessage An optional error message about any problems encountered while firing
* the "canmakepayment" event.
* @param canMakePayment Whether payments can be made.
* @param readyForMinimalUI Whether minimal UI should be used.
* @param accountBalance The account balance to display in the minimal UI.
*/
@CalledByNative
private static void onCanMakePaymentEventResponse(CanMakePaymentEventCallback callback,
String errorMessage, boolean canMakePayment, boolean readyForMinimalUI,
@Nullable String accountBalance) {
ThreadUtils.assertOnUiThread();
callback.onCanMakePaymentEventResponse(
errorMessage, canMakePayment, readyForMinimalUI, accountBalance);
}
@CalledByNative @CalledByNative
private static String getSupportedMethodFromMethodData(PaymentMethodData data) { private static String getSupportedMethodFromMethodData(PaymentMethodData data) {
return data.supportedMethod; return data.supportedMethod;
...@@ -421,6 +565,24 @@ public class ServiceWorkerPaymentAppBridge { ...@@ -421,6 +565,24 @@ public class ServiceWorkerPaymentAppBridge {
return options.shippingType; return options.shippingType;
} }
@CalledByNative
private static Object[] createCapabilities(int count) {
return new ServiceWorkerPaymentApp.Capabilities[count];
}
@CalledByNative
private static Object createSupportedDelegations(
boolean shippingAddress, boolean payerName, boolean payerPhone, boolean payerEmail) {
return new SupportedDelegations(shippingAddress, payerName, payerPhone, payerEmail);
}
@CalledByNative
private static void addCapabilities(
Object[] capabilities, int index, int[] supportedCardNetworks) {
assert index < capabilities.length;
capabilities[index] = new ServiceWorkerPaymentApp.Capabilities(supportedCardNetworks);
}
@CalledByNative @CalledByNative
private static void onHasServiceWorkerPaymentApps( private static void onHasServiceWorkerPaymentApps(
HasServiceWorkerPaymentAppsCallback callback, boolean hasPaymentApps) { HasServiceWorkerPaymentAppsCallback callback, boolean hasPaymentApps) {
...@@ -503,6 +665,9 @@ public class ServiceWorkerPaymentAppBridge { ...@@ -503,6 +665,9 @@ public class ServiceWorkerPaymentAppBridge {
@NativeMethods @NativeMethods
interface Natives { interface Natives {
void getAllPaymentApps(Origin merchantOrigin, RenderFrameHost initiatorRenderFrameHost,
PaymentMethodData[] methodData, boolean mayCrawlForInstallablePaymentApps,
PaymentHandlerFinder callback);
void hasServiceWorkerPaymentApps(HasServiceWorkerPaymentAppsCallback callback); void hasServiceWorkerPaymentApps(HasServiceWorkerPaymentAppsCallback callback);
void getServiceWorkerPaymentAppsInfo(GetServiceWorkerPaymentAppsInfoCallback callback); void getServiceWorkerPaymentAppsInfo(GetServiceWorkerPaymentAppsInfoCallback callback);
void invokePaymentApp(WebContents webContents, long registrationId, void invokePaymentApp(WebContents webContents, long registrationId,
...@@ -526,8 +691,8 @@ public class ServiceWorkerPaymentAppBridge { ...@@ -526,8 +691,8 @@ public class ServiceWorkerPaymentAppBridge {
void fireCanMakePaymentEvent(WebContents webContents, long registrationId, void fireCanMakePaymentEvent(WebContents webContents, long registrationId,
String serviceWorkerScope, String paymentRequestId, String topOrigin, String serviceWorkerScope, String paymentRequestId, String topOrigin,
String paymentRequestOrigin, PaymentMethodData[] methodData, String paymentRequestOrigin, PaymentMethodData[] methodData,
PaymentDetailsModifier[] modifiers, String currency, PaymentDetailsModifier[] modifiers, String currency, PaymentHandlerFinder callback,
CanMakePaymentEventCallback callback); ServiceWorkerPaymentApp app);
void onClosingPaymentAppWindow(WebContents webContents, int reason); void onClosingPaymentAppWindow(WebContents webContents, int reason);
long getSourceIdForPaymentAppFromScope(String swScope); long getSourceIdForPaymentAppFromScope(String swScope);
} }
......
...@@ -20,26 +20,24 @@ ...@@ -20,26 +20,24 @@
#include "components/payments/content/payment_app_service.h" #include "components/payments/content/payment_app_service.h"
#include "components/payments/content/payment_app_service_factory.h" #include "components/payments/content/payment_app_service_factory.h"
#include "components/payments/content/payment_manifest_web_data_service.h" #include "components/payments/content/payment_manifest_web_data_service.h"
#include "components/url_formatter/elide_url.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/payments/payment_app.mojom.h" #include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h" #include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
#include "ui/gfx/android/java_bitmap.h"
#include "url/origin.h" #include "url/origin.h"
namespace { namespace {
using ::base::android::AttachCurrentThread; using ::base::android::AttachCurrentThread;
using ::base::android::ConvertJavaStringToUTF8; using ::base::android::ConvertJavaStringToUTF8;
using ::base::android::ConvertUTF8ToJavaString; using ::base::android::ConvertUTF8ToJavaString;
using ::base::android::JavaParamRef; using ::base::android::JavaParamRef;
using ::base::android::JavaRef; using ::base::android::JavaRef;
using ::base::android::ScopedJavaGlobalRef; using ::base::android::ScopedJavaGlobalRef;
using ::base::android::ScopedJavaLocalRef;
using ::base::android::ToJavaArrayOfStrings;
using ::base::android::ToJavaIntArray;
using ::payments::android::DeserializeFromJavaByteBufferArray; using ::payments::android::DeserializeFromJavaByteBufferArray;
using ::payments::mojom::BasicCardNetwork;
using ::payments::mojom::PaymentMethodData;
using ::payments::mojom::PaymentMethodDataPtr; using ::payments::mojom::PaymentMethodDataPtr;
// Helper to get the PaymentAppService associated with |render_frame_host|'s // Helper to get the PaymentAppService associated with |render_frame_host|'s
...@@ -52,82 +50,9 @@ payments::PaymentAppService* GetPaymentAppService( ...@@ -52,82 +50,9 @@ payments::PaymentAppService* GetPaymentAppService(
web_contents ? web_contents->GetBrowserContext() : nullptr); web_contents ? web_contents->GetBrowserContext() : nullptr);
} }
void OnPaymentAppsCreated( void OnPaymentAppCreated(const JavaRef<jobject>& jcallback) {
const JavaRef<jobject>& jcallback,
const content::PaymentAppProvider::PaymentApps& apps,
const payments::ServiceWorkerPaymentAppFinder::InstallablePaymentApps&
installable_apps) {
JNIEnv* env = AttachCurrentThread(); JNIEnv* env = AttachCurrentThread();
Java_PaymentAppServiceCallback_onPaymentAppCreated(env, jcallback);
for (const auto& app_info : apps) {
// Sends related application Ids to java side if the app prefers related
// applications.
std::vector<std::string> preferred_related_application_ids;
if (app_info.second->prefer_related_applications) {
for (const auto& related_application :
app_info.second->related_applications) {
// Only consider related applications on Google play for Android.
if (related_application.platform == "play")
preferred_related_application_ids.emplace_back(
related_application.id);
}
}
base::android::ScopedJavaLocalRef<jobjectArray> jcapabilities =
Java_PaymentAppServiceBridge_createCapabilities(
env, app_info.second->capabilities.size());
for (size_t i = 0; i < app_info.second->capabilities.size(); i++) {
Java_PaymentAppServiceBridge_addCapabilities(
env, jcapabilities, base::checked_cast<int>(i),
ToJavaIntArray(
env, app_info.second->capabilities[i].supported_card_networks));
}
base::android::ScopedJavaLocalRef<jobject> jsupported_delegations =
Java_PaymentAppServiceBridge_createSupportedDelegations(
env, app_info.second->supported_delegations.shipping_address,
app_info.second->supported_delegations.payer_name,
app_info.second->supported_delegations.payer_phone,
app_info.second->supported_delegations.payer_email);
// TODO(crbug.com/846077): Find a proper way to make use of user hint.
Java_PaymentAppServiceCallback_onInstalledPaymentHandlerFound(
env, jcallback, app_info.second->registration_id,
ConvertUTF8ToJavaString(env, app_info.second->scope.spec()),
app_info.second->name.empty()
? nullptr
: ConvertUTF8ToJavaString(env, app_info.second->name),
nullptr, ConvertUTF8ToJavaString(env, app_info.second->scope.host()),
app_info.second->icon == nullptr
? nullptr
: gfx::ConvertToJavaBitmap(app_info.second->icon.get()),
ToJavaArrayOfStrings(env, app_info.second->enabled_methods),
app_info.second->has_explicitly_verified_methods, jcapabilities,
ToJavaArrayOfStrings(env, preferred_related_application_ids),
jsupported_delegations);
}
for (const auto& installable_app : installable_apps) {
base::android::ScopedJavaLocalRef<jobject> jsupported_delegations =
Java_PaymentAppServiceBridge_createSupportedDelegations(
env, installable_app.second->supported_delegations.shipping_address,
installable_app.second->supported_delegations.payer_name,
installable_app.second->supported_delegations.payer_phone,
installable_app.second->supported_delegations.payer_email);
Java_PaymentAppServiceCallback_onInstallablePaymentHandlerFound(
env, jcallback,
ConvertUTF8ToJavaString(env, installable_app.second->name),
ConvertUTF8ToJavaString(env, installable_app.second->sw_js_url),
ConvertUTF8ToJavaString(env, installable_app.second->sw_scope),
installable_app.second->sw_use_cache,
installable_app.second->icon == nullptr
? nullptr
: gfx::ConvertToJavaBitmap(installable_app.second->icon.get()),
ConvertUTF8ToJavaString(env, installable_app.first.spec()),
ToJavaArrayOfStrings(env, installable_app.second->preferred_app_ids),
jsupported_delegations);
}
} }
void OnPaymentAppCreationError(const JavaRef<jobject>& jcallback, void OnPaymentAppCreationError(const JavaRef<jobject>& jcallback,
...@@ -174,7 +99,7 @@ void JNI_PaymentAppServiceBridge_Create( ...@@ -174,7 +99,7 @@ void JNI_PaymentAppServiceBridge_Create(
service->GetNumberOfFactories(), render_frame_host, GURL(top_origin), service->GetNumberOfFactories(), render_frame_host, GURL(top_origin),
std::move(method_data), web_data_service, std::move(method_data), web_data_service,
jmay_crawl_for_installable_payment_apps, jmay_crawl_for_installable_payment_apps,
base::BindRepeating(&OnPaymentAppsCreated, base::BindRepeating(&OnPaymentAppCreated,
ScopedJavaGlobalRef<jobject>(env, jcallback)), ScopedJavaGlobalRef<jobject>(env, jcallback)),
base::BindRepeating(&OnPaymentAppCreationError, base::BindRepeating(&OnPaymentAppCreationError,
ScopedJavaGlobalRef<jobject>(env, jcallback)), ScopedJavaGlobalRef<jobject>(env, jcallback)),
...@@ -226,14 +151,14 @@ PaymentAppServiceBridge* PaymentAppServiceBridge::Create( ...@@ -226,14 +151,14 @@ PaymentAppServiceBridge* PaymentAppServiceBridge::Create(
std::vector<mojom::PaymentMethodDataPtr> request_method_data, std::vector<mojom::PaymentMethodDataPtr> request_method_data,
scoped_refptr<PaymentManifestWebDataService> web_data_service, scoped_refptr<PaymentManifestWebDataService> web_data_service,
bool may_crawl_for_installable_payment_apps, bool may_crawl_for_installable_payment_apps,
PaymentAppsCreatedCallback payment_apps_created_callback, PaymentAppCreatedCallback payment_app_created_callback,
PaymentAppCreationErrorCallback payment_app_creation_error_callback, PaymentAppCreationErrorCallback payment_app_creation_error_callback,
base::OnceClosure done_creating_payment_apps_callback) { base::OnceClosure done_creating_payment_apps_callback) {
std::unique_ptr<PaymentAppServiceBridge> bridge(new PaymentAppServiceBridge( std::unique_ptr<PaymentAppServiceBridge> bridge(new PaymentAppServiceBridge(
number_of_factories, render_frame_host, top_origin, number_of_factories, render_frame_host, top_origin,
std::move(request_method_data), std::move(web_data_service), std::move(request_method_data), std::move(web_data_service),
may_crawl_for_installable_payment_apps, may_crawl_for_installable_payment_apps,
std::move(payment_apps_created_callback), std::move(payment_app_created_callback),
std::move(payment_app_creation_error_callback), std::move(payment_app_creation_error_callback),
std::move(done_creating_payment_apps_callback))); std::move(done_creating_payment_apps_callback)));
return PaymentAppServiceBridgeStorage::GetInstance()->Add(std::move(bridge)); return PaymentAppServiceBridgeStorage::GetInstance()->Add(std::move(bridge));
...@@ -246,7 +171,7 @@ PaymentAppServiceBridge::PaymentAppServiceBridge( ...@@ -246,7 +171,7 @@ PaymentAppServiceBridge::PaymentAppServiceBridge(
std::vector<mojom::PaymentMethodDataPtr> request_method_data, std::vector<mojom::PaymentMethodDataPtr> request_method_data,
scoped_refptr<PaymentManifestWebDataService> web_data_service, scoped_refptr<PaymentManifestWebDataService> web_data_service,
bool may_crawl_for_installable_payment_apps, bool may_crawl_for_installable_payment_apps,
PaymentAppsCreatedCallback payment_apps_created_callback, PaymentAppCreatedCallback payment_app_created_callback,
PaymentAppCreationErrorCallback payment_app_creation_error_callback, PaymentAppCreationErrorCallback payment_app_creation_error_callback,
base::OnceClosure done_creating_payment_apps_callback) base::OnceClosure done_creating_payment_apps_callback)
: number_of_pending_factories_(number_of_factories), : number_of_pending_factories_(number_of_factories),
...@@ -254,14 +179,13 @@ PaymentAppServiceBridge::PaymentAppServiceBridge( ...@@ -254,14 +179,13 @@ PaymentAppServiceBridge::PaymentAppServiceBridge(
content::WebContents::FromRenderFrameHost(render_frame_host)), content::WebContents::FromRenderFrameHost(render_frame_host)),
render_frame_host_(render_frame_host), render_frame_host_(render_frame_host),
top_origin_(top_origin), top_origin_(top_origin),
frame_origin_(url_formatter::FormatUrlForSecurityDisplay( frame_origin_(render_frame_host->GetLastCommittedURL()),
render_frame_host->GetLastCommittedURL())),
frame_security_origin_(render_frame_host->GetLastCommittedOrigin()), frame_security_origin_(render_frame_host->GetLastCommittedOrigin()),
request_method_data_(std::move(request_method_data)), request_method_data_(std::move(request_method_data)),
payment_manifest_web_data_service_(web_data_service), payment_manifest_web_data_service_(web_data_service),
may_crawl_for_installable_payment_apps_( may_crawl_for_installable_payment_apps_(
may_crawl_for_installable_payment_apps), may_crawl_for_installable_payment_apps),
payment_apps_created_callback_(std::move(payment_apps_created_callback)), payment_app_created_callback_(std::move(payment_app_created_callback)),
payment_app_creation_error_callback_( payment_app_creation_error_callback_(
std::move(payment_app_creation_error_callback)), std::move(payment_app_creation_error_callback)),
done_creating_payment_apps_callback_( done_creating_payment_apps_callback_(
...@@ -347,9 +271,11 @@ bool PaymentAppServiceBridge::SkipCreatingNativePaymentApps() const { ...@@ -347,9 +271,11 @@ bool PaymentAppServiceBridge::SkipCreatingNativePaymentApps() const {
} }
void PaymentAppServiceBridge::OnCreatingNativePaymentAppsSkipped( void PaymentAppServiceBridge::OnCreatingNativePaymentAppsSkipped(
content::PaymentAppProvider::PaymentApps apps, const content::PaymentAppProvider::PaymentApps& apps,
ServiceWorkerPaymentAppFinder::InstallablePaymentApps installable_apps) { const ServiceWorkerPaymentAppFinder::InstallablePaymentApps&
payment_apps_created_callback_.Run(apps, installable_apps); installable_apps) {
// TODO(crbug.com/1063118): call back to Java with apps information.
payment_app_created_callback_.Run();
} }
void PaymentAppServiceBridge::OnPaymentAppCreationError( void PaymentAppServiceBridge::OnPaymentAppCreationError(
......
...@@ -32,9 +32,9 @@ namespace payments { ...@@ -32,9 +32,9 @@ namespace payments {
// callbacks from PaymentAppFactory to callbacks set by the caller. // callbacks from PaymentAppFactory to callbacks set by the caller.
class PaymentAppServiceBridge : public PaymentAppFactory::Delegate { class PaymentAppServiceBridge : public PaymentAppFactory::Delegate {
public: public:
using PaymentAppsCreatedCallback = base::RepeatingCallback<void( // TODO(crbug.com/1063118): add more parameter to this callback to actually
const content::PaymentAppProvider::PaymentApps&, // pass payment app data back to Java side.
const payments::ServiceWorkerPaymentAppFinder::InstallablePaymentApps&)>; using PaymentAppCreatedCallback = base::RepeatingCallback<void()>;
using PaymentAppCreationErrorCallback = using PaymentAppCreationErrorCallback =
base::RepeatingCallback<void(const std::string&)>; base::RepeatingCallback<void(const std::string&)>;
...@@ -48,7 +48,7 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate { ...@@ -48,7 +48,7 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate {
std::vector<mojom::PaymentMethodDataPtr> request_method_data, std::vector<mojom::PaymentMethodDataPtr> request_method_data,
scoped_refptr<PaymentManifestWebDataService> web_data_service, scoped_refptr<PaymentManifestWebDataService> web_data_service,
bool may_crawl_for_installable_payment_apps, bool may_crawl_for_installable_payment_apps,
PaymentAppsCreatedCallback payment_apps_created_callback, PaymentAppCreatedCallback payment_app_created_callback,
PaymentAppCreationErrorCallback payment_app_creation_error_callback, PaymentAppCreationErrorCallback payment_app_creation_error_callback,
base::OnceClosure done_creating_payment_apps_callback); base::OnceClosure done_creating_payment_apps_callback);
...@@ -81,9 +81,9 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate { ...@@ -81,9 +81,9 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate {
void OnPaymentAppCreationError(const std::string& error_message) override; void OnPaymentAppCreationError(const std::string& error_message) override;
bool SkipCreatingNativePaymentApps() const override; bool SkipCreatingNativePaymentApps() const override;
void OnCreatingNativePaymentAppsSkipped( void OnCreatingNativePaymentAppsSkipped(
content::PaymentAppProvider::PaymentApps apps, const content::PaymentAppProvider::PaymentApps& apps,
ServiceWorkerPaymentAppFinder::InstallablePaymentApps installable_apps) const ServiceWorkerPaymentAppFinder::InstallablePaymentApps&
override; installable_apps) override;
void OnDoneCreatingPaymentApps() override; void OnDoneCreatingPaymentApps() override;
private: private:
...@@ -95,7 +95,7 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate { ...@@ -95,7 +95,7 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate {
std::vector<mojom::PaymentMethodDataPtr> request_method_data, std::vector<mojom::PaymentMethodDataPtr> request_method_data,
scoped_refptr<PaymentManifestWebDataService> web_data_service, scoped_refptr<PaymentManifestWebDataService> web_data_service,
bool may_crawl_for_installable_payment_apps, bool may_crawl_for_installable_payment_apps,
PaymentAppsCreatedCallback payment_apps_created_callback, PaymentAppCreatedCallback payment_app_created_callback,
PaymentAppCreationErrorCallback payment_app_creation_error_callback, PaymentAppCreationErrorCallback payment_app_creation_error_callback,
base::OnceClosure done_creating_payment_apps_callback); base::OnceClosure done_creating_payment_apps_callback);
...@@ -111,7 +111,7 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate { ...@@ -111,7 +111,7 @@ class PaymentAppServiceBridge : public PaymentAppFactory::Delegate {
bool may_crawl_for_installable_payment_apps_; bool may_crawl_for_installable_payment_apps_;
std::vector<autofill::AutofillProfile*> dummy_profiles_; std::vector<autofill::AutofillProfile*> dummy_profiles_;
PaymentAppsCreatedCallback payment_apps_created_callback_; PaymentAppCreatedCallback payment_app_created_callback_;
PaymentAppCreationErrorCallback payment_app_creation_error_callback_; PaymentAppCreationErrorCallback payment_app_creation_error_callback_;
base::OnceClosure done_creating_payment_apps_callback_; base::OnceClosure done_creating_payment_apps_callback_;
......
...@@ -24,10 +24,7 @@ namespace payments { ...@@ -24,10 +24,7 @@ namespace payments {
class MockCallback { class MockCallback {
public: public:
MockCallback() = default; MockCallback() = default;
MOCK_METHOD2(NotifyPaymentAppsCreated, MOCK_METHOD0(NotifyPaymentAppCreated, void(void));
void(const content::PaymentAppProvider::PaymentApps&,
const payments::ServiceWorkerPaymentAppFinder::
InstallablePaymentApps&));
MOCK_METHOD1(NotifyPaymentAppCreationError, void(const std::string& error)); MOCK_METHOD1(NotifyPaymentAppCreationError, void(const std::string& error));
MOCK_METHOD0(NotifyDoneCreatingPaymentApps, void(void)); MOCK_METHOD0(NotifyDoneCreatingPaymentApps, void(void));
}; };
...@@ -71,7 +68,7 @@ TEST_F(PaymentAppServiceBridgeUnitTest, Smoke) { ...@@ -71,7 +68,7 @@ TEST_F(PaymentAppServiceBridgeUnitTest, Smoke) {
/* number_of_factories= */ 3, web_contents_->GetMainFrame(), /* number_of_factories= */ 3, web_contents_->GetMainFrame(),
top_origin_, std::move(method_data), web_data_service_, top_origin_, std::move(method_data), web_data_service_,
/* may_crawl_for_installable_payment_apps= */ true, /* may_crawl_for_installable_payment_apps= */ true,
base::BindRepeating(&MockCallback::NotifyPaymentAppsCreated, base::BindRepeating(&MockCallback::NotifyPaymentAppCreated,
base::Unretained(&mock_callback)), base::Unretained(&mock_callback)),
base::BindRepeating(&MockCallback::NotifyPaymentAppCreationError, base::BindRepeating(&MockCallback::NotifyPaymentAppCreationError,
base::Unretained(&mock_callback)), base::Unretained(&mock_callback)),
...@@ -95,10 +92,8 @@ TEST_F(PaymentAppServiceBridgeUnitTest, Smoke) { ...@@ -95,10 +92,8 @@ TEST_F(PaymentAppServiceBridgeUnitTest, Smoke) {
content::PaymentAppProvider::PaymentApps apps; content::PaymentAppProvider::PaymentApps apps;
ServiceWorkerPaymentAppFinder::InstallablePaymentApps installables; ServiceWorkerPaymentAppFinder::InstallablePaymentApps installables;
EXPECT_CALL(mock_callback, EXPECT_CALL(mock_callback, NotifyPaymentAppCreated());
NotifyPaymentAppsCreated(::testing::_, ::testing::_)); bridge->OnCreatingNativePaymentAppsSkipped(apps, installables);
bridge->OnCreatingNativePaymentAppsSkipped(std::move(apps),
std::move(installables));
EXPECT_CALL(mock_callback, NotifyPaymentAppCreationError("some error")); EXPECT_CALL(mock_callback, NotifyPaymentAppCreationError("some error"));
bridge->OnPaymentAppCreationError("some error"); bridge->OnPaymentAppCreationError("some error");
......
...@@ -60,6 +60,92 @@ using ::payments::mojom::PaymentShippingOption; ...@@ -60,6 +60,92 @@ using ::payments::mojom::PaymentShippingOption;
using ::payments::mojom::PaymentShippingOptionPtr; using ::payments::mojom::PaymentShippingOptionPtr;
using ::payments::mojom::PaymentShippingType; using ::payments::mojom::PaymentShippingType;
void OnGotAllPaymentApps(
const JavaRef<jobject>& jcallback,
content::PaymentAppProvider::PaymentApps apps,
payments::ServiceWorkerPaymentAppFinder::InstallablePaymentApps
installable_apps,
const std::string& error_message) {
JNIEnv* env = AttachCurrentThread();
if (!error_message.empty()) {
Java_PaymentHandlerFinder_onGetPaymentAppsError(
env, jcallback, ConvertUTF8ToJavaString(env, error_message));
}
for (const auto& app_info : apps) {
// Sends related application Ids to java side if the app prefers related
// applications.
std::vector<std::string> preferred_related_application_ids;
if (app_info.second->prefer_related_applications) {
for (const auto& related_application :
app_info.second->related_applications) {
// Only consider related applications on Google play for Android.
if (related_application.platform == "play")
preferred_related_application_ids.emplace_back(
related_application.id);
}
}
base::android::ScopedJavaLocalRef<jobjectArray> jcapabilities =
Java_ServiceWorkerPaymentAppBridge_createCapabilities(
env, app_info.second->capabilities.size());
for (size_t i = 0; i < app_info.second->capabilities.size(); i++) {
Java_ServiceWorkerPaymentAppBridge_addCapabilities(
env, jcapabilities, base::checked_cast<int>(i),
ToJavaIntArray(
env, app_info.second->capabilities[i].supported_card_networks));
}
base::android::ScopedJavaLocalRef<jobject> jsupported_delegations =
Java_ServiceWorkerPaymentAppBridge_createSupportedDelegations(
env, app_info.second->supported_delegations.shipping_address,
app_info.second->supported_delegations.payer_name,
app_info.second->supported_delegations.payer_phone,
app_info.second->supported_delegations.payer_email);
// TODO(crbug.com/846077): Find a proper way to make use of user hint.
Java_PaymentHandlerFinder_onInstalledPaymentHandlerFound(
env, jcallback, app_info.second->registration_id,
ConvertUTF8ToJavaString(env, app_info.second->scope.spec()),
app_info.second->name.empty()
? nullptr
: ConvertUTF8ToJavaString(env, app_info.second->name),
nullptr, ConvertUTF8ToJavaString(env, app_info.second->scope.host()),
app_info.second->icon == nullptr
? nullptr
: gfx::ConvertToJavaBitmap(app_info.second->icon.get()),
ToJavaArrayOfStrings(env, app_info.second->enabled_methods),
app_info.second->has_explicitly_verified_methods, jcapabilities,
ToJavaArrayOfStrings(env, preferred_related_application_ids),
jsupported_delegations);
}
for (const auto& installable_app : installable_apps) {
base::android::ScopedJavaLocalRef<jobject> jsupported_delegations =
Java_ServiceWorkerPaymentAppBridge_createSupportedDelegations(
env, installable_app.second->supported_delegations.shipping_address,
installable_app.second->supported_delegations.payer_name,
installable_app.second->supported_delegations.payer_phone,
installable_app.second->supported_delegations.payer_email);
Java_PaymentHandlerFinder_onInstallablePaymentHandlerFound(
env, jcallback,
ConvertUTF8ToJavaString(env, installable_app.second->name),
ConvertUTF8ToJavaString(env, installable_app.second->sw_js_url),
ConvertUTF8ToJavaString(env, installable_app.second->sw_scope),
installable_app.second->sw_use_cache,
installable_app.second->icon == nullptr
? nullptr
: gfx::ConvertToJavaBitmap(installable_app.second->icon.get()),
ConvertUTF8ToJavaString(env, installable_app.first.spec()),
ToJavaArrayOfStrings(env, installable_app.second->preferred_app_ids),
jsupported_delegations);
}
Java_PaymentHandlerFinder_onAllPaymentAppsCreated(env, jcallback);
}
void OnHasServiceWorkerPaymentAppsResponse( void OnHasServiceWorkerPaymentAppsResponse(
const JavaRef<jobject>& jcallback, const JavaRef<jobject>& jcallback,
content::PaymentAppProvider::PaymentApps apps) { content::PaymentAppProvider::PaymentApps apps) {
...@@ -92,10 +178,11 @@ void OnGetServiceWorkerPaymentAppsInfo( ...@@ -92,10 +178,11 @@ void OnGetServiceWorkerPaymentAppsInfo(
} }
void OnCanMakePayment(const JavaRef<jobject>& jcallback, void OnCanMakePayment(const JavaRef<jobject>& jcallback,
const JavaRef<jobject>& japp,
payments::mojom::CanMakePaymentResponsePtr response) { payments::mojom::CanMakePaymentResponsePtr response) {
JNIEnv* env = AttachCurrentThread(); JNIEnv* env = AttachCurrentThread();
Java_ServiceWorkerPaymentAppBridge_onCanMakePaymentEventResponse( Java_PaymentHandlerFinder_onCanMakePaymentEventResponse(
env, jcallback, env, jcallback, japp,
ConvertUTF8ToJavaString( ConvertUTF8ToJavaString(
env, payments::ConvertCanMakePaymentEventResponseTypeToErrorString( env, payments::ConvertCanMakePaymentEventResponseTypeToErrorString(
response->response_type)), response->response_type)),
...@@ -332,6 +419,35 @@ PaymentRequestEventDataPtr ConvertPaymentRequestEventDataFromJavaToNative( ...@@ -332,6 +419,35 @@ PaymentRequestEventDataPtr ConvertPaymentRequestEventDataFromJavaToNative(
} // namespace } // namespace
static void JNI_ServiceWorkerPaymentAppBridge_GetAllPaymentApps(
JNIEnv* env,
const JavaParamRef<jobject>& jorigin,
const JavaParamRef<jobject>& jrender_frame_host,
const JavaParamRef<jobjectArray>& jmethod_data,
jboolean jmay_crawl_for_installable_payment_apps,
const JavaParamRef<jobject>& jcallback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::RenderFrameHost* render_frame_host =
content::RenderFrameHost::FromJavaRenderFrameHost(jrender_frame_host);
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
payments::ServiceWorkerPaymentAppFinder::GetInstance()->GetAllPaymentApps(
url::Origin::FromJavaObject(jorigin), render_frame_host, web_contents,
WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext()),
ServiceAccessType::EXPLICIT_ACCESS),
ConvertPaymentMethodDataFromJavaToNative(env, jmethod_data),
jmay_crawl_for_installable_payment_apps,
base::BindOnce(&OnGotAllPaymentApps,
ScopedJavaGlobalRef<jobject>(env, jcallback)),
base::BindOnce([]() {
/* Nothing needs to be done after writing cache. This callback is used
* only in tests. */
}));
}
static void JNI_ServiceWorkerPaymentAppBridge_HasServiceWorkerPaymentApps( static void JNI_ServiceWorkerPaymentAppBridge_HasServiceWorkerPaymentApps(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jobject>& jcallback) { const JavaParamRef<jobject>& jcallback) {
...@@ -363,7 +479,8 @@ static void JNI_ServiceWorkerPaymentAppBridge_FireCanMakePaymentEvent( ...@@ -363,7 +479,8 @@ static void JNI_ServiceWorkerPaymentAppBridge_FireCanMakePaymentEvent(
const JavaParamRef<jobjectArray>& jmethod_data, const JavaParamRef<jobjectArray>& jmethod_data,
const JavaParamRef<jobjectArray>& jmodifiers, const JavaParamRef<jobjectArray>& jmodifiers,
const JavaParamRef<jstring>& jcurrency, const JavaParamRef<jstring>& jcurrency,
const JavaParamRef<jobject>& jcallback) { const JavaParamRef<jobject>& jcallback,
const JavaParamRef<jobject>& japp) {
content::WebContents* web_contents = content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(jweb_contents); content::WebContents::FromJavaWebContents(jweb_contents);
...@@ -416,7 +533,8 @@ static void JNI_ServiceWorkerPaymentAppBridge_FireCanMakePaymentEvent( ...@@ -416,7 +533,8 @@ static void JNI_ServiceWorkerPaymentAppBridge_FireCanMakePaymentEvent(
GURL(ConvertJavaStringToUTF8(env, jservice_worker_scope))), GURL(ConvertJavaStringToUTF8(env, jservice_worker_scope))),
ConvertJavaStringToUTF8(env, jpayment_request_id), std::move(event_data), ConvertJavaStringToUTF8(env, jpayment_request_id), std::move(event_data),
base::BindOnce(&OnCanMakePayment, base::BindOnce(&OnCanMakePayment,
ScopedJavaGlobalRef<jobject>(env, jcallback))); ScopedJavaGlobalRef<jobject>(env, jcallback),
ScopedJavaGlobalRef<jobject>(env, japp)));
} }
static void JNI_ServiceWorkerPaymentAppBridge_InvokePaymentApp( static void JNI_ServiceWorkerPaymentAppBridge_InvokePaymentApp(
......
...@@ -84,8 +84,8 @@ class PaymentAppFactory { ...@@ -84,8 +84,8 @@ class PaymentAppFactory {
// When SkipCreatingNativePaymentApps() is true, this callback is called // When SkipCreatingNativePaymentApps() is true, this callback is called
// when service-worker payment app info is available. // when service-worker payment app info is available.
virtual void OnCreatingNativePaymentAppsSkipped( virtual void OnCreatingNativePaymentAppsSkipped(
content::PaymentAppProvider::PaymentApps apps, const content::PaymentAppProvider::PaymentApps& apps,
ServiceWorkerPaymentAppFinder::InstallablePaymentApps const ServiceWorkerPaymentAppFinder::InstallablePaymentApps&
installable_apps) = 0; installable_apps) = 0;
// Called when all apps of this factory have been created. // Called when all apps of this factory have been created.
......
...@@ -181,8 +181,8 @@ bool PaymentRequestState::SkipCreatingNativePaymentApps() const { ...@@ -181,8 +181,8 @@ bool PaymentRequestState::SkipCreatingNativePaymentApps() const {
} }
void PaymentRequestState::OnCreatingNativePaymentAppsSkipped( void PaymentRequestState::OnCreatingNativePaymentAppsSkipped(
content::PaymentAppProvider::PaymentApps unused_apps, const content::PaymentAppProvider::PaymentApps& unused_apps,
ServiceWorkerPaymentAppFinder::InstallablePaymentApps const ServiceWorkerPaymentAppFinder::InstallablePaymentApps&
unused_installable_apps) { unused_installable_apps) {
NOTREACHED(); NOTREACHED();
} }
......
...@@ -150,9 +150,9 @@ class PaymentRequestState : public PaymentAppFactory::Delegate, ...@@ -150,9 +150,9 @@ class PaymentRequestState : public PaymentAppFactory::Delegate,
void OnPaymentAppCreationError(const std::string& error_message) override; void OnPaymentAppCreationError(const std::string& error_message) override;
bool SkipCreatingNativePaymentApps() const override; bool SkipCreatingNativePaymentApps() const override;
void OnCreatingNativePaymentAppsSkipped( void OnCreatingNativePaymentAppsSkipped(
content::PaymentAppProvider::PaymentApps apps, const content::PaymentAppProvider::PaymentApps& apps,
ServiceWorkerPaymentAppFinder::InstallablePaymentApps installable_apps) const ServiceWorkerPaymentAppFinder::InstallablePaymentApps&
override; installable_apps) override;
void OnDoneCreatingPaymentApps() override; void OnDoneCreatingPaymentApps() override;
// PaymentResponseHelper::Delegate // PaymentResponseHelper::Delegate
......
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