Commit 1983372d authored by Liquan (Max) Gu's avatar Liquan (Max) Gu Committed by Chromium LUCI CQ

[Modular] Breaks PaymentUiService's dependency on ChromeActivity

PaymentUiService used to depend on ChromeActivity. This is undesirable
because the Clank modularization efforts requires that "ChromeActivity
should fully build/initialize the app without feature code having to
reference ChromeActivity for dependencies". This CL breaks this
dependency.

This also unblocks CL https://crrev.com/c/2602382 because
PaymentRequestParamsBuilder no longer has to depend on ChromeActivity
after this change.

Bug: 1155788
Change-Id: Ib539f37ca5056565d3c385b56f0ada0f1a430533
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2615480Reviewed-by: default avatarLiquan (Max) Gu <maxlg@chromium.org>
Reviewed-by: default avatarNick Burris <nburris@chromium.org>
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841625}
parent 586bd5ee
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.payments; package org.chromium.chrome.browser.payments;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -11,9 +12,14 @@ import androidx.annotation.Nullable; ...@@ -11,9 +12,14 @@ import androidx.annotation.Nullable;
import androidx.collection.ArrayMap; import androidx.collection.ArrayMap;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.browser.ChromeTabbedActivity;
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.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.payments.ui.PaymentUiService; import org.chromium.chrome.browser.payments.ui.PaymentUiService;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.components.autofill.EditableOption; import org.chromium.components.autofill.EditableOption;
import org.chromium.components.payments.AbortReason; import org.chromium.components.payments.AbortReason;
import org.chromium.components.payments.AndroidPaymentApp; import org.chromium.components.payments.AndroidPaymentApp;
...@@ -123,15 +129,15 @@ public class ChromePaymentRequestService ...@@ -123,15 +129,15 @@ public class ChromePaymentRequestService
} }
/** /**
* Looks up the Chrome activity of the given web contents. This can be null. Should never be * Looks up the Android Activity of the given web contents. This can be null. Should never
* cached, because web contents can change activities, e.g., when user selects "Open in * be cached, because web contents can change activities, e.g., when user selects "Open in
* Chrome" menu item. * Chrome" menu item.
* *
* @param webContents The web contents for which to lookup the Chrome activity. * @param webContents The web contents for which to lookup the Android activity.
* @return Possibly null Chrome activity that should never be cached. * @return Possibly null Android activity that should never be cached.
*/ */
@Nullable @Nullable
default ChromeActivity getChromeActivity(WebContents webContents) { default Activity getActivity(WebContents webContents) {
return ChromeActivity.fromWebContents(webContents); return ChromeActivity.fromWebContents(webContents);
} }
...@@ -189,6 +195,50 @@ public class ChromePaymentRequestService ...@@ -189,6 +195,50 @@ public class ChromePaymentRequestService
WebContents webContents, PaymentRequestUpdateEventListener listener) { WebContents webContents, PaymentRequestUpdateEventListener listener) {
return new PaymentHandlerHost(webContents, listener); return new PaymentHandlerHost(webContents, listener);
} }
/**
* @param webContents Any WebContents.
* @return The TabModelSelector of the given WebContents.
*/
@Nullable
default TabModelSelector getTabModelSelector(WebContents webContents) {
ChromeActivity activity = ChromeActivity.fromWebContents(webContents);
return activity == null ? null : activity.getTabModelSelector();
}
/**
* @param webContents Any WebContents.
* @return The TabModel of the given WebContents.
*/
@Nullable
default TabModel getTabModel(WebContents webContents) {
ChromeActivity activity = ChromeActivity.fromWebContents(webContents);
return activity == null ? null : activity.getCurrentTabModel();
}
/**
* @param webContents Any WebContents.
* @return The OverviewModeBehavior of the given WebContents.
*/
@Nullable
default OverviewModeBehavior getOverviewModeBehavior(WebContents webContents) {
ChromeActivity activity = ChromeActivity.fromWebContents(webContents);
if (activity == null) return null;
if (!(activity instanceof ChromeTabbedActivity)) return null;
return ((ChromeTabbedActivity) activity).getOverviewModeBehaviorSupplier().get();
}
/**
* @param webContents Any WebContents.
* @return The ActivityLifecycleDispatcher of the ChromeActivity that contains the given
* WebContents.
*/
@Nullable
default ActivityLifecycleDispatcher getActivityLifecycleDispatcher(
WebContents webContents) {
ChromeActivity activity = ChromeActivity.fromWebContents(webContents);
return activity == null ? null : activity.getLifecycleDispatcher();
}
} }
/** /**
...@@ -317,10 +367,15 @@ public class ChromePaymentRequestService ...@@ -317,10 +367,15 @@ public class ChromePaymentRequestService
@Override @Override
public String showOrSkipAppSelector(boolean isShowWaitingForUpdatedDetails, PaymentItem total, public String showOrSkipAppSelector(boolean isShowWaitingForUpdatedDetails, PaymentItem total,
boolean shouldSkipAppSelector) { boolean shouldSkipAppSelector) {
ChromeActivity chromeActivity = mDelegate.getChromeActivity(mWebContents); Activity activity = mDelegate.getActivity(mWebContents);
if (chromeActivity == null) return ErrorStrings.ACTIVITY_NOT_FOUND; if (activity == null) return ErrorStrings.ACTIVITY_NOT_FOUND;
String error = mPaymentUiService.buildPaymentRequestUI(chromeActivity, TabModelSelector tabModelSelector = mDelegate.getTabModelSelector(mWebContents);
/*isWebContentsActive=*/mDelegate.isWebContentsActive(mRenderFrameHost)); if (tabModelSelector == null) return ErrorStrings.TAB_NOT_FOUND;
TabModel tabModel = mDelegate.getTabModel(mWebContents);
if (tabModel == null) return ErrorStrings.TAB_NOT_FOUND;
String error = mPaymentUiService.buildPaymentRequestUI(
/*isWebContentsActive=*/mDelegate.isWebContentsActive(mRenderFrameHost), activity,
tabModelSelector, tabModel, mDelegate.getOverviewModeBehavior(mWebContents));
if (error != null) return error; if (error != null) return error;
// Calculate skip ui and build ui only after all payment apps are ready and // Calculate skip ui and build ui only after all payment apps are ready and
// request.show() is called. // request.show() is called.
...@@ -770,4 +825,11 @@ public class ChromePaymentRequestService ...@@ -770,4 +825,11 @@ public class ChromePaymentRequestService
public Context getContext() { public Context getContext() {
return mDelegate.getContext(mRenderFrameHost); return mDelegate.getContext(mRenderFrameHost);
} }
// Implement PaymentUiService.Delegate:
@Override
@Nullable
public ActivityLifecycleDispatcher getActivityLifecycleDispatcher() {
return mDelegate.getActivityLifecycleDispatcher(mWebContents);
}
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.payments.ui; package org.chromium.chrome.browser.payments.ui;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -14,8 +15,6 @@ import androidx.annotation.VisibleForTesting; ...@@ -14,8 +15,6 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeTabbedActivity;
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.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
...@@ -23,6 +22,7 @@ import org.chromium.chrome.browser.autofill.PersonalDataManager.NormalizedAddres ...@@ -23,6 +22,7 @@ import org.chromium.chrome.browser.autofill.PersonalDataManager.NormalizedAddres
import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.payments.AddressEditor; import org.chromium.chrome.browser.payments.AddressEditor;
import org.chromium.chrome.browser.payments.AutofillAddress; import org.chromium.chrome.browser.payments.AutofillAddress;
import org.chromium.chrome.browser.payments.AutofillContact; import org.chromium.chrome.browser.payments.AutofillContact;
...@@ -221,6 +221,10 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs ...@@ -221,6 +221,10 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs
*/ */
@Nullable @Nullable
Context getContext(); Context getContext();
/** @return The ActivityLifecycleDispatcher of the current ChromeActivity. */
@Nullable
ActivityLifecycleDispatcher getActivityLifecycleDispatcher();
} }
/** /**
...@@ -1196,12 +1200,17 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs ...@@ -1196,12 +1200,17 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs
/** /**
* Build the PaymentRequest UI. * Build the PaymentRequest UI.
* @param activity The ChromeActivity for the payment request, cannot be null.
* @param isWebContentsActive Whether the merchant's WebContents is active. * @param isWebContentsActive Whether the merchant's WebContents is active.
* @param activity The activity of the current tab.
* @param tabModelSelector The tab model selector of the current tab.
* @param tabModel The tab model of the current tab.
* @param overviewModeBehavior The overview model behaviour of the current tab, can be null.
* @return The error message if built unsuccessfully; null otherwise. * @return The error message if built unsuccessfully; null otherwise.
*/ */
@Nullable @Nullable
public String buildPaymentRequestUI(ChromeActivity activity, boolean isWebContentsActive) { public String buildPaymentRequestUI(boolean isWebContentsActive, Activity activity,
TabModelSelector tabModelSelector, TabModel tabModel,
@Nullable OverviewModeBehavior overviewModeBehavior) {
// Payment methods section must be ready before building the rest of the UI. This is because // Payment methods section must be ready before building the rest of the UI. This is because
// shipping and contact sections (when requested by merchant) are populated depending on // shipping and contact sections (when requested by merchant) are populated depending on
// whether or not the selected payment app (if such exists) can provide the required // whether or not the selected payment app (if such exists) can provide the required
...@@ -1209,6 +1218,9 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs ...@@ -1209,6 +1218,9 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs
assert mPaymentMethodsSection != null; assert mPaymentMethodsSection != null;
assert activity != null; assert activity != null;
assert tabModelSelector != null;
assert tabModel != null;
assert overviewModeBehavior != null;
// Only the currently selected tab is allowed to show the payment UI. // Only the currently selected tab is allowed to show the payment UI.
if (!isWebContentsActive) return ErrorStrings.CANNOT_SHOW_IN_BACKGROUND_TAB; if (!isWebContentsActive) return ErrorStrings.CANNOT_SHOW_IN_BACKGROUND_TAB;
...@@ -1220,21 +1232,20 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs ...@@ -1220,21 +1232,20 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs
if (mObservedTabModelSelector != null) { if (mObservedTabModelSelector != null) {
mObservedTabModelSelector.removeObserver(mSelectorObserver); mObservedTabModelSelector.removeObserver(mSelectorObserver);
} }
mObservedTabModelSelector = activity.getTabModelSelector(); mObservedTabModelSelector = tabModelSelector;
mObservedTabModelSelector.addObserver(mSelectorObserver); mObservedTabModelSelector.addObserver(mSelectorObserver);
if (mObservedTabModel != null) { if (mObservedTabModel != null) {
mObservedTabModel.removeObserver(mTabModelObserver); mObservedTabModel.removeObserver(mTabModelObserver);
} }
mObservedTabModel = activity.getCurrentTabModel(); mObservedTabModel = tabModel;
mObservedTabModel.addObserver(mTabModelObserver); mObservedTabModel.addObserver(mTabModelObserver);
// Catch any time the user enters the overview mode and dismiss the payment UI. // Catch any time the user enters the overview mode and dismiss the payment UI.
if (activity instanceof ChromeTabbedActivity) { if (overviewModeBehavior != null) {
if (mOverviewModeBehavior != null) { if (mOverviewModeBehavior != null) {
mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver); mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver);
} }
mOverviewModeBehavior = mOverviewModeBehavior = overviewModeBehavior;
((ChromeTabbedActivity) activity).getOverviewModeBehaviorSupplier().get();
assert mOverviewModeBehavior != null; assert mOverviewModeBehavior != null;
if (mOverviewModeBehavior.overviewVisible()) return ErrorStrings.TAB_OVERVIEW_MODE; if (mOverviewModeBehavior.overviewVisible()) return ErrorStrings.TAB_OVERVIEW_MODE;
...@@ -1252,8 +1263,10 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs ...@@ -1252,8 +1263,10 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs
SecurityStateModel.getSecurityLevelForWebContents(mWebContents), SecurityStateModel.getSecurityLevelForWebContents(mWebContents),
new ShippingStrings(mParams.getPaymentOptions().shippingType), new ShippingStrings(mParams.getPaymentOptions().shippingType),
mPaymentUisShowStateReconciler, Profile.fromWebContents(mWebContents)); mPaymentUisShowStateReconciler, Profile.fromWebContents(mWebContents));
activity.getLifecycleDispatcher().register( ActivityLifecycleDispatcher dispatcher = mDelegate.getActivityLifecycleDispatcher();
mPaymentRequestUI); // registered as a PauseResumeWithNativeObserver if (dispatcher != null) {
dispatcher.register(mPaymentRequestUI); // registered as a PauseResumeWithNativeObserver
}
final FaviconHelper faviconHelper = new FaviconHelper(); final FaviconHelper faviconHelper = new FaviconHelper();
faviconHelper.getLocalFaviconImageForURL(Profile.fromWebContents(mWebContents), faviconHelper.getLocalFaviconImageForURL(Profile.fromWebContents(mWebContents),
...@@ -1685,9 +1698,9 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs ...@@ -1685,9 +1698,9 @@ public class PaymentUiService implements SettingsAutofillAndPaymentsObserver.Obs
if (mPaymentRequestUI != null) { if (mPaymentRequestUI != null) {
mPaymentRequestUI.close(); mPaymentRequestUI.close();
ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents); ActivityLifecycleDispatcher dispatcher = mDelegate.getActivityLifecycleDispatcher();
if (activity != null) { if (dispatcher != null) {
activity.getLifecycleDispatcher().unregister(mPaymentRequestUI); dispatcher.unregister(mPaymentRequestUI);
} }
mPaymentRequestUI = null; mPaymentRequestUI = null;
mPaymentUisShowStateReconciler.onPaymentRequestUiClosed(); mPaymentUisShowStateReconciler.onPaymentRequestUiClosed();
......
...@@ -24,7 +24,8 @@ public class MockPaymentUiServiceBuilder { ...@@ -24,7 +24,8 @@ public class MockPaymentUiServiceBuilder {
mPaymentUiService = Mockito.mock(PaymentUiService.class); mPaymentUiService = Mockito.mock(PaymentUiService.class);
Mockito.doReturn(null) Mockito.doReturn(null)
.when(mPaymentUiService) .when(mPaymentUiService)
.buildPaymentRequestUI(Mockito.any(), Mockito.anyBoolean()); .buildPaymentRequestUI(Mockito.anyBoolean(), Mockito.any(), Mockito.any(),
Mockito.any(), Mockito.any());
Mockito.doReturn(true).when(mPaymentUiService).hasAvailableApps(); Mockito.doReturn(true).when(mPaymentUiService).hasAvailableApps();
List<PaymentApp> apps = new ArrayList<>(); List<PaymentApp> apps = new ArrayList<>();
apps.add(app); apps.add(app);
...@@ -35,7 +36,8 @@ public class MockPaymentUiServiceBuilder { ...@@ -35,7 +36,8 @@ public class MockPaymentUiServiceBuilder {
/* package */ MockPaymentUiServiceBuilder setBuildPaymentRequestUIResult(String result) { /* package */ MockPaymentUiServiceBuilder setBuildPaymentRequestUIResult(String result) {
Mockito.doReturn(result) Mockito.doReturn(result)
.when(mPaymentUiService) .when(mPaymentUiService)
.buildPaymentRequestUI(Mockito.any(), Mockito.anyBoolean()); .buildPaymentRequestUI(Mockito.anyBoolean(), Mockito.any(), Mockito.any(),
Mockito.any(), Mockito.any());
return this; return this;
} }
......
...@@ -4,14 +4,19 @@ ...@@ -4,14 +4,19 @@
package org.chromium.chrome.browser.payments; package org.chromium.chrome.browser.payments;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.payments.ui.PaymentUiService; import org.chromium.chrome.browser.payments.ui.PaymentUiService;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.components.payments.BrowserPaymentRequest; import org.chromium.components.payments.BrowserPaymentRequest;
import org.chromium.components.payments.JourneyLogger; import org.chromium.components.payments.JourneyLogger;
import org.chromium.components.payments.MojoPaymentRequestGateKeeper; import org.chromium.components.payments.MojoPaymentRequestGateKeeper;
...@@ -48,7 +53,6 @@ public class PaymentRequestParamsBuilder implements ChromePaymentRequestService. ...@@ -48,7 +53,6 @@ public class PaymentRequestParamsBuilder implements ChromePaymentRequestService.
private final WebContents mWebContents; private final WebContents mWebContents;
private final JourneyLogger mJourneyLogger; private final JourneyLogger mJourneyLogger;
private final PaymentRequestSpec mSpec; private final PaymentRequestSpec mSpec;
private final ChromeActivity mActivity;
private final PaymentUiService mPaymentUiService; private final PaymentUiService mPaymentUiService;
private final boolean mGoogleBridgeEligible; private final boolean mGoogleBridgeEligible;
private final PaymentOptions mOptions; private final PaymentOptions mOptions;
...@@ -63,7 +67,6 @@ public class PaymentRequestParamsBuilder implements ChromePaymentRequestService. ...@@ -63,7 +67,6 @@ public class PaymentRequestParamsBuilder implements ChromePaymentRequestService.
mClient = client; mClient = client;
mDelegate = this; mDelegate = this;
mPaymentUiService = paymentUiService; mPaymentUiService = paymentUiService;
mActivity = Mockito.mock(ChromeActivity.class);
mJourneyLogger = Mockito.mock(JourneyLogger.class); mJourneyLogger = Mockito.mock(JourneyLogger.class);
mWebContents = Mockito.mock(WebContents.class); mWebContents = Mockito.mock(WebContents.class);
Mockito.doReturn("https://top.level.origin").when(mWebContents).getLastCommittedUrl(); Mockito.doReturn("https://top.level.origin").when(mWebContents).getLastCommittedUrl();
...@@ -184,8 +187,35 @@ public class PaymentRequestParamsBuilder implements ChromePaymentRequestService. ...@@ -184,8 +187,35 @@ public class PaymentRequestParamsBuilder implements ChromePaymentRequestService.
} }
@Override @Override
public ChromeActivity getChromeActivity(WebContents webContents) { public Activity getActivity(WebContents webContents) {
return mActivity; Activity activity = Mockito.mock(Activity.class);
Resources resources = Mockito.mock(Resources.class);
Mockito.doReturn(resources).when(activity).getResources();
return activity;
}
@Nullable
@Override
public TabModelSelector getTabModelSelector(WebContents webContents) {
return Mockito.mock(TabModelSelector.class);
}
@Nullable
@Override
public TabModel getTabModel(WebContents webContents) {
return Mockito.mock(TabModel.class);
}
@Nullable
@Override
public OverviewModeBehavior getOverviewModeBehavior(WebContents webContents) {
return Mockito.mock(OverviewModeBehavior.class);
}
@Nullable
@Override
public ActivityLifecycleDispatcher getActivityLifecycleDispatcher(WebContents webContents) {
return Mockito.mock(ActivityLifecycleDispatcher.class);
} }
@Override @Override
......
...@@ -30,6 +30,8 @@ public abstract class ErrorStrings {{ ...@@ -30,6 +30,8 @@ public abstract class ErrorStrings {{
public static final String CONTEXT_NOT_FOUND = "Unable to find Chrome context."; public static final String CONTEXT_NOT_FOUND = "Unable to find Chrome context.";
public static final String TAB_NOT_FOUND = "Unable to find Chrome tab.";
public static final String WINDOW_NOT_FOUND = "Unable to find Chrome window."; public static final String WINDOW_NOT_FOUND = "Unable to find Chrome window.";
public static final String PAYMENT_APP_INVALID_RESPONSE = "Payment app response is not valid."; public static final String PAYMENT_APP_INVALID_RESPONSE = "Payment app response is not valid.";
......
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