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

[PaymentHandler] Add toolbar

This patch adds a toolbar to the Bottom-sheet based Payment handler.
The features of the toolbar includes:
* origin: shows the origin of the payment app url (with the scheme)
* title: shows the payment app title
* progress bar: shows the load progress of the payment app
* security icon: show 3 different icons based on the security level.

Because of its resemblance with the ephemeral tab toolbar, we reuse
the ephemeral tab toolbar's layout but implement it with different
controlling logic.

Note that the above features support redirect. Whenever the payment
app page redirect, these features would get updated to match the
current page.

The progress bar updates the load progress whenever receiving
web-contents' progress-updating callback. It get hidden once the
progress reaches 100%; it shows up again once the progress turns below
100%.

Bug: 999196

Change-Id: Ifaf9e971256ff82888176623b3a4b51749246a73
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1901639Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714484}
parent 2388aa16
...@@ -1221,6 +1221,11 @@ chrome_java_sources = [ ...@@ -1221,6 +1221,11 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerProperties.java", "java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerProperties.java",
"java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerViewBinder.java", "java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerViewBinder.java",
"java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerView.java", "java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerView.java",
"java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarCoordinator.java",
"java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarMediator.java",
"java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarProperties.java",
"java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarViewBinder.java",
"java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarView.java",
"java/src/org/chromium/chrome/browser/payments/JourneyLogger.java", "java/src/org/chromium/chrome/browser/payments/JourneyLogger.java",
"java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java", "java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java",
"java/src/org/chromium/chrome/browser/payments/PaymentApp.java", "java/src/org/chromium/chrome/browser/payments/PaymentApp.java",
......
...@@ -23,16 +23,16 @@ ...@@ -23,16 +23,16 @@
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="62dp" android:layout_height="62dp"
android:paddingStart="8dp"
android:orientation="horizontal"> android:orientation="horizontal">
<org.chromium.ui.widget.ChromeImageView <org.chromium.ui.widget.ChromeImageView
android:id="@+id/favicon" android:id="@+id/favicon"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:padding="12dp" android:padding="12dp"
android:layout_alignParentStart="true"
android:scaleType="fitCenter" android:scaleType="fitCenter"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:layout_marginStart="8dp"
android:layout_toStartOf="@id/open_in_new_tab" android:layout_toStartOf="@id/open_in_new_tab"
android:layout_toEndOf="@id/favicon" android:layout_toEndOf="@id/favicon"
android:textAlignment="viewStart" android:textAlignment="viewStart"
...@@ -73,6 +74,7 @@ ...@@ -73,6 +74,7 @@
android:id="@+id/security_icon" android:id="@+id/security_icon"
android:layout_width="16dp" android:layout_width="16dp"
android:layout_height="16dp" android:layout_height="16dp"
android:layout_marginStart="8dp"
android:layout_below="@id/ephemeral_tab_text" android:layout_below="@id/ephemeral_tab_text"
android:layout_toEndOf="@id/favicon" android:layout_toEndOf="@id/favicon"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
......
...@@ -4,11 +4,7 @@ ...@@ -4,11 +4,7 @@
found in the LICENSE file. --> found in the LICENSE file. -->
<FrameLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/sheet_bg_color"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<org.chromium.chrome.browser.ui.widget.FadingShadowView
android:id="@+id/shadow"
android:layout_width="match_parent"
android:layout_height="@dimen/action_bar_shadow_height"/>
</FrameLayout> </FrameLayout>
...@@ -8,6 +8,7 @@ import org.chromium.chrome.browser.ChromeActivity; ...@@ -8,6 +8,7 @@ import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.ChromeVersionInfo;
import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.WebContentsFactory;
import org.chromium.chrome.browser.payments.handler.toolbar.PaymentHandlerToolbarCoordinator;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
import org.chromium.components.embedder_support.view.ContentView; import org.chromium.components.embedder_support.view.ContentView;
import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.LoadUrlParams;
...@@ -59,7 +60,11 @@ public class PaymentHandlerCoordinator { ...@@ -59,7 +60,11 @@ public class PaymentHandlerCoordinator {
bottomSheetController.addObserver(mediator); bottomSheetController.addObserver(mediator);
webContents.addObserver(mediator); webContents.addObserver(mediator);
PaymentHandlerView view = new PaymentHandlerView(activity, webContents, webContentView); PaymentHandlerToolbarCoordinator toolbarCoordinator = new PaymentHandlerToolbarCoordinator(
activity, webContents, () -> { mHider.run(); });
PaymentHandlerView view = new PaymentHandlerView(
activity, webContents, webContentView, toolbarCoordinator.getView());
assert toolbarCoordinator.getToolbarHeightPx() == view.getToolbarHeightPx();
PropertyModelChangeProcessor changeProcessor = PropertyModelChangeProcessor changeProcessor =
PropertyModelChangeProcessor.create(model, view, PaymentHandlerViewBinder::bind); PropertyModelChangeProcessor.create(model, view, PaymentHandlerViewBinder::bind);
mHider = () -> { mHider = () -> {
......
...@@ -23,6 +23,8 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -23,6 +23,8 @@ import org.chromium.ui.modelutil.PropertyModel;
extends WebContentsObserver implements BottomSheetObserver { extends WebContentsObserver implements BottomSheetObserver {
private final PropertyModel mModel; private final PropertyModel mModel;
private final Runnable mHider; private final Runnable mHider;
/** Postfixed with "Ref" to distinguish from mWebContent in WebContentsObserver. */
private final WebContents mWebContentsRef;
/** /**
* Build a new mediator that handle events from outside the payment handler component. * Build a new mediator that handle events from outside the payment handler component.
...@@ -35,28 +37,17 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -35,28 +37,17 @@ import org.chromium.ui.modelutil.PropertyModel;
/* package */ PaymentHandlerMediator( /* package */ PaymentHandlerMediator(
PropertyModel model, Runnable hider, WebContents webContents) { PropertyModel model, Runnable hider, WebContents webContents) {
super(webContents); super(webContents);
mWebContentsRef = webContents;
mModel = model; mModel = model;
mHider = hider; mHider = hider;
} }
/**
* Hide the bottom-sheet if weak-ref of web-contents refers to null.
* @return Return true if the sheet is hidden.
*/
private boolean hideSheetIfWebContentsNotExist() {
if (mWebContents != null) return false;
// TODO(maxlg): how to inform the service worker when the web-contents is missing.
mHider.run();
return true;
}
// BottomSheetObserver: // BottomSheetObserver:
@Override @Override
public void onSheetStateChanged(@SheetState int newState) { public void onSheetStateChanged(@SheetState int newState) {
if (hideSheetIfWebContentsNotExist()) return;
switch (newState) { switch (newState) {
case BottomSheetController.SheetState.HIDDEN: case BottomSheetController.SheetState.HIDDEN:
ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContents.get()); ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContentsRef);
mHider.run(); mHider.run();
break; break;
} }
...@@ -88,28 +79,25 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -88,28 +79,25 @@ import org.chromium.ui.modelutil.PropertyModel;
// WebContentsObserver: // WebContentsObserver:
@Override @Override
public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) { public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
if (hideSheetIfWebContentsNotExist()) return; if (!SslValidityChecker.isValidPageInPaymentHandlerWindow(mWebContentsRef)) {
if (!SslValidityChecker.isValidPageInPaymentHandlerWindow(mWebContents.get())) {
ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindowForInsecureNavigation( ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindowForInsecureNavigation(
mWebContents.get()); mWebContentsRef);
mHider.run(); mHider.run();
} }
} }
@Override @Override
public void didAttachInterstitialPage() { public void didAttachInterstitialPage() {
if (hideSheetIfWebContentsNotExist()) return;
ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindowForInsecureNavigation( ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindowForInsecureNavigation(
mWebContents.get()); mWebContentsRef);
mHider.run(); mHider.run();
} }
@Override @Override
public void didFailLoad( public void didFailLoad(
boolean isMainFrame, int errorCode, String description, String failingUrl) { boolean isMainFrame, int errorCode, String description, String failingUrl) {
if (hideSheetIfWebContentsNotExist()) return;
// TODO(crbug.com/1017926): Respond to service worker with the net error. // TODO(crbug.com/1017926): Respond to service worker with the net error.
ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContents.get()); ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContentsRef);
mHider.run(); mHider.run();
} }
} }
...@@ -11,13 +11,10 @@ import android.view.View; ...@@ -11,13 +11,10 @@ import android.view.View;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.thinwebview.ThinWebView; import org.chromium.chrome.browser.thinwebview.ThinWebView;
import org.chromium.chrome.browser.thinwebview.ThinWebViewFactory; import org.chromium.chrome.browser.thinwebview.ThinWebViewFactory;
import org.chromium.chrome.browser.ui.widget.FadingShadow;
import org.chromium.chrome.browser.ui.widget.FadingShadowView;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContent; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContent;
import org.chromium.components.embedder_support.view.ContentView; import org.chromium.components.embedder_support.view.ContentView;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
...@@ -25,12 +22,12 @@ import org.chromium.ui.base.ActivityWindowAndroid; ...@@ -25,12 +22,12 @@ import org.chromium.ui.base.ActivityWindowAndroid;
/** PaymentHandler UI. */ /** PaymentHandler UI. */
/* package */ class PaymentHandlerView implements BottomSheetContent { /* package */ class PaymentHandlerView implements BottomSheetContent {
private final int mToolbarHeightPx;
private final View mToolbarView; private final View mToolbarView;
private final FrameLayout mContentView; private final FrameLayout mContentView;
private final ThinWebView mThinWebView; private final ThinWebView mThinWebView;
private final Handler mReflowHandler = new Handler(); private final Handler mReflowHandler = new Handler();
private final int mTabHeight; private final int mTabHeight;
private final int mToolbarHeightPx;
/** /**
* Construct the PaymentHandlerView. * Construct the PaymentHandlerView.
...@@ -39,13 +36,12 @@ import org.chromium.ui.base.ActivityWindowAndroid; ...@@ -39,13 +36,12 @@ import org.chromium.ui.base.ActivityWindowAndroid;
* @param webContents The web-content of the payment-handler web-app. * @param webContents The web-content of the payment-handler web-app.
* @param webContentView The {@link ContentView} that has been contructed with the web-content. * @param webContentView The {@link ContentView} that has been contructed with the web-content.
*/ */
/* package */ PaymentHandlerView( /* package */ PaymentHandlerView(ChromeActivity activity, WebContents webContents,
ChromeActivity activity, WebContents webContents, ContentView webContentView) { ContentView webContentView, View toolbarView) {
mToolbarHeightPx = activity.getResources().getDimensionPixelSize(
R.dimen.custom_tabs_control_container_height);
mTabHeight = activity.getActivityTab().getHeight(); mTabHeight = activity.getActivityTab().getHeight();
mToolbarView = toolbarView;
mToolbarView = LayoutInflater.from(activity).inflate(R.layout.custom_tabs_toolbar, null); mToolbarHeightPx =
activity.getResources().getDimensionPixelSize(R.dimen.preview_tab_toolbar_height);
mContentView = (FrameLayout) LayoutInflater.from(activity).inflate( mContentView = (FrameLayout) LayoutInflater.from(activity).inflate(
R.layout.payment_handler_content, null); R.layout.payment_handler_content, null);
...@@ -63,13 +59,10 @@ import org.chromium.ui.base.ActivityWindowAndroid; ...@@ -63,13 +59,10 @@ import org.chromium.ui.base.ActivityWindowAndroid;
*/ */
private void initContentView(ChromeActivity activity, ThinWebView thinWebView, private void initContentView(ChromeActivity activity, ThinWebView thinWebView,
WebContents webContents, ContentView webContentView) { WebContents webContents, ContentView webContentView) {
FadingShadowView shadow = mContentView.findViewById(R.id.shadow);
shadow.init(ApiCompatibilityUtils.getColor(
activity.getResources(), R.color.toolbar_shadow_color),
FadingShadow.POSITION_TOP);
assert webContentView.getParent() == null; assert webContentView.getParent() == null;
thinWebView.attachWebContents(webContents, webContentView); thinWebView.attachWebContents(webContents, webContentView);
mContentView.setPadding(/*left=*/0, /*top=*/mToolbarHeightPx, /*right=*/0, /*bottom=*/0); mContentView.setPadding(
/*left=*/0, /*top=*/mToolbarHeightPx, /*right=*/0, /*bottom=*/0);
mContentView.addView(thinWebView.getView(), /*index=*/0); mContentView.addView(thinWebView.getView(), /*index=*/0);
} }
...@@ -89,6 +82,10 @@ import org.chromium.ui.base.ActivityWindowAndroid; ...@@ -89,6 +82,10 @@ import org.chromium.ui.base.ActivityWindowAndroid;
mThinWebView.getView().setLayoutParams(params); mThinWebView.getView().setLayoutParams(params);
} }
/* package */ int getToolbarHeightPx() {
return mToolbarHeightPx;
}
// BottomSheetContent: // BottomSheetContent:
@Override @Override
public View getContentView() { public View getContentView() {
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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.toolbar;
import android.content.Context;
import android.view.View;
import org.chromium.components.security_state.ConnectionSecurityLevel;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
/**
* PaymentHandlerToolbar coordinator, which owns the component overall, i.e., creates other objects
* in the component and connects them. It decouples the implementation of this component from other
* components and acts as the point of contact between them. Any code in this component that needs
* to interact with another component does that through this coordinator.
*/
public class PaymentHandlerToolbarCoordinator {
private Runnable mHider;
private PaymentHandlerToolbarView mToolbarView;
/**
* Observer for the error of the payment handler toolbar.
*/
public interface ErrorObserver {
/**
* Called when the UI gets an error
*/
void onError();
}
/** Constructs the payment-handler toolbar component coordinator. */
public PaymentHandlerToolbarCoordinator(
Context context, WebContents webContents, ErrorObserver errorObserver) {
mToolbarView = new PaymentHandlerToolbarView(context);
PropertyModel model = new PropertyModel.Builder(PaymentHandlerToolbarProperties.ALL_KEYS)
.with(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, true)
.with(PaymentHandlerToolbarProperties.LOAD_PROGRESS, 0)
.with(PaymentHandlerToolbarProperties.SECURITY_ICON,
ConnectionSecurityLevel.NONE)
.build();
PaymentHandlerToolbarMediator mediator =
new PaymentHandlerToolbarMediator(model, webContents, errorObserver);
webContents.addObserver(mediator);
PropertyModelChangeProcessor changeProcessor = PropertyModelChangeProcessor.create(
model, mToolbarView, PaymentHandlerToolbarViewBinder::bind);
}
/** @return The height of the toolbar in px. */
public int getToolbarHeightPx() {
return mToolbarView.getToolbarHeightPx();
}
/** @return The toolbar of the PaymentHandler. */
public View getView() {
return mToolbarView.getView();
}
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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.toolbar;
import android.os.Handler;
import android.support.annotation.DrawableRes;
import org.chromium.base.Log;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.payments.handler.toolbar.PaymentHandlerToolbarCoordinator.ErrorObserver;
import org.chromium.chrome.browser.ssl.SecurityStateModel;
import org.chromium.components.security_state.ConnectionSecurityLevel;
import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.ui.modelutil.PropertyModel;
import java.net.URI;
import java.net.URISyntaxException;
/**
* PaymentHandlerToolbar mediator, which is responsible for receiving events from the view and
* notifies the backend (the coordinator).
*/
/* package */ class PaymentHandlerToolbarMediator extends WebContentsObserver {
private static final String TAG = "PaymentHandlerTb";
/** The delay (four video frames - for 60Hz) after which the hide progress will be hidden. */
private static final long HIDE_PROGRESS_BAR_DELAY_MS = (1000 / 60) * 4;
private final PropertyModel mModel;
private final ErrorObserver mErrorObserver;
/** The handler to delay hiding the progress bar. */
private Handler mHideProgressBarHandler;
/** Postfixed with "Ref" to distinguish from mWebContent in WebContentsObserver. */
private final WebContents mWebContentsRef;
/**
* Build a new mediator that handle events from outside the payment handler toolbar component.
* @param model The {@link PaymentHandlerToolbarProperties} that holds all the view state for
* the payment handler toolbar component.
* @param hider The callback to clean up the {@link ErrorObserver} when the sheet is
* hidden.
* @param webContents The web-contents that loads the payment app.
*/
/* package */ PaymentHandlerToolbarMediator(
PropertyModel model, WebContents webContents, ErrorObserver errorObserver) {
super(webContents);
mWebContentsRef = webContents;
mModel = model;
mErrorObserver = errorObserver;
}
// WebContentsObserver:
@Override
public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
// Hides the Progress Bar after a delay to make sure it is rendered for at least
// a few frames, otherwise its completion won't be visually noticeable.
mHideProgressBarHandler = new Handler();
mHideProgressBarHandler.postDelayed(() -> {
mModel.set(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, false);
mHideProgressBarHandler = null;
}, HIDE_PROGRESS_BAR_DELAY_MS);
return;
}
@Override
public void didFailLoad(
boolean isMainFrame, int errorCode, String description, String failingUrl) {
mModel.set(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, false);
}
@Override
public void didFinishNavigation(NavigationHandle navigation) {
if (navigation.hasCommitted() && navigation.isInMainFrame()) {
String url = navigation.getUrl();
String origin = UrlFormatter.formatUrlForSecurityDisplayOmitScheme(url);
try {
mModel.set(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, false);
mModel.set(PaymentHandlerToolbarProperties.ORIGIN, new URI(origin));
} catch (URISyntaxException e) {
Log.e(TAG, "Failed to instantiate URI with the origin \"%s\", whose url is \"%s\".",
origin, url);
mErrorObserver.onError();
return;
}
}
}
@Override
public void titleWasSet(String title) {
mModel.set(PaymentHandlerToolbarProperties.TITLE, title);
}
@Override
public void loadProgressChanged(float progress) {
if (progress == 1.0) return;
// If the load restarts when the progress bar is waiting to hide, cancel the handler
// callbacks.
if (mHideProgressBarHandler != null) {
mHideProgressBarHandler.removeCallbacksAndMessages(null);
mHideProgressBarHandler = null;
}
mModel.set(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, true);
mModel.set(PaymentHandlerToolbarProperties.LOAD_PROGRESS, progress);
}
@DrawableRes
private static int getSecurityIconResource(@ConnectionSecurityLevel int securityLevel) {
switch (securityLevel) {
case ConnectionSecurityLevel.NONE:
case ConnectionSecurityLevel.WARNING:
return R.drawable.omnibox_info;
case ConnectionSecurityLevel.DANGEROUS:
return R.drawable.omnibox_not_secure_warning;
case ConnectionSecurityLevel.SECURE_WITH_POLICY_INSTALLED_CERT:
case ConnectionSecurityLevel.SECURE:
case ConnectionSecurityLevel.EV_SECURE:
return R.drawable.omnibox_https_valid;
default:
assert false;
}
return 0;
}
@Override
public void didChangeVisibleSecurityState() {
int securityLevel = SecurityStateModel.getSecurityLevelForWebContents(mWebContentsRef);
mModel.set(PaymentHandlerToolbarProperties.SECURITY_ICON,
getSecurityIconResource(securityLevel));
}
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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.toolbar;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableFloatPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
import java.net.URI;
/** PaymentHandlerToolbar UI properties, which fully describe the state of the UI. */
/* package */ class PaymentHandlerToolbarProperties {
/* package */ static final WritableObjectPropertyKey<URI> ORIGIN =
new WritableObjectPropertyKey<>();
/* package */ static final WritableObjectPropertyKey<String> TITLE =
new WritableObjectPropertyKey<>();
/* package */ static final WritableFloatPropertyKey LOAD_PROGRESS =
new WritableFloatPropertyKey();
/* package */ static final WritableBooleanPropertyKey PROGRESS_VISIBLE =
new WritableBooleanPropertyKey();
/* package */ static final WritableIntPropertyKey SECURITY_ICON = new WritableIntPropertyKey();
/* package */ static final PropertyKey[] ALL_KEYS =
new PropertyKey[] {ORIGIN, TITLE, LOAD_PROGRESS, PROGRESS_VISIBLE, SECURITY_ICON};
// Prevent instantiation.
private PaymentHandlerToolbarProperties() {}
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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.toolbar;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ui.widget.FadingShadow;
import org.chromium.chrome.browser.ui.widget.FadingShadowView;
/** PaymentHandlerToolbar UI. */
/* package */ class PaymentHandlerToolbarView {
private final int mToolbarHeightPx;
private final View mToolbarView;
/* package */ final TextView mOriginView;
/* package */ final TextView mTitleView;
/* package */ final ProgressBar mProgressBar;
/* package */ final ImageView mSecurityIconView;
/**
* Construct the PaymentHandlerToolbarView.
*
* @param context The context where the bottome-sheet should be shown.
*/
/* package */ PaymentHandlerToolbarView(Context context) {
mToolbarHeightPx =
context.getResources().getDimensionPixelSize(R.dimen.preview_tab_toolbar_height);
mToolbarView = LayoutInflater.from(context).inflate(R.layout.ephemeral_tab_toolbar, null);
mOriginView = mToolbarView.findViewById(R.id.ephemeral_tab_caption);
mTitleView = mToolbarView.findViewById(R.id.ephemeral_tab_text);
mProgressBar = mToolbarView.findViewById(R.id.progress_bar);
mSecurityIconView = mToolbarView.findViewById(R.id.security_icon);
// These parts from ephemeral_tab_toolbar are not needed in this component.
mToolbarView.findViewById(R.id.open_in_new_tab).setVisibility(View.GONE);
mToolbarView.findViewById(R.id.favicon).setVisibility(View.GONE);
FadingShadowView shadow = mToolbarView.findViewById(R.id.shadow);
shadow.init(ApiCompatibilityUtils.getColor(
context.getResources(), R.color.toolbar_shadow_color),
FadingShadow.POSITION_TOP);
}
/** @return The height of the toolbar in px. */
/* package */ int getToolbarHeightPx() {
return mToolbarHeightPx;
}
/** @return The layout of the PaymentHandlerToolbar. */
/* package */ View getView() {
return mToolbarView;
}
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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.toolbar;
import android.view.View;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
/**
* PaymentHandlerToolbar view binder, which is stateless. It is called to bind a given model to a
* given view. Should contain as little business logic as possible.
*/
/* package */ class PaymentHandlerToolbarViewBinder {
/* package */ static void bind(
PropertyModel model, PaymentHandlerToolbarView view, PropertyKey propertyKey) {
if (PaymentHandlerToolbarProperties.ORIGIN == propertyKey) {
view.mOriginView.setText(model.get(PaymentHandlerToolbarProperties.ORIGIN).toString());
} else if (PaymentHandlerToolbarProperties.TITLE == propertyKey) {
view.mTitleView.setText(model.get(PaymentHandlerToolbarProperties.TITLE));
} else if (PaymentHandlerToolbarProperties.LOAD_PROGRESS == propertyKey) {
view.mProgressBar.setProgress(
Math.round(model.get(PaymentHandlerToolbarProperties.LOAD_PROGRESS) * 100));
} else if (PaymentHandlerToolbarProperties.PROGRESS_VISIBLE == propertyKey) {
boolean visible = model.get(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE);
view.mProgressBar.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
} else if (PaymentHandlerToolbarProperties.SECURITY_ICON == propertyKey) {
int securityIconResource = model.get(PaymentHandlerToolbarProperties.SECURITY_ICON);
view.mSecurityIconView.setImageResource(securityIconResource);
}
}
}
...@@ -126,6 +126,11 @@ void WebContentsObserverProxy::DidFailLoad( ...@@ -126,6 +126,11 @@ void WebContentsObserverProxy::DidFailLoad(
jstring_error_description, jstring_url); jstring_error_description, jstring_url);
} }
void WebContentsObserverProxy::DidChangeVisibleSecurityState() {
Java_WebContentsObserverProxy_didChangeVisibleSecurityState(
AttachCurrentThread(), java_observer_);
}
void WebContentsObserverProxy::DocumentAvailableInMainFrame() { void WebContentsObserverProxy::DocumentAvailableInMainFrame() {
JNIEnv* env = AttachCurrentThread(); JNIEnv* env = AttachCurrentThread();
Java_WebContentsObserverProxy_documentAvailableInMainFrame(env, Java_WebContentsObserverProxy_documentAvailableInMainFrame(env,
......
...@@ -40,6 +40,7 @@ class WebContentsObserverProxy : public WebContentsObserver { ...@@ -40,6 +40,7 @@ class WebContentsObserverProxy : public WebContentsObserver {
const GURL& validated_url, const GURL& validated_url,
int error_code, int error_code,
const base::string16& error_description) override; const base::string16& error_description) override;
void DidChangeVisibleSecurityState() override;
void DocumentAvailableInMainFrame() override; void DocumentAvailableInMainFrame() override;
void DidFirstVisuallyNonEmptyPaint() override; void DidFirstVisuallyNonEmptyPaint() override;
void OnVisibilityChanged(content::Visibility visibility) override; void OnVisibilityChanged(content::Visibility visibility) override;
......
...@@ -126,6 +126,14 @@ class WebContentsObserverProxy extends WebContentsObserver { ...@@ -126,6 +126,14 @@ class WebContentsObserverProxy extends WebContentsObserver {
} }
} }
@Override
@CalledByNative
public void didChangeVisibleSecurityState() {
for (mObserversIterator.rewind(); mObserversIterator.hasNext();) {
mObserversIterator.next().didChangeVisibleSecurityState();
}
}
@Override @Override
@CalledByNative @CalledByNative
public void didFailLoad( public void didFailLoad(
......
...@@ -81,6 +81,11 @@ public abstract class WebContentsObserver { ...@@ -81,6 +81,11 @@ public abstract class WebContentsObserver {
*/ */
public void loadProgressChanged(float progress) {} public void loadProgressChanged(float progress) {}
/**
* Called when a page's visible security state has changed.
*/
public void didChangeVisibleSecurityState() {}
/** /**
* Called when an error occurs while loading a page and/or the page fails to load. * Called when an error occurs while loading a page and/or the page fails to load.
* @param isMainFrame Whether the navigation occurred in main frame. * @param isMainFrame Whether the navigation occurred in main frame.
......
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