Commit cf391422 authored by Liquan (Max) Gu's avatar Liquan (Max) Gu Committed by Commit Bot

[WebLayer] Refactors CPRService#updateWith

Changes:
* Replaced `mPaymentUiService.getPaymentRequestUI() == null` with
  `mIsCurrentPaymentRequestShowing` as the way to check for 'update-
  without-show".
* Renamed "parseAndValidateDetailsForSkipToGPayHelper" as
  "parseAndValidateDetailsFurtherIfNeeded" because PRService needs to
  call it, and PRService does not know about skip-to-gpay.
* Moved the main logic of CPRService#updateWith into PRService, with
  the remaining part called onPaymentDetailsUpdated() left in
  CPRService.
* Since "invokedPaymentApp.updateWith()" is moved into PRService,
  PRService delegates the dependency MethodChecker.

Bug: 1131059

Change-Id: If305338491240b16d230e3ab6b43d0c64c256de7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2530312
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#826326}
parent caa82f8f
...@@ -31,6 +31,7 @@ import org.chromium.components.payments.PaymentApp; ...@@ -31,6 +31,7 @@ import org.chromium.components.payments.PaymentApp;
import org.chromium.components.payments.PaymentAppService; import org.chromium.components.payments.PaymentAppService;
import org.chromium.components.payments.PaymentAppType; import org.chromium.components.payments.PaymentAppType;
import org.chromium.components.payments.PaymentDetailsConverter; import org.chromium.components.payments.PaymentDetailsConverter;
import org.chromium.components.payments.PaymentDetailsConverter.MethodChecker;
import org.chromium.components.payments.PaymentDetailsUpdateServiceHelper; import org.chromium.components.payments.PaymentDetailsUpdateServiceHelper;
import org.chromium.components.payments.PaymentFeatureList; import org.chromium.components.payments.PaymentFeatureList;
import org.chromium.components.payments.PaymentHandlerHost; import org.chromium.components.payments.PaymentHandlerHost;
...@@ -214,7 +215,7 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest, ...@@ -214,7 +215,7 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest,
mSkipToGPayHelper = new SkipToGPayHelper(options, data.gpayBridgeData); mSkipToGPayHelper = new SkipToGPayHelper(options, data.gpayBridgeData);
} }
if (!parseAndValidateDetailsForSkipToGPayHelper(details)) { if (!parseAndValidateDetailsFurtherIfNeeded(details)) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER); mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_PAYMENT_DETAILS); disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_PAYMENT_DETAILS);
return true; return true;
...@@ -484,57 +485,23 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest, ...@@ -484,57 +485,23 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest,
} }
// Implement BrowserPaymentRequest: // Implement BrowserPaymentRequest:
/**
* Called by merchant to update the shipping options and line items after the user has selected
* their shipping address or shipping option.
*/
@Override @Override
public void updateWith(PaymentDetails details) { public MethodChecker getMethodChecker() {
return this;
}
// Implement BrowserPaymentRequest:
@Override
public void onPaymentDetailsUpdated(
PaymentDetails details, boolean hasNotifiedInvokedPaymentApp) {
if (mPaymentRequestService == null) return; if (mPaymentRequestService == null) return;
// mSpec.updateWith() can be used only when mSpec has not been destroyed. // mSpec.updateWith() can be used only when mSpec has not been destroyed.
assert !mSpec.isDestroyed(); assert !mSpec.isDestroyed();
if (mPaymentRequestService.isShowWaitingForUpdatedDetails()) {
// Under this condition, updateWith() is called in response to the resolution of
// show()'s PaymentDetailsUpdate promise.
continueShow(details);
return;
}
if (mPaymentUiService.getPaymentRequestUI() == null) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(ErrorStrings.CANNOT_UPDATE_WITHOUT_SHOW);
return;
}
PaymentApp invokedPaymentApp = mPaymentRequestService.getInvokedPaymentApp();
if (!PaymentOptionsUtils.requestAnyInformation(mPaymentOptions)
&& (invokedPaymentApp == null
|| !invokedPaymentApp.isWaitingForPaymentDetailsUpdate())) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_STATE);
return;
}
if (!PaymentValidator.validatePaymentDetails(details)
|| !parseAndValidateDetailsForSkipToGPayHelper(details)) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_PAYMENT_DETAILS);
return;
}
mSpec.updateWith(details);
mPaymentUiService.updateDetailsOnPaymentRequestUI( mPaymentUiService.updateDetailsOnPaymentRequestUI(
mSpec.getPaymentDetails(), mSpec.getRawTotal(), mSpec.getRawLineItems()); mSpec.getPaymentDetails(), mSpec.getRawTotal(), mSpec.getRawLineItems());
if (invokedPaymentApp != null && invokedPaymentApp.isWaitingForPaymentDetailsUpdate()) { if (hasNotifiedInvokedPaymentApp) return;
// After a payment app has been invoked, all of the merchant's calls to update the price
// via updateWith() should be forwarded to the invoked app, so it can reflect the
// updated price in its UI.
invokedPaymentApp.updateWith(
PaymentDetailsConverter.convertToPaymentRequestDetailsUpdate(details,
/*methodChecker=*/this, invokedPaymentApp));
return;
}
if (mPaymentUiService.shouldShowShippingSection() if (mPaymentUiService.shouldShowShippingSection()
&& (mPaymentUiService.getUiShippingOptions().isEmpty() && (mPaymentUiService.getUiShippingOptions().isEmpty()
...@@ -551,7 +518,9 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest, ...@@ -551,7 +518,9 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest,
if (providedInformationToPaymentRequestUI) recordShowEventAndTransactionAmount(); if (providedInformationToPaymentRequestUI) recordShowEventAndTransactionAmount();
} }
private void continueShow(PaymentDetails details) { // Implements BrowserPaymentRequest:
@Override
public void continueShow(PaymentDetails details) {
assert mPaymentRequestService.isShowWaitingForUpdatedDetails(); assert mPaymentRequestService.isShowWaitingForUpdatedDetails();
// mSpec.updateWith() can be used only when mSpec has not been destroyed. // mSpec.updateWith() can be used only when mSpec has not been destroyed.
assert !mSpec.isDestroyed(); assert !mSpec.isDestroyed();
...@@ -564,7 +533,7 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest, ...@@ -564,7 +533,7 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest,
} }
if (!PaymentValidator.validatePaymentDetails(details) if (!PaymentValidator.validatePaymentDetails(details)
|| !parseAndValidateDetailsForSkipToGPayHelper(details)) { || !parseAndValidateDetailsFurtherIfNeeded(details)) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER); mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_PAYMENT_DETAILS); disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_PAYMENT_DETAILS);
return; return;
...@@ -651,13 +620,9 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest, ...@@ -651,13 +620,9 @@ public class ChromePaymentRequestService implements BrowserPaymentRequest,
if (providedInformationToPaymentRequestUI) recordShowEventAndTransactionAmount(); if (providedInformationToPaymentRequestUI) recordShowEventAndTransactionAmount();
} }
/** // Implements BrowserPaymentRequest:
* If executing on the skip-to-gpay flow, do the flow's specific validation for details. If @Override
* valid, set shipping options for SkipToGPayHelper. public boolean parseAndValidateDetailsFurtherIfNeeded(PaymentDetails details) {
* @param details The details specified by the merchant.
* @return True if skip-to-gpay parameters are valid or when skip-to-gpay does not apply.
*/
private boolean parseAndValidateDetailsForSkipToGPayHelper(PaymentDetails details) {
return mSkipToGPayHelper == null || mSkipToGPayHelper.setShippingOptionIfValid(details); return mSkipToGPayHelper == null || mSkipToGPayHelper.setShippingOptionIfValid(details);
} }
......
...@@ -6,6 +6,7 @@ package org.chromium.components.payments; ...@@ -6,6 +6,7 @@ package org.chromium.components.payments;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.chromium.components.payments.PaymentDetailsConverter.MethodChecker;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.payments.mojom.PaymentDetails; import org.chromium.payments.mojom.PaymentDetails;
import org.chromium.payments.mojom.PaymentMethodData; import org.chromium.payments.mojom.PaymentMethodData;
...@@ -36,10 +37,13 @@ public interface BrowserPaymentRequest { ...@@ -36,10 +37,13 @@ public interface BrowserPaymentRequest {
} }
/** /**
* The browser part of the {@link PaymentRequest#updateWith} implementation. * The client of the interface calls this when it has received the payment details update
* from the merchant and has updated the PaymentRequestSpec.
* @param details The details that the merchant provides to update the payment request. * @param details The details that the merchant provides to update the payment request.
* @param hasNotifiedInvokedPaymentApp Whether the client has notified the invoked
* payment app of the updated details.
*/ */
void updateWith(PaymentDetails details); void onPaymentDetailsUpdated(PaymentDetails details, boolean hasNotifiedInvokedPaymentApp);
/** The browser part of the {@link PaymentRequest#onPaymentDetailsNotUpdated} implementation. */ /** The browser part of the {@link PaymentRequest#onPaymentDetailsNotUpdated} implementation. */
void onPaymentDetailsNotUpdated(); void onPaymentDetailsNotUpdated();
...@@ -187,4 +191,28 @@ public interface BrowserPaymentRequest { ...@@ -187,4 +191,28 @@ public interface BrowserPaymentRequest {
default boolean isShowingUi() { default boolean isShowingUi() {
return false; return false;
} }
/**
* Continues the unfinished part of show() that was blocked for the payment details that was
* pending to be updated.
* @param details The updated payment details that show() is waiting for.
*/
default void continueShow(PaymentDetails details) {}
/**
* If needed, do extra parsing and validation for details.
* @param details The details specified by the merchant.
* @return True if the validation pass.
*/
default boolean parseAndValidateDetailsFurtherIfNeeded(PaymentDetails details) {
return true;
}
/**
* @return The {@link MethodChecker} that can check whether the invoked payment app is valid for
* the given payment method identifier.
*/
default MethodChecker getMethodChecker() {
return null;
}
} }
...@@ -941,7 +941,50 @@ public class PaymentRequestService ...@@ -941,7 +941,50 @@ public class PaymentRequestService
*/ */
/* package */ void updateWith(PaymentDetails details) { /* package */ void updateWith(PaymentDetails details) {
if (mBrowserPaymentRequest == null) return; if (mBrowserPaymentRequest == null) return;
mBrowserPaymentRequest.updateWith(details); if (mIsShowWaitingForUpdatedDetails) {
// Under this condition, updateWith() is called in response to the resolution of
// show()'s PaymentDetailsUpdate promise.
mBrowserPaymentRequest.continueShow(details);
return;
}
if (!mIsCurrentPaymentRequestShowing) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(
ErrorStrings.CANNOT_UPDATE_WITHOUT_SHOW, PaymentErrorReason.USER_CANCEL);
return;
}
if (!PaymentOptionsUtils.requestAnyInformation(mPaymentOptions)
&& (mInvokedPaymentApp == null
|| !mInvokedPaymentApp.isWaitingForPaymentDetailsUpdate())) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(
ErrorStrings.INVALID_STATE, PaymentErrorReason.USER_CANCEL);
return;
}
if (!PaymentValidator.validatePaymentDetails(details)
|| !mBrowserPaymentRequest.parseAndValidateDetailsFurtherIfNeeded(details)) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(
ErrorStrings.INVALID_PAYMENT_DETAILS, PaymentErrorReason.USER_CANCEL);
return;
}
mSpec.updateWith(details);
boolean hasNotifiedInvokedPaymentApp =
mInvokedPaymentApp != null && mInvokedPaymentApp.isWaitingForPaymentDetailsUpdate();
if (hasNotifiedInvokedPaymentApp) {
// After a payment app has been invoked, all of the merchant's calls to update the price
// via updateWith() should be forwarded to the invoked app, so it can reflect the
// updated price in its UI.
mInvokedPaymentApp.updateWith(
PaymentDetailsConverter.convertToPaymentRequestDetailsUpdate(details,
/*methodChecker=*/mBrowserPaymentRequest.getMethodChecker(),
mInvokedPaymentApp));
}
mBrowserPaymentRequest.onPaymentDetailsUpdated(details, hasNotifiedInvokedPaymentApp);
} }
/** /**
......
...@@ -24,7 +24,8 @@ public class WebLayerPaymentRequestService implements BrowserPaymentRequest { ...@@ -24,7 +24,8 @@ public class WebLayerPaymentRequestService implements BrowserPaymentRequest {
} }
@Override @Override
public void updateWith(PaymentDetails details) { public void onPaymentDetailsUpdated(
PaymentDetails details, boolean hasNotifiedInvokedPaymentApp) {
assert false : "Not implemented yet"; assert false : "Not implemented yet";
} }
......
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