chromium/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerView.java

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.payments.handler;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;

import androidx.annotation.Nullable;

import org.chromium.base.supplier.ObservableSupplierImpl;
import org.chromium.chrome.R;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
import org.chromium.components.payments.InputProtector;
import org.chromium.content_public.browser.RenderCoordinates;
import org.chromium.content_public.browser.WebContents;

/**
 * The view of the PaymentHandler UI. This view can be divided into the toolbar area and the
 * content area. The content area does not include the toolbar area; it includes the BottomSheet
 * area below the toolbar, which includes the part that extends beneath the screen. The ThinWebView
 * has a fixed height, which is the height of visible content area when the sheet is in full state.
 */
/* package */ class PaymentHandlerView implements BottomSheetContent {
    private final View mToolbarView;
    private final PaymentHandlerContentFrameLayout mContentView;
    private final View mThinWebView;
    private final WebContents mWebContents;
    private final int mToolbarHeightPx;
    private final ObservableSupplierImpl<Boolean> mBackPressStateChangedSupplier =
            new ObservableSupplierImpl<>();
    private Runnable mBackPressCallback;

    /**
     * Construct the PaymentHandlerView.
     *
     * @param context The {@link Context} of the Application.
     * @param webContents The web-content of the payment-handler web-app.
     * @param toolbarView The view of the Payment Handler toolbar.
     * @param thinWebView The view that shows the WebContents of the payment app.
     */
    /* package */ PaymentHandlerView(
            Context context,
            WebContents webContents,
            View toolbarView,
            View thinWebView,
            InputProtector inputProtector) {
        mWebContents = webContents;
        mToolbarView = toolbarView;
        mThinWebView = thinWebView;
        mToolbarHeightPx =
                context.getResources().getDimensionPixelSize(R.dimen.sheet_tab_toolbar_height);
        mContentView =
                (PaymentHandlerContentFrameLayout)
                        LayoutInflater.from(context)
                                .inflate(R.layout.payment_handler_content, null);
        mContentView.setInputProtector(inputProtector);
        mContentView.setPadding(
                /* left= */ 0, /* top= */ mToolbarHeightPx, /* right= */ 0, /* bottom= */ 0);
        mContentView.addView(thinWebView, /* index= */ 0);
        mBackPressStateChangedSupplier.set(true);
    }

    /**
     * Set the callback to be invoked when the system back button is pressed.
     * @param callback the callback to be invoked
     */
    /* package */ void setBackPressCallback(Runnable callback) {
        mBackPressCallback = callback;
    }

    /**
     * Invoked when the visible area of the content container changes.
     * @param heightPx The height of the visible area of the Payment Handler UI content container,
     *         in pixels.
     */
    /* package */ void onContentVisibleHeightChanged(int heightPx) {
        LayoutParams params = (LayoutParams) mThinWebView.getLayoutParams();
        params.height = Math.max(0, heightPx);
        mThinWebView.setLayoutParams(params);
    }

    /* package */ int getToolbarHeightPx() {
        return mToolbarHeightPx;
    }

    // BottomSheetContent:
    @Override
    public View getContentView() {
        return mContentView;
    }

    @Override
    public @Nullable View getToolbarView() {
        return mToolbarView;
    }

    @Override
    public float getFullHeightRatio() {
        return PaymentHandlerMediator.FULL_HEIGHT_RATIO;
    }

    @Override
    public float getHalfHeightRatio() {
        return PaymentHandlerMediator.HALF_HEIGHT_RATIO;
    }

    @Override
    public boolean hasCustomScrimLifecycle() {
        return true;
    }

    @Override
    public int getVerticalScrollOffset() {
        return mWebContents == null
                ? 0
                : RenderCoordinates.fromWebContents(mWebContents).getScrollYPixInt();
    }

    @Override
    public void destroy() {}

    @Override
    public @ContentPriority int getPriority() {
        // If multiple bottom sheets are queued up to be shown, prioritize payment-handler, because
        // it's triggered by a user gesture, such as a click on <button>Buy this article</button>.
        return BottomSheetContent.ContentPriority.HIGH;
    }

    @Override
    public int getPeekHeight() {
        return BottomSheetContent.HeightMode.DISABLED;
    }

    @Override
    public boolean handleBackPress() {
        mBackPressCallback.run();
        return true; // Prevent further handling of the back press.
    }

    @Override
    public ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
        return mBackPressStateChangedSupplier;
    }

    @Override
    public void onBackPressed() {
        mBackPressCallback.run();
    }

    @Override
    public int getSheetContentDescriptionStringId() {
        return R.string.payment_handler_sheet_description;
    }

    @Override
    public int getSheetHalfHeightAccessibilityStringId() {
        return R.string.payment_handler_sheet_opened_half;
    }

    @Override
    public int getSheetFullHeightAccessibilityStringId() {
        return R.string.payment_handler_sheet_opened_full;
    }

    @Override
    public int getSheetClosedAccessibilityStringId() {
        return R.string.payment_handler_sheet_closed;
    }

    @Override
    public boolean swipeToDismissEnabled() {
        // flinging down hard enough will close the sheet.
        return true;
    }
}