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

[PRImpl] Move PRImpl#buildUI UI logic into PaymentUIsManager

Change:
* Move the UI logic of PaymentRequestImpl#buildUI() into
PaymentUIsManager#buildPaymentRequestUI()
* Change buildPaymentRequestUI()'s structure to return an error
message. This way, PRImpl#buildUI()'s size can be reduced.
* PRImpl no longer depends on:
 - org.chromium.chrome.browser.tab
 - org.chromium.chrome.browser.tabmodel
 - org.chromium.chrome.browser.compositor.layouts
 - org.chromium.chrome.browser.ChromeTabbedActivity

Bug: 1102522

Change-Id: I5f61a57b7891ec06a59527852d1a37f14bda031a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2384315
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805524}
parent c97a51a3
...@@ -18,14 +18,10 @@ import org.chromium.base.LocaleUtils; ...@@ -18,14 +18,10 @@ import org.chromium.base.LocaleUtils;
import org.chromium.base.Log; import org.chromium.base.Log;
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.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.NormalizedAddressRequestDelegate; import org.chromium.chrome.browser.autofill.PersonalDataManager.NormalizedAddressRequestDelegate;
import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
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.handler.PaymentHandlerCoordinator.PaymentHandlerWebContentsObserver;
import org.chromium.chrome.browser.payments.minimal.MinimalUICoordinator; import org.chromium.chrome.browser.payments.minimal.MinimalUICoordinator;
...@@ -38,13 +34,6 @@ import org.chromium.chrome.browser.payments.ui.SectionInformation; ...@@ -38,13 +34,6 @@ import org.chromium.chrome.browser.payments.ui.SectionInformation;
import org.chromium.chrome.browser.payments.ui.ShoppingCart; import org.chromium.chrome.browser.payments.ui.ShoppingCart;
import org.chromium.chrome.browser.settings.SettingsLauncher; import org.chromium.chrome.browser.settings.SettingsLauncher;
import org.chromium.chrome.browser.settings.SettingsLauncherImpl; import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabSelectionType;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
import org.chromium.components.autofill.EditableOption; import org.chromium.components.autofill.EditableOption;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.embedder_support.util.UrlConstants;
...@@ -167,35 +156,6 @@ public class PaymentRequestImpl ...@@ -167,35 +156,6 @@ public class PaymentRequestImpl
@Nullable @Nullable
private ComponentPaymentRequestImpl mComponentPaymentRequestImpl; private ComponentPaymentRequestImpl mComponentPaymentRequestImpl;
/** Monitors changes in the TabModelSelector. */
private final TabModelSelectorObserver mSelectorObserver = new EmptyTabModelSelectorObserver() {
@Override
public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER);
disconnectFromClientWithDebugMessage(ErrorStrings.TAB_SWITCH);
}
};
/** Monitors changes in the current TabModel. */
private final TabModelObserver mTabModelObserver = new TabModelObserver() {
@Override
public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
if (tab == null || tab.getId() != lastId) {
mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER);
disconnectFromClientWithDebugMessage(ErrorStrings.TAB_SWITCH);
}
}
};
/** Monitors changes in the tab overview. */
private final OverviewModeObserver mOverviewModeObserver = new EmptyOverviewModeObserver() {
@Override
public void onOverviewModeStartedShowing(boolean showToolbar) {
mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER);
disconnectFromClientWithDebugMessage(ErrorStrings.TAB_OVERVIEW_MODE);
}
};
private final Handler mHandler = new Handler(); private final Handler mHandler = new Handler();
private final RenderFrameHost mRenderFrameHost; private final RenderFrameHost mRenderFrameHost;
private final Delegate mDelegate; private final Delegate mDelegate;
...@@ -232,9 +192,6 @@ public class PaymentRequestImpl ...@@ -232,9 +192,6 @@ public class PaymentRequestImpl
private PaymentApp mInvokedPaymentApp; private PaymentApp mInvokedPaymentApp;
private boolean mHideServerAutofillCards; private boolean mHideServerAutofillCards;
private boolean mWaitForUpdatedDetails; private boolean mWaitForUpdatedDetails;
private TabModelSelector mObservedTabModelSelector;
private TabModel mObservedTabModel;
private OverviewModeBehavior mOverviewModeBehavior;
private PaymentHandlerHost mPaymentHandlerHost; private PaymentHandlerHost mPaymentHandlerHost;
/** /**
...@@ -448,62 +405,18 @@ public class PaymentRequestImpl ...@@ -448,62 +405,18 @@ public class PaymentRequestImpl
/** @return Whether the UI was built. */ /** @return Whether the UI was built. */
private boolean buildUI(ChromeActivity activity) { private boolean buildUI(ChromeActivity activity) {
// Payment methods section must be ready before building the rest of the UI. This is because String error = mPaymentUIsManager.buildPaymentRequestUI(activity,
// shipping and contact sections (when requested by merchant) are populated depending on /*isWebContentsActive=*/mDelegate.isWebContentsActive(activity),
// whether or not the selected payment app (if such exists) can provide the required /*waitForUpdatedDetails=*/mWaitForUpdatedDetails);
// information. if (error != null) {
assert mPaymentUIsManager.getPaymentMethodsSection() != null;
assert activity != null;
// Catch any time the user switches tabs. Because the dialog is modal, a user shouldn't be
// allowed to switch tabs, which can happen if the user receives an external Intent.
mObservedTabModelSelector = activity.getTabModelSelector();
mObservedTabModel = activity.getCurrentTabModel();
mObservedTabModelSelector.addObserver(mSelectorObserver);
mObservedTabModel.addObserver(mTabModelObserver);
// Only the currently selected tab is allowed to show the payment UI.
if (!mDelegate.isWebContentsActive(activity)) {
mJourneyLogger.setNotShown(NotShownReason.OTHER); mJourneyLogger.setNotShown(NotShownReason.OTHER);
disconnectFromClientWithDebugMessage(ErrorStrings.CANNOT_SHOW_IN_BACKGROUND_TAB); disconnectFromClientWithDebugMessage(error);
if (ComponentPaymentRequestImpl.getObserverForTest() != null) { if (ComponentPaymentRequestImpl.getObserverForTest() != null) {
ComponentPaymentRequestImpl.getObserverForTest() ComponentPaymentRequestImpl.getObserverForTest()
.onPaymentRequestServiceShowFailed(); .onPaymentRequestServiceShowFailed();
} }
return false; return false;
} }
// Catch any time the user enters the overview mode and dismiss the payment UI.
if (activity instanceof ChromeTabbedActivity) {
mOverviewModeBehavior =
((ChromeTabbedActivity) activity).getOverviewModeBehaviorSupplier().get();
assert mOverviewModeBehavior != null;
if (mOverviewModeBehavior.overviewVisible()) {
mJourneyLogger.setNotShown(NotShownReason.OTHER);
disconnectFromClientWithDebugMessage(ErrorStrings.TAB_OVERVIEW_MODE);
if (ComponentPaymentRequestImpl.getObserverForTest() != null) {
ComponentPaymentRequestImpl.getObserverForTest()
.onPaymentRequestServiceShowFailed();
}
return false;
}
mOverviewModeBehavior.addOverviewModeObserver(mOverviewModeObserver);
}
if (shouldShowShippingSection() && !mWaitForUpdatedDetails) {
mPaymentUIsManager.createShippingSectionForPaymentRequestUI(activity);
}
if (shouldShowContactSection()) {
mPaymentUIsManager.setContactSection(
new ContactDetailsSection(activity, mPaymentUIsManager.getAutofillProfiles(),
mPaymentUIsManager.getContactEditor(), mJourneyLogger));
}
mPaymentUIsManager.buildPaymentRequestUI(activity);
return true; return true;
} }
...@@ -2113,20 +2026,7 @@ public class PaymentRequestImpl ...@@ -2113,20 +2026,7 @@ public class PaymentRequestImpl
mPaymentUIsManager.setPaymentMethodsSection(null); mPaymentUIsManager.setPaymentMethodsSection(null);
} }
if (mObservedTabModelSelector != null) { mPaymentUIsManager.removeLeavingTabObservers();
mObservedTabModelSelector.removeObserver(mSelectorObserver);
mObservedTabModelSelector = null;
}
if (mObservedTabModel != null) {
mObservedTabModel.removeObserver(mTabModelObserver);
mObservedTabModel = null;
}
if (mOverviewModeBehavior != null) {
mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver);
mOverviewModeBehavior = null;
}
SettingsAutofillAndPaymentsObserver.getInstance().unregisterObserver(mPaymentUIsManager); SettingsAutofillAndPaymentsObserver.getInstance().unregisterObserver(mPaymentUIsManager);
...@@ -2193,4 +2093,12 @@ public class PaymentRequestImpl ...@@ -2193,4 +2093,12 @@ public class PaymentRequestImpl
if (mComponentPaymentRequestImpl == null) return; if (mComponentPaymentRequestImpl == null) return;
mComponentPaymentRequestImpl.warnNoFavicon(); mComponentPaymentRequestImpl.warnNoFavicon();
} }
// Implement PaymentUIsObserver.onLeavingCurrentTab:
@Override
public void onLeavingCurrentTab(String reason) {
if (mComponentPaymentRequestImpl == null) return;
mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER);
disconnectFromClientWithDebugMessage(reason);
}
} }
...@@ -14,10 +14,14 @@ import androidx.annotation.VisibleForTesting; ...@@ -14,10 +14,14 @@ 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.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;
import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
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;
...@@ -35,10 +39,19 @@ import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.Pa ...@@ -35,10 +39,19 @@ import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.Pa
import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerWebContentsObserver; import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerWebContentsObserver;
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;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabSelectionType;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
import org.chromium.chrome.browser.ui.favicon.FaviconHelper; import org.chromium.chrome.browser.ui.favicon.FaviconHelper;
import org.chromium.components.autofill.Completable; import org.chromium.components.autofill.Completable;
import org.chromium.components.autofill.EditableOption; import org.chromium.components.autofill.EditableOption;
import org.chromium.components.payments.BrowserPaymentRequest;
import org.chromium.components.payments.CurrencyFormatter; import org.chromium.components.payments.CurrencyFormatter;
import org.chromium.components.payments.ErrorStrings;
import org.chromium.components.payments.JourneyLogger; import org.chromium.components.payments.JourneyLogger;
import org.chromium.components.payments.PaymentApp; import org.chromium.components.payments.PaymentApp;
import org.chromium.components.payments.PaymentAppType; import org.chromium.components.payments.PaymentAppType;
...@@ -94,6 +107,9 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob ...@@ -94,6 +107,9 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob
private final boolean mIsOffTheRecord; private final boolean mIsOffTheRecord;
private final Handler mHandler = new Handler(); private final Handler mHandler = new Handler();
private final Queue<Runnable> mRetryQueue = new LinkedList<>(); private final Queue<Runnable> mRetryQueue = new LinkedList<>();
private final OverviewModeObserver mOverviewModeObserver;
private final TabModelSelectorObserver mSelectorObserver;
private final TabModelObserver mTabModelObserver;
private ContactEditor mContactEditor; private ContactEditor mContactEditor;
private PaymentHandlerCoordinator mPaymentHandlerUi; private PaymentHandlerCoordinator mPaymentHandlerUi;
private Callback<PaymentInformation> mPaymentInformationCallback; private Callback<PaymentInformation> mPaymentInformationCallback;
...@@ -122,6 +138,9 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob ...@@ -122,6 +138,9 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob
private boolean mCanUserAddCreditCard; private boolean mCanUserAddCreditCard;
private final JourneyLogger mJourneyLogger; private final JourneyLogger mJourneyLogger;
private PaymentUIsObserver mObserver; private PaymentUIsObserver mObserver;
private TabModelSelector mObservedTabModelSelector;
private TabModel mObservedTabModel;
private OverviewModeBehavior mOverviewModeBehavior;
/** /**
* True if we should skip showing PaymentRequest UI. * True if we should skip showing PaymentRequest UI.
...@@ -231,6 +250,26 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob ...@@ -231,6 +250,26 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob
mIsOffTheRecord = isOffTheRecord; mIsOffTheRecord = isOffTheRecord;
mPaymentAppComparator = new PaymentAppComparator(/*params=*/mParams); mPaymentAppComparator = new PaymentAppComparator(/*params=*/mParams);
mObserver = observer; mObserver = observer;
mSelectorObserver = new EmptyTabModelSelectorObserver() {
@Override
public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
mObserver.onLeavingCurrentTab(ErrorStrings.TAB_SWITCH);
}
};
mTabModelObserver = new TabModelObserver() {
@Override
public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
if (tab == null || tab.getId() != lastId) {
mObserver.onLeavingCurrentTab(ErrorStrings.TAB_SWITCH);
}
}
};
mOverviewModeObserver = new EmptyOverviewModeObserver() {
@Override
public void onOverviewModeStartedShowing(boolean showToolbar) {
mObserver.onLeavingCurrentTab(ErrorStrings.TAB_OVERVIEW_MODE);
}
};
} }
/** @return The PaymentRequestUI. */ /** @return The PaymentRequestUI. */
...@@ -947,10 +986,61 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob ...@@ -947,10 +986,61 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob
/** /**
* Build the PaymentRequest UI. * Build the PaymentRequest UI.
* @param activity The ChromeActivity for the payment request. * @param activity The ChromeActivity for the payment request, cannot be null.
* @param isWebContentsActive Whether the merchant's WebContents is active.
* @param waitForUpdatedDetails Whether to wait for updated details. See {@link
* BrowserPaymentRequest#show}'s waitForUpdatedDetails.
* @return The error message if built unsuccessfully; null otherwise.
*/ */
public void buildPaymentRequestUI(ChromeActivity activity) { @Nullable
assert mIsPaymentRequestParamsInitiated; public String buildPaymentRequestUI(
ChromeActivity activity, boolean isWebContentsActive, boolean waitForUpdatedDetails) {
// 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
// whether or not the selected payment app (if such exists) can provide the required
// information.
assert mPaymentMethodsSection != null;
assert activity != null;
// Only the currently selected tab is allowed to show the payment UI.
if (!isWebContentsActive) return ErrorStrings.CANNOT_SHOW_IN_BACKGROUND_TAB;
// Catch any time the user switches tabs. Because the dialog is modal, a user shouldn't be
// allowed to switch tabs, which can happen if the user receives an external Intent.
if (mObservedTabModelSelector != null) {
mObservedTabModelSelector.removeObserver(mSelectorObserver);
}
mObservedTabModelSelector = activity.getTabModelSelector();
mObservedTabModelSelector.addObserver(mSelectorObserver);
if (mObservedTabModel != null) {
mObservedTabModel.removeObserver(mTabModelObserver);
}
mObservedTabModel = activity.getCurrentTabModel();
mObservedTabModel.addObserver(mTabModelObserver);
// Catch any time the user enters the overview mode and dismiss the payment UI.
if (activity instanceof ChromeTabbedActivity) {
if (mOverviewModeBehavior != null) {
mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver);
}
mOverviewModeBehavior =
((ChromeTabbedActivity) activity).getOverviewModeBehaviorSupplier().get();
assert mOverviewModeBehavior != null;
if (mOverviewModeBehavior.overviewVisible()) return ErrorStrings.TAB_OVERVIEW_MODE;
mOverviewModeBehavior.addOverviewModeObserver(mOverviewModeObserver);
}
if (shouldShowShippingSection() && !waitForUpdatedDetails) {
createShippingSectionForPaymentRequestUI(activity);
}
if (shouldShowContactSection()) {
mContactSection = new ContactDetailsSection(
activity, mAutofillProfiles, mContactEditor, mJourneyLogger);
}
mPaymentRequestUI = new PaymentRequestUI(activity, mDelegate.getPaymentRequestUIClient(), mPaymentRequestUI = new PaymentRequestUI(activity, mDelegate.getPaymentRequestUIClient(),
mMerchantSupportsAutofillCards, !PaymentPreferencesUtil.isPaymentCompleteOnce(), mMerchantSupportsAutofillCards, !PaymentPreferencesUtil.isPaymentCompleteOnce(),
mMerchantName, mTopLevelOriginFormattedForDisplay, mMerchantName, mTopLevelOriginFormattedForDisplay,
...@@ -985,6 +1075,7 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob ...@@ -985,6 +1075,7 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob
if (mContactEditor != null) { if (mContactEditor != null) {
mContactEditor.setEditorDialog(mPaymentRequestUI.getEditorDialog()); mContactEditor.setEditorDialog(mPaymentRequestUI.getEditorDialog());
} }
return null;
} }
/** Create a shipping section for PaymentRequest UI. */ /** Create a shipping section for PaymentRequest UI. */
...@@ -1291,4 +1382,22 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob ...@@ -1291,4 +1382,22 @@ public class PaymentUIsManager implements SettingsAutofillAndPaymentsObserver.Ob
// skip-UI. // skip-UI.
&& (isUserGestureShow || !selectedApp.isUserGestureRequiredToSkipUi()); && (isUserGestureShow || !selectedApp.isUserGestureRequiredToSkipUi());
} }
/** Removes all of the observers that observe users leaving the tab. */
public void removeLeavingTabObservers() {
if (mObservedTabModelSelector != null) {
mObservedTabModelSelector.removeObserver(mSelectorObserver);
mObservedTabModelSelector = null;
}
if (mObservedTabModel != null) {
mObservedTabModel.removeObserver(mTabModelObserver);
mObservedTabModel = null;
}
if (mOverviewModeBehavior != null) {
mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver);
mOverviewModeBehavior = null;
}
}
} }
...@@ -8,4 +8,12 @@ package org.chromium.components.payments; ...@@ -8,4 +8,12 @@ package org.chromium.components.payments;
public interface PaymentUIsObserver { public interface PaymentUIsObserver {
/** Called when favicon not available for payment request UI. */ /** Called when favicon not available for payment request UI. */
void onPaymentRequestUIFaviconNotAvailable(); void onPaymentRequestUIFaviconNotAvailable();
/**
* Called when the user is leaving the current tab (e.g., tab switched or tab overview mode is
* shown), upon which the PaymentRequest service should be closed.
* @param reason The reason of leaving the current tab, to be used as debug message for the
* developers.
*/
void onLeavingCurrentTab(String reason);
} }
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