tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Theresa Wellington | 33a9238 | 2020-06-19 19:23:00 | [diff] [blame] | 5 | package org.chromium.chrome.browser.browser_controls; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 6 | |
| 7 | import android.os.Handler; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 8 | import android.os.SystemClock; |
| 9 | |
Henrique Nakashima | ae72a58 | 2019-11-13 16:56:16 | [diff] [blame] | 10 | import androidx.annotation.VisibleForTesting; |
| 11 | |
jonross | e6852d5 | 2019-07-12 17:42:49 | [diff] [blame] | 12 | import org.chromium.base.CommandLine; |
Theresa Wellington | 6695751 | 2020-01-08 03:24:25 | [diff] [blame] | 13 | import org.chromium.base.supplier.ObservableSupplier; |
| 14 | import org.chromium.base.supplier.Supplier; |
Dave Tapuska | fc4adbae | 2020-12-02 22:08:59 | [diff] [blame^] | 15 | import org.chromium.cc.input.BrowserControlsState; |
Henrique Nakashima | b64e178 | 2020-03-06 06:21:18 | [diff] [blame] | 16 | import org.chromium.chrome.browser.flags.ChromeSwitches; |
Evan Stade | d26b27c | 2020-02-07 19:46:20 | [diff] [blame] | 17 | import org.chromium.components.browser_ui.util.BrowserControlsVisibilityDelegate; |
Matt Jones | 672eebc | 2019-10-14 23:03:00 | [diff] [blame] | 18 | import org.chromium.ui.util.TokenHolder; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 19 | |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 20 | /** |
| 21 | * Determines the desired visibility of the browser controls based on the current state of the |
| 22 | * running activity. |
| 23 | */ |
| 24 | public class BrowserStateBrowserControlsVisibilityDelegate |
Ted Choc | d4dab4b | 2019-12-09 21:41:26 | [diff] [blame] | 25 | extends BrowserControlsVisibilityDelegate { |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 26 | /** Minimum duration (in milliseconds) that the controls are shown when requested. */ |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 27 | @VisibleForTesting |
| 28 | static final long MINIMUM_SHOW_DURATION_MS = 3000; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 29 | |
| 30 | private static boolean sDisableOverridesForTesting; |
| 31 | |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 32 | private final TokenHolder mTokenHolder; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 33 | |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 34 | private final Handler mHandler = new Handler(); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 35 | |
Jinsuk Kim | b717720 | 2019-06-13 12:52:33 | [diff] [blame] | 36 | /** Predicate that tells if we're in persistent fullscreen mode. */ |
| 37 | private final Supplier<Boolean> mPersistentFullscreenMode; |
| 38 | |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 39 | private long mCurrentShowingStartTime; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 40 | |
| 41 | /** |
| 42 | * Constructs a BrowserControlsVisibilityDelegate designed to deal with overrides driven by |
| 43 | * the browser UI (as opposed to the state of the tab). |
tedchoc | c5be519e | 2017-01-20 20:54:17 | [diff] [blame] | 44 | * |
Jinsuk Kim | b717720 | 2019-06-13 12:52:33 | [diff] [blame] | 45 | * @param persistentFullscreenMode Predicate that tells if we're in persistent fullscreen mode. |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 46 | */ |
Jinsuk Kim | b717720 | 2019-06-13 12:52:33 | [diff] [blame] | 47 | public BrowserStateBrowserControlsVisibilityDelegate( |
Ted Choc | d4dab4b | 2019-12-09 21:41:26 | [diff] [blame] | 48 | ObservableSupplier<Boolean> persistentFullscreenMode) { |
| 49 | super(BrowserControlsState.BOTH); |
| 50 | mTokenHolder = new TokenHolder(this::updateVisibilityConstraints); |
Jinsuk Kim | b717720 | 2019-06-13 12:52:33 | [diff] [blame] | 51 | mPersistentFullscreenMode = persistentFullscreenMode; |
Ted Choc | d4dab4b | 2019-12-09 21:41:26 | [diff] [blame] | 52 | persistentFullscreenMode.addObserver((persistentMode) -> updateVisibilityConstraints()); |
| 53 | updateVisibilityConstraints(); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 54 | } |
| 55 | |
| 56 | private void ensureControlsVisibleForMinDuration() { |
jonross | e6852d5 | 2019-07-12 17:42:49 | [diff] [blame] | 57 | // Do not lock the controls as visible. Such as in testing. |
Matt Jones | 672eebc | 2019-10-14 23:03:00 | [diff] [blame] | 58 | if (CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_MINIMUM_SHOW_DURATION)) { |
jonross | e6852d5 | 2019-07-12 17:42:49 | [diff] [blame] | 59 | return; |
Matt Jones | 672eebc | 2019-10-14 23:03:00 | [diff] [blame] | 60 | } |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 61 | if (mHandler.hasMessages(0)) return; // Messages sent via post/postDelayed have what=0 |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 62 | |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 63 | long currentShowingTime = SystemClock.uptimeMillis() - mCurrentShowingStartTime; |
| 64 | if (currentShowingTime >= MINIMUM_SHOW_DURATION_MS) return; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 65 | |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 66 | final int temporaryToken = mTokenHolder.acquireToken(); |
Theresa Wellington | 33a9238 | 2020-06-19 19:23:00 | [diff] [blame] | 67 | mHandler.postDelayed(() |
| 68 | -> mTokenHolder.releaseToken(temporaryToken), |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 69 | MINIMUM_SHOW_DURATION_MS - currentShowingTime); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | /** |
| 73 | * Trigger a temporary showing of the browser controls. |
| 74 | */ |
| 75 | public void showControlsTransient() { |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 76 | if (!mTokenHolder.hasTokens()) mCurrentShowingStartTime = SystemClock.uptimeMillis(); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 77 | ensureControlsVisibleForMinDuration(); |
| 78 | } |
| 79 | |
| 80 | /** |
| 81 | * Trigger a permanent showing of the browser controls until requested otherwise. |
| 82 | * |
| 83 | * @return The token that determines whether the requester still needs persistent controls to |
| 84 | * be present on the screen. |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 85 | * @see #releasePersistentShowingToken(int) |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 86 | */ |
| 87 | public int showControlsPersistent() { |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 88 | if (!mTokenHolder.hasTokens()) mCurrentShowingStartTime = SystemClock.uptimeMillis(); |
| 89 | return mTokenHolder.acquireToken(); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Same behavior as {@link #showControlsPersistent()} but also handles removing a previously |
| 94 | * requested token if necessary. |
| 95 | * |
| 96 | * @param oldToken The old fullscreen token to be cleared. |
| 97 | * @return The fullscreen token as defined in {@link #showControlsPersistent()}. |
| 98 | */ |
| 99 | public int showControlsPersistentAndClearOldToken(int oldToken) { |
| 100 | int newToken = showControlsPersistent(); |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 101 | mTokenHolder.releaseToken(oldToken); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 102 | return newToken; |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Notify the manager that the browser controls are no longer required for the given token. |
| 107 | * |
| 108 | * @param token The fullscreen token returned from {@link #showControlsPersistent()}. |
| 109 | */ |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 110 | public void releasePersistentShowingToken(int token) { |
| 111 | if (mTokenHolder.containsOnly(token)) { |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 112 | ensureControlsVisibleForMinDuration(); |
| 113 | } |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 114 | mTokenHolder.releaseToken(token); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 115 | } |
| 116 | |
Ted Choc | d4dab4b | 2019-12-09 21:41:26 | [diff] [blame] | 117 | @BrowserControlsState |
| 118 | private int calculateVisibilityConstraints() { |
| 119 | if (mPersistentFullscreenMode.get()) { |
| 120 | return BrowserControlsState.HIDDEN; |
| 121 | } else if (mTokenHolder.hasTokens() && !sDisableOverridesForTesting) { |
| 122 | return BrowserControlsState.SHOWN; |
| 123 | } |
| 124 | return BrowserControlsState.BOTH; |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 125 | } |
| 126 | |
Ted Choc | d4dab4b | 2019-12-09 21:41:26 | [diff] [blame] | 127 | private void updateVisibilityConstraints() { |
| 128 | set(calculateVisibilityConstraints()); |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | /** |
| 132 | * Disable any browser visibility overrides for testing. |
| 133 | */ |
| 134 | public static void disableForTesting() { |
| 135 | sDisableOverridesForTesting = true; |
| 136 | } |
Pavel Shmakov | 760c5a94 | 2018-10-12 17:09:51 | [diff] [blame] | 137 | |
| 138 | /** |
| 139 | * Performs clean-up. |
| 140 | */ |
| 141 | public void destroy() { |
| 142 | mHandler.removeCallbacksAndMessages(null); |
| 143 | } |
tedchoc | b026e994 | 2016-11-16 01:36:44 | [diff] [blame] | 144 | } |