Commit ece08cd7 authored by Mehran Mahmoudi's avatar Mehran Mahmoudi Committed by Commit Bot

[Paint Preview] Disable toolbar hide on scroll when Paint Preview showing

This CL introduces the new PaintPreviewWindowAndroidHelper class. This
class stores activity-specific variables in PaintPreviewHelper. Using
the BrowserControlsManager class, it makes the top toolbar persistent
when a Paint Preview is shown.

This CL also fixes a bug where TabbedPaintPreviewPlayer#onDismiss was
never called.

Bug: 1131497
Change-Id: I3caf7017f601536ba03c1e1c60c9b024917f6063
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2425433
Commit-Queue: Mehran Mahmoudi <mahmoudi@chromium.org>
Reviewed-by: default avatarCalder Kitagawa <ckitagawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810838}
parent c2b4d7c7
......@@ -4,11 +4,15 @@
package org.chromium.chrome.browser.paint_preview;
import android.app.Activity;
import android.os.SystemClock;
import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.flags.CachedFeatureFlags;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
import org.chromium.chrome.browser.metrics.PageLoadMetrics;
import org.chromium.chrome.browser.metrics.UmaUtils;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
......@@ -18,6 +22,10 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;
import java.util.HashMap;
import java.util.Map;
/**
* Handles initialization of the Paint Preview tab observers.
......@@ -31,9 +39,12 @@ public class PaintPreviewHelper {
private static boolean sHasAttemptedToShowOnRestore;
/**
* Tracks the activity creation time in ms from {@link SystemClock#elapsedRealtime}.
* A map for keeping Activity-specific variables and classes. New entries are added on calls
* to {@link #initialize(ChromeActivity, TabModelSelector)}. Entries are automatically removed
* when their respective Activity is destroyed.
*/
private static long sActivityCreationTimeMs;
private static Map<WindowAndroid, PaintPreviewWindowAndroidHelper> sWindowAndroidHelperMap =
new HashMap<>();
/**
* Initializes the logic required for the Paint Preview on startup feature. Mainly, observes a
......@@ -41,13 +52,14 @@ public class PaintPreviewHelper {
* @param activity The ChromeActivity that corresponds to the tabModelSelector.
* @param tabModelSelector The TabModelSelector to observe.
*/
public static void initialize(ChromeActivity activity, TabModelSelector tabModelSelector) {
public static void initialize(ChromeActivity<?> activity, TabModelSelector tabModelSelector) {
if (!CachedFeatureFlags.isEnabled(ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP)) return;
if (!MultiWindowUtils.getInstance().areMultipleChromeInstancesRunning(activity)) {
sHasAttemptedToShowOnRestore = false;
}
sActivityCreationTimeMs = activity.getOnCreateTimestampMs();
sWindowAndroidHelperMap.put(
activity.getWindowAndroid(), new PaintPreviewWindowAndroidHelper(activity));
// TODO(crbug/1074428): verify this doesn't cause a memory leak if the user exits Chrome
// prior to onTabStateInitialized being called.
......@@ -66,22 +78,23 @@ public class PaintPreviewHelper {
}
/**
* Attempts to display the Paint Preview representation of for the given Tab.
* @param onShown The callback for when the Paint Preview is shown.
* @param onDismissed The callback for when the Paint Preview is dismissed.
* @return Whether the Paint Preview started to initialize or is already initializating.
* Note that if the Paint Preview is already showing, this will return false.
* Attempts to display the Paint Preview representation for the given Tab.
*/
public static boolean showPaintPreviewOnRestore(Tab tab) {
public static void showPaintPreviewOnRestore(Tab tab) {
if (!CachedFeatureFlags.isEnabled(ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP)
|| sHasAttemptedToShowOnRestore
|| ChromeAccessibilityUtil.get().isAccessibilityEnabled()) {
return false;
return;
}
sHasAttemptedToShowOnRestore = true;
PaintPreviewWindowAndroidHelper windowAndroidHelper =
sWindowAndroidHelperMap.get(tab.getWindowAndroid());
if (windowAndroidHelper == null) return;
sHasAttemptedToShowOnRestore = true;
TabbedPaintPreviewPlayer player = TabbedPaintPreviewPlayer.get(tab);
player.setBrowserVisibilityDelegate(
windowAndroidHelper.getBrowserControlsManager().getBrowserVisibilityDelegate());
PageLoadMetrics.Observer observer = new PageLoadMetrics.Observer() {
@Override
public void onFirstMeaningfulPaint(WebContents webContents, long navigationId,
......@@ -90,16 +103,49 @@ public class PaintPreviewHelper {
}
};
if (!player.maybeShow(() -> {
PageLoadMetrics.removeObserver(observer);
}, sActivityCreationTimeMs, () -> {
return UmaUtils.hasComeToForeground() && !UmaUtils.hasComeToBackground();
})) {
return false;
if (!player.maybeShow(()
-> PageLoadMetrics.removeObserver(observer),
windowAndroidHelper.getActivityCreationTime(),
() -> UmaUtils.hasComeToForeground() && !UmaUtils.hasComeToBackground())) {
return;
}
PageLoadMetrics.addObserver(observer);
}
return true;
/**
* A helper class for keeping activity-specific variables and classes.
*/
private static class PaintPreviewWindowAndroidHelper
implements ApplicationStatus.ActivityStateListener {
/**
* Tracks the activity creation time in ms from {@link SystemClock#elapsedRealtime}.
*/
private long mActivityCreationTime;
private WindowAndroid mWindowAndroid;
private BrowserControlsManager mBrowserControlsManager;
PaintPreviewWindowAndroidHelper(ChromeActivity<?> chromeActivity) {
mWindowAndroid = chromeActivity.getWindowAndroid();
mActivityCreationTime = chromeActivity.getOnCreateTimestampMs();
mBrowserControlsManager = chromeActivity.getBrowserControlsManager();
ApplicationStatus.registerStateListenerForActivity(this, chromeActivity);
}
long getActivityCreationTime() {
return mActivityCreationTime;
}
BrowserControlsManager getBrowserControlsManager() {
return mBrowserControlsManager;
}
@Override
public void onActivityStateChange(Activity activity, @ActivityState int newState) {
if (newState == ActivityState.DESTROYED) {
sWindowAndroidHelperMap.remove(mWindowAndroid);
ApplicationStatus.unregisterActivityStateListener(this);
}
}
}
}
......@@ -34,6 +34,7 @@ android_library("java") {
"//base:base_java",
"//base:jni_java",
"//chrome/browser/android/lifecycle:java",
"//chrome/browser/browser_controls/android:java",
"//chrome/browser/flags:java",
"//chrome/browser/tab:java",
"//chrome/browser/tabmodel:java",
......
......@@ -15,6 +15,7 @@ import android.view.View;
import androidx.annotation.Nullable;
import org.chromium.base.UserData;
import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.paint_preview.TabbedPaintPreviewMetricsHelper.ExitCause;
import org.chromium.chrome.browser.paint_preview.services.PaintPreviewTabService;
......@@ -31,6 +32,7 @@ import org.chromium.components.paintpreview.player.PlayerManager;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.util.TokenHolder;
import org.chromium.url.GURL;
import java.util.concurrent.Callable;
......@@ -61,6 +63,8 @@ public class TabbedPaintPreviewPlayer implements TabViewProvider, UserData {
private boolean mFadingOut;
private int mSnackbarShownCount;
private TabbedPaintPreviewMetricsHelper mMetricsHelper;
private BrowserStateBrowserControlsVisibilityDelegate mBrowserVisibilityDelegate;
private int mPersistentToolbarToken = TokenHolder.INVALID_TOKEN;
public static TabbedPaintPreviewPlayer get(Tab tab) {
if (tab.getUserDataHost().getUserData(USER_DATA_KEY) == null) {
......@@ -116,6 +120,8 @@ public class TabbedPaintPreviewPlayer implements TabViewProvider, UserData {
@Override
public void onHidden(Tab tab, @TabHidingType int hidingType) {
releasePersistentToolbar();
if (mPlayerManager == null || !isShowingAndNeedsBadge()) return;
// If the tab is hidden as a result of pausing the activity we shouldn't remove it.
......@@ -123,6 +129,11 @@ public class TabbedPaintPreviewPlayer implements TabViewProvider, UserData {
removePaintPreview(ExitCause.TAB_HIDDEN);
}
@Override
public void onShown(Tab tab, int type) {
if (isShowingAndNeedsBadge()) showToolbarPersistent();
}
}
private TabbedPaintPreviewPlayer(Tab tab) {
......@@ -133,6 +144,11 @@ public class TabbedPaintPreviewPlayer implements TabViewProvider, UserData {
mTab.addObserver(mObserver);
}
public void setBrowserVisibilityDelegate(
BrowserStateBrowserControlsVisibilityDelegate browserVisibilityDelegate) {
mBrowserVisibilityDelegate = browserVisibilityDelegate;
}
/**
* Triggered via {@link PageLoadMetrics.Observer} when First Meaningful Paint happens.
* @param webContents the webContents that triggered the event.
......@@ -207,11 +223,12 @@ public class TabbedPaintPreviewPlayer implements TabViewProvider, UserData {
*/
private void removePaintPreview(@ExitCause int exitCause) {
PaintPreviewCompositorUtils.stopWarmCompositor();
mOnDismissed = null;
mInitializing = false;
if (mTab == null || mPlayerManager == null || mFadingOut) return;
mFadingOut = true;
if (mOnDismissed != null) mOnDismissed.run();
mOnDismissed = null;
Point scrollPosition = mPlayerManager.getScrollPosition();
if (mTab.getWebContents() != null && scrollPosition != null) {
mTab.getWebContents().getEventForwarder().scrollTo(scrollPosition.x, scrollPosition.y);
......@@ -276,6 +293,25 @@ public class TabbedPaintPreviewPlayer implements TabViewProvider, UserData {
mTab.loadUrl(new LoadUrlParams(url.getSpec()));
}
/**
* Persistently shows the toolbar and avoids hiding it on scrolling down.
*/
private void showToolbarPersistent() {
if (mBrowserVisibilityDelegate == null
|| mPersistentToolbarToken != TokenHolder.INVALID_TOKEN) {
return;
}
mPersistentToolbarToken = mBrowserVisibilityDelegate.showControlsPersistent();
}
private void releasePersistentToolbar() {
if (mBrowserVisibilityDelegate == null) return;
mBrowserVisibilityDelegate.releasePersistentShowingToken(mPersistentToolbarToken);
mPersistentToolbarToken = TokenHolder.INVALID_TOKEN;
}
@Override
public int getTabViewProviderType() {
return Type.PAINT_PREVIEW;
......@@ -286,9 +322,14 @@ public class TabbedPaintPreviewPlayer implements TabViewProvider, UserData {
return mPlayerManager == null ? null : mPlayerManager.getView();
}
@Override
public void onShown() {
showToolbarPersistent();
}
@Override
public void onHidden() {
if (mOnDismissed != null) mOnDismissed.run();
releasePersistentToolbar();
}
@Override
......
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