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

Should call onWebContentsForRequestAvailable only once

Change:
* onWebContentsForRequestAvailable() was called two times when
bottomSheetController.requestShowContent() failed in
PaymentHandlerCoordinator. One is in PaymentHandlerCoordinator; one is
in ServiceTabLauncher. Now, onWebContentsForRequestAvailable()
guaranteed to be called only once - in ServiceTabLauncher only.

Bug: 1132972

Change-Id: Iba288b1287e034a35ff83994f5f675b5df463527
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2435739Reviewed-by: default avatarLiquan (Max) Gu <maxlg@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811465}
parent b4ecdad7
...@@ -81,8 +81,12 @@ public class ServiceTabLauncher { ...@@ -81,8 +81,12 @@ public class ServiceTabLauncher {
if (disposition == WindowOpenDisposition.NEW_POPUP) { if (disposition == WindowOpenDisposition.NEW_POPUP) {
boolean success = false; boolean success = false;
if (PaymentHandlerCoordinator.isEnabled()) { if (PaymentHandlerCoordinator.isEnabled()) {
success = PaymentRequestImpl.openPaymentHandlerWindow(url, WebContents paymentHandlerWebContent =
(webContents) -> onWebContentsForRequestAvailable(requestId, webContents)); PaymentRequestImpl.openPaymentHandlerWindow(url);
if (paymentHandlerWebContent != null) {
success = true;
onWebContentsForRequestAvailable(requestId, paymentHandlerWebContent);
}
} else { } else {
success = createPopupCustomTab(requestId, url.getSpec(), incognito); success = createPopupCustomTab(requestId, url.getSpec(), incognito);
} }
......
...@@ -20,7 +20,6 @@ import org.chromium.chrome.R; ...@@ -20,7 +20,6 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator; import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerWebContentsObserver;
import org.chromium.chrome.browser.payments.ui.PaymentInformation; import org.chromium.chrome.browser.payments.ui.PaymentInformation;
import org.chromium.chrome.browser.payments.ui.PaymentRequestUI; import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
import org.chromium.chrome.browser.payments.ui.PaymentUIsManager; import org.chromium.chrome.browser.payments.ui.PaymentUIsManager;
...@@ -683,39 +682,37 @@ public class PaymentRequestImpl ...@@ -683,39 +682,37 @@ public class PaymentRequestImpl
/** /**
* Called to open a new PaymentHandler UI on the showing PaymentRequest. * Called to open a new PaymentHandler UI on the showing PaymentRequest.
* @param url The url of the payment app to be displayed in the UI. * @param url The url of the payment app to be displayed in the UI.
* @param paymentHandlerWebContentsObserver The observer of the WebContents of the * @return The WebContents of the payment handler that's just opened when the opening is
* PaymentHandler. * successful; null if failed.
* @return Whether the opening is successful.
*/ */
public static boolean openPaymentHandlerWindow( @Nullable
GURL url, PaymentHandlerWebContentsObserver paymentHandlerWebContentsObserver) { public static WebContents openPaymentHandlerWindow(GURL url) {
return sShowingPaymentRequest != null if (sShowingPaymentRequest == null) return null;
&& sShowingPaymentRequest.openPaymentHandlerWindowInternal( return sShowingPaymentRequest.openPaymentHandlerWindowInternal(url);
url, paymentHandlerWebContentsObserver);
} }
/** /**
* Called to open a new PaymentHandler UI on this PaymentRequest. * Called to open a new PaymentHandler UI on this PaymentRequest.
* @param url The url of the payment app to be displayed in the UI. * @param url The url of the payment app to be displayed in the UI.
* @param paymentHandlerWebContentsObserver The observer of the WebContents of the * @return The WebContents of the payment handler that's just opened when the opening is
* PaymentHandler. * successful; null if failed.
* @return Whether the opening is successful.
*/ */
private boolean openPaymentHandlerWindowInternal( @Nullable
GURL url, PaymentHandlerWebContentsObserver paymentHandlerWebContentsObserver) { private WebContents openPaymentHandlerWindowInternal(GURL url) {
assert mInvokedPaymentApp != null; assert mInvokedPaymentApp != null;
assert mInvokedPaymentApp.getPaymentAppType() == PaymentAppType.SERVICE_WORKER_APP; assert mInvokedPaymentApp.getPaymentAppType() == PaymentAppType.SERVICE_WORKER_APP;
if (mComponentPaymentRequestImpl == null) return false; if (mComponentPaymentRequestImpl == null) return null;
boolean success = mPaymentUIsManager.showPaymentHandlerUI(mWebContents, url, @Nullable
paymentHandlerWebContentsObserver, mComponentPaymentRequestImpl.isOffTheRecord()); WebContents paymentHandlerWebContents = mPaymentUIsManager.showPaymentHandlerUI(
if (success) { url, mComponentPaymentRequestImpl.isOffTheRecord());
if (paymentHandlerWebContents != null) {
// UKM for payment app origin should get recorded only when the origin of the invoked // UKM for payment app origin should get recorded only when the origin of the invoked
// payment app is shown to the user. // payment app is shown to the user.
mJourneyLogger.setPaymentAppUkmSourceId(mInvokedPaymentApp.getUkmSourceId()); mJourneyLogger.setPaymentAppUkmSourceId(mInvokedPaymentApp.getUkmSourceId());
} }
return success; return paymentHandlerWebContents;
} }
@Override @Override
......
...@@ -34,7 +34,7 @@ import org.chromium.url.GURL; ...@@ -34,7 +34,7 @@ import org.chromium.url.GURL;
*/ */
public class PaymentHandlerCoordinator { public class PaymentHandlerCoordinator {
private Runnable mHider; private Runnable mHider;
private WebContents mWebContents; private WebContents mPaymentHandlerWebContents;
private PaymentHandlerToolbarCoordinator mToolbarCoordinator; private PaymentHandlerToolbarCoordinator mToolbarCoordinator;
/** Constructs the payment-handler component coordinator. */ /** Constructs the payment-handler component coordinator. */
...@@ -50,57 +50,50 @@ public class PaymentHandlerCoordinator { ...@@ -50,57 +50,50 @@ public class PaymentHandlerCoordinator {
void onPaymentHandlerUiShown(); void onPaymentHandlerUiShown();
} }
/** Observes the WebContents of the payment-handler UI. */
public interface PaymentHandlerWebContentsObserver {
/**
* Called when the WebContents has been initialized.
* @param webContents The WebContents of the PaymentHandler.
*/
void onWebContentsInitialized(WebContents webContents);
}
/** /**
* Shows the payment-handler UI. * Shows the payment-handler UI.
* *
* @param activity The activity where the UI should be shown. * @param paymentRequestWebContents The WebContents of the merchant's frame.
* @param url The url of the payment handler app, i.e., that of * @param url The url of the payment handler app, i.e., that of
* "PaymentRequestEvent.openWindow(url)". * "PaymentRequestEvent.openWindow(url)".
* @param isIncognito Whether the tab is in incognito mode. * @param isIncognito Whether the tab is in incognito mode.
* @param webContentsObserver The observer of the WebContents of the
* PaymentHandler.
* @param uiObserver The {@link PaymentHandlerUiObserver} that observes this Payment Handler UI. * @param uiObserver The {@link PaymentHandlerUiObserver} that observes this Payment Handler UI.
* @return Whether the payment-handler UI was shown. Can be false if the UI was suppressed. * @return The WebContents of the payment handler that's just opened when the showing is
* successful; null if failed.
*/ */
public boolean show(ChromeActivity activity, GURL url, boolean isIncognito, public WebContents show(WebContents paymentRequestWebContents, GURL url, boolean isIncognito,
PaymentHandlerWebContentsObserver webContentsObserver,
PaymentHandlerUiObserver uiObserver) { PaymentHandlerUiObserver uiObserver) {
assert mHider == null : "Already showing payment-handler UI"; assert mHider == null : "Already showing payment-handler UI";
assert paymentRequestWebContents != null;
ChromeActivity activity = ChromeActivity.fromWebContents(paymentRequestWebContents);
if (activity == null) return null;
mWebContents = WebContentsFactory.createWebContents(isIncognito, /*initiallyHidden=*/false); mPaymentHandlerWebContents =
WebContentsFactory.createWebContents(isIncognito, /*initiallyHidden=*/false);
ContentView webContentView = ContentView.createContentView( ContentView webContentView = ContentView.createContentView(
activity, null /* eventOffsetHandler */, mWebContents); activity, null /* eventOffsetHandler */, mPaymentHandlerWebContents);
initializeWebContents(activity, webContentView, webContentsObserver, url); initializeWebContents(activity, webContentView, url);
mToolbarCoordinator = new PaymentHandlerToolbarCoordinator(activity, mWebContents, url); mToolbarCoordinator =
new PaymentHandlerToolbarCoordinator(activity, mPaymentHandlerWebContents, url);
PropertyModel model = new PropertyModel.Builder(PaymentHandlerProperties.ALL_KEYS).build(); PropertyModel model = new PropertyModel.Builder(PaymentHandlerProperties.ALL_KEYS).build();
PaymentHandlerMediator mediator = new PaymentHandlerMediator(model, this::hide, PaymentHandlerMediator mediator = new PaymentHandlerMediator(model, this::hide,
mWebContents, uiObserver, activity.getActivityTab().getView(), mPaymentHandlerWebContents, uiObserver, activity.getActivityTab().getView(),
mToolbarCoordinator.getToolbarHeightPx(), mToolbarCoordinator.getToolbarHeightPx(), activity.getLifecycleDispatcher(),
activity.getLifecycleDispatcher(),
BottomSheetControllerProvider.from(activity.getWindowAndroid())); BottomSheetControllerProvider.from(activity.getWindowAndroid()));
activity.getWindow().getDecorView().addOnLayoutChangeListener(mediator); activity.getWindow().getDecorView().addOnLayoutChangeListener(mediator);
BottomSheetController bottomSheetController = BottomSheetController bottomSheetController =
BottomSheetControllerProvider.from(activity.getWindowAndroid()); BottomSheetControllerProvider.from(activity.getWindowAndroid());
bottomSheetController.addObserver(mediator); bottomSheetController.addObserver(mediator);
mWebContents.addObserver(mediator); mPaymentHandlerWebContents.addObserver(mediator);
mToolbarCoordinator.setCloseButtonOnClickCallback(mediator::onToolbarCloseButtonClicked); mToolbarCoordinator.setCloseButtonOnClickCallback(mediator::onToolbarCloseButtonClicked);
ThinWebView thinWebView = ThinWebViewFactory.create(activity, new ThinWebViewConstraints()); ThinWebView thinWebView = ThinWebViewFactory.create(activity, new ThinWebViewConstraints());
assert webContentView.getParent() == null; assert webContentView.getParent() == null;
thinWebView.attachWebContents(mWebContents, webContentView, null); thinWebView.attachWebContents(mPaymentHandlerWebContents, webContentView, null);
PaymentHandlerView view = new PaymentHandlerView( PaymentHandlerView view = new PaymentHandlerView(activity, mPaymentHandlerWebContents,
activity, mWebContents, mToolbarCoordinator.getView(), thinWebView.getView()); mToolbarCoordinator.getView(), thinWebView.getView());
assert mToolbarCoordinator.getToolbarHeightPx() == view.getToolbarHeightPx(); assert mToolbarCoordinator.getToolbarHeightPx() == view.getToolbarHeightPx();
PropertyModelChangeProcessor changeProcessor = PropertyModelChangeProcessor changeProcessor =
PropertyModelChangeProcessor.create(model, view, PaymentHandlerViewBinder::bind); PropertyModelChangeProcessor.create(model, view, PaymentHandlerViewBinder::bind);
...@@ -114,24 +107,27 @@ public class PaymentHandlerCoordinator { ...@@ -114,24 +107,27 @@ public class PaymentHandlerCoordinator {
activity.getWindow().getDecorView().removeOnLayoutChangeListener(mediator); activity.getWindow().getDecorView().removeOnLayoutChangeListener(mediator);
mediator.destroy(); mediator.destroy();
thinWebView.destroy(); thinWebView.destroy();
mWebContents.destroy(); mPaymentHandlerWebContents.destroy();
}; };
return bottomSheetController.requestShowContent(view, /*animate=*/true); boolean isShowSuccess = bottomSheetController.requestShowContent(view, /*animate=*/true);
return isShowSuccess ? mPaymentHandlerWebContents : null;
} }
private void initializeWebContents(ChromeActivity activity, ContentView webContentView, private void initializeWebContents(
PaymentHandlerWebContentsObserver webContentsObserver, GURL url) { ChromeActivity activity, ContentView webContentView, GURL url) {
mWebContents.initialize(ChromeVersionInfo.getProductVersion(), mPaymentHandlerWebContents.initialize(ChromeVersionInfo.getProductVersion(),
ViewAndroidDelegate.createBasicDelegate(webContentView), webContentView, ViewAndroidDelegate.createBasicDelegate(webContentView), webContentView,
activity.getWindowAndroid(), WebContents.createDefaultInternalsHolder()); activity.getWindowAndroid(), WebContents.createDefaultInternalsHolder());
SelectionPopupController controller = SelectionPopupController controller =
SelectionPopupController.fromWebContents(mWebContents); SelectionPopupController.fromWebContents(mPaymentHandlerWebContents);
controller.setActionModeCallback(new PaymentHandlerActionModeCallback(mWebContents)); controller.setActionModeCallback(
controller.setSelectionClient(SelectionClient.createSmartSelectionClient(mWebContents)); new PaymentHandlerActionModeCallback(mPaymentHandlerWebContents));
controller.setSelectionClient(
webContentsObserver.onWebContentsInitialized(mWebContents); SelectionClient.createSmartSelectionClient(mPaymentHandlerWebContents));
mWebContents.getNavigationController().loadUrl(new LoadUrlParams(url.getSpec()));
mPaymentHandlerWebContents.getNavigationController().loadUrl(
new LoadUrlParams(url.getSpec()));
} }
/** /**
...@@ -142,7 +138,7 @@ public class PaymentHandlerCoordinator { ...@@ -142,7 +138,7 @@ public class PaymentHandlerCoordinator {
*/ */
@VisibleForTesting @VisibleForTesting
public WebContents getWebContentsForTest() { public WebContents getWebContentsForTest() {
return mWebContents; return mPaymentHandlerWebContents;
} }
/** Hides the payment-handler UI. */ /** Hides the payment-handler UI. */
......
...@@ -36,7 +36,6 @@ import org.chromium.chrome.browser.payments.SettingsAutofillAndPaymentsObserver; ...@@ -36,7 +36,6 @@ import org.chromium.chrome.browser.payments.SettingsAutofillAndPaymentsObserver;
import org.chromium.chrome.browser.payments.ShippingStrings; import org.chromium.chrome.browser.payments.ShippingStrings;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator; import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerUiObserver; import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerUiObserver;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerWebContentsObserver;
import org.chromium.chrome.browser.payments.minimal.MinimalUICoordinator; import org.chromium.chrome.browser.payments.minimal.MinimalUICoordinator;
import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.FocusChangedObserver; import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.FocusChangedObserver;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
...@@ -941,23 +940,23 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob ...@@ -941,23 +940,23 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob
/** /**
* Create and show the (BottomSheet) PaymentHandler UI. * Create and show the (BottomSheet) PaymentHandler UI.
* @param webContents The WebContents of the merchant page.
* @param url The URL of the payment app. * @param url The URL of the payment app.
* @param paymentHandlerWebContentsObserver An observer of the WebContents of the Payment
* Handler UI.
* @param isOffTheRecord Whether the merchant page is currently in an OffTheRecord tab. * @param isOffTheRecord Whether the merchant page is currently in an OffTheRecord tab.
* @return Whether the PaymentHandler UI is shown successfully. * @return The WebContents of the payment handler that's just opened when the opening is
* successful; null if failed.
*/ */
public boolean showPaymentHandlerUI(WebContents webContents, GURL url, @Nullable
PaymentHandlerWebContentsObserver paymentHandlerWebContentsObserver, public WebContents showPaymentHandlerUI(GURL url, boolean isOffTheRecord) {
boolean isOffTheRecord) { if (mPaymentHandlerUi != null) return null;
if (mPaymentHandlerUi != null) return false; ChromeActivity chromeActivity = ChromeActivity.fromWebContents(mWebContents);
ChromeActivity chromeActivity = ChromeActivity.fromWebContents(webContents); if (chromeActivity == null) return null;
if (chromeActivity == null) return false;
PaymentHandlerCoordinator paymentHandlerUi = new PaymentHandlerCoordinator();
mPaymentHandlerUi = new PaymentHandlerCoordinator(); WebContents paymentHandlerWebContents = paymentHandlerUi.show(
return mPaymentHandlerUi.show(chromeActivity, url, isOffTheRecord, /*paymentRequestWebContents=*/mWebContents, url, isOffTheRecord,
paymentHandlerWebContentsObserver, /*uiObserver=*/this); /*uiObserver=*/this);
if (paymentHandlerWebContents != null) mPaymentHandlerUi = paymentHandlerUi;
return paymentHandlerWebContents;
} }
@VisibleForTesting(otherwise = VisibleForTesting.NONE) @VisibleForTesting(otherwise = VisibleForTesting.NONE)
......
...@@ -38,7 +38,6 @@ import org.chromium.chrome.browser.app.ChromeActivity; ...@@ -38,7 +38,6 @@ import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator; import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerUiObserver; import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerUiObserver;
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerWebContentsObserver;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
...@@ -71,7 +70,6 @@ public class ExpandablePaymentHandlerTest { ...@@ -71,7 +70,6 @@ public class ExpandablePaymentHandlerTest {
private EmbeddedTestServer mServer; private EmbeddedTestServer mServer;
private boolean mUiShownCalled; private boolean mUiShownCalled;
private boolean mUiClosedCalled; private boolean mUiClosedCalled;
private boolean mWebContentsInitializedCallbackInvoked;
private UiDevice mDevice; private UiDevice mDevice;
private boolean mDefaultIsIncognito; private boolean mDefaultIsIncognito;
private ChromeActivity mDefaultActivity; private ChromeActivity mDefaultActivity;
...@@ -133,8 +131,8 @@ public class ExpandablePaymentHandlerTest { ...@@ -133,8 +131,8 @@ public class ExpandablePaymentHandlerTest {
PaymentHandlerCoordinator paymentHandler = new PaymentHandlerCoordinator(); PaymentHandlerCoordinator paymentHandler = new PaymentHandlerCoordinator();
mRule.runOnUiThread( mRule.runOnUiThread(
() ()
-> paymentHandler.show(mDefaultActivity, defaultPaymentAppUrl(), -> paymentHandler.show(mDefaultActivity.getCurrentWebContents(),
isIncognito, defaultWebContentObserver(), defaultUiObserver())); defaultPaymentAppUrl(), isIncognito, defaultUiObserver()));
return paymentHandler; return paymentHandler;
} }
...@@ -161,15 +159,6 @@ public class ExpandablePaymentHandlerTest { ...@@ -161,15 +159,6 @@ public class ExpandablePaymentHandlerTest {
"/components/test/data/payments/maxpay.com/payment_handler_window.html")); "/components/test/data/payments/maxpay.com/payment_handler_window.html"));
} }
private PaymentHandlerWebContentsObserver defaultWebContentObserver() {
return new PaymentHandlerWebContentsObserver() {
@Override
public void onWebContentsInitialized(WebContents webContents) {
mWebContentsInitializedCallbackInvoked = true;
}
};
}
private PaymentHandlerUiObserver defaultUiObserver() { private PaymentHandlerUiObserver defaultUiObserver() {
return new PaymentHandlerUiObserver() { return new PaymentHandlerUiObserver() {
@Override @Override
...@@ -247,8 +236,6 @@ public class ExpandablePaymentHandlerTest { ...@@ -247,8 +236,6 @@ public class ExpandablePaymentHandlerTest {
PaymentHandlerCoordinator paymentHandler = createPaymentHandlerAndShow(mDefaultIsIncognito); PaymentHandlerCoordinator paymentHandler = createPaymentHandlerAndShow(mDefaultIsIncognito);
waitForUiShown(); waitForUiShown();
Assert.assertTrue(mWebContentsInitializedCallbackInvoked);
mRule.runOnUiThread(() -> paymentHandler.hide()); mRule.runOnUiThread(() -> paymentHandler.hide());
waitForUiClosed(); waitForUiClosed();
} }
......
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