1 // Copyright 2015 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 
5 package org.chromium.chrome.browser.toolbar.top;
6 
7 import android.content.Context;
8 import android.content.res.ColorStateList;
9 import android.graphics.Canvas;
10 import android.graphics.Rect;
11 import android.graphics.drawable.Drawable;
12 import android.os.SystemClock;
13 import android.util.AttributeSet;
14 import android.view.InputDevice;
15 import android.view.MotionEvent;
16 import android.view.View;
17 import android.view.ViewGroup;
18 import android.widget.FrameLayout;
19 import android.widget.ProgressBar;
20 
21 import androidx.annotation.CallSuper;
22 import androidx.annotation.Nullable;
23 import androidx.annotation.VisibleForTesting;
24 
25 import org.chromium.base.Callback;
26 import org.chromium.base.ObserverList;
27 import org.chromium.base.TraceEvent;
28 import org.chromium.chrome.R;
29 import org.chromium.chrome.browser.findinpage.FindToolbar;
30 import org.chromium.chrome.browser.omnibox.LocationBar;
31 import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
32 import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
33 import org.chromium.chrome.browser.omnibox.UrlBarData;
34 import org.chromium.chrome.browser.profiles.Profile;
35 import org.chromium.chrome.browser.tab.Tab;
36 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
37 import org.chromium.chrome.browser.toolbar.ButtonData;
38 import org.chromium.chrome.browser.toolbar.HomeButton;
39 import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
40 import org.chromium.chrome.browser.toolbar.TabCountProvider;
41 import org.chromium.chrome.browser.toolbar.ThemeColorProvider;
42 import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver;
43 import org.chromium.chrome.browser.toolbar.ThemeColorProvider.TintObserver;
44 import org.chromium.chrome.browser.toolbar.ToolbarColors;
45 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
46 import org.chromium.chrome.browser.toolbar.ToolbarProgressBar;
47 import org.chromium.chrome.browser.toolbar.ToolbarTabController;
48 import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator;
49 import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator.UrlExpansionObserver;
50 import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
51 import org.chromium.ui.UiUtils;
52 import org.chromium.ui.base.ViewUtils;
53 
54 /**
55  * Layout class that contains the base shared logic for manipulating the toolbar component. For
56  * interaction that are not from Views inside Toolbar hierarchy all interactions should be done
57  * through {@link Toolbar} rather than using this class directly.
58  */
59 public abstract class ToolbarLayout
60         extends FrameLayout implements TintObserver, ThemeColorObserver {
61     private Callback<Runnable> mInvalidator;
62 
63     protected final ObserverList<UrlExpansionObserver> mUrlExpansionObservers =
64             new ObserverList<>();
65     private final int[] mTempPosition = new int[2];
66 
67     private final ColorStateList mDefaultTint;
68 
69     private ToolbarDataProvider mToolbarDataProvider;
70     private ToolbarTabController mToolbarTabController;
71 
72     @Nullable
73     protected ToolbarProgressBar mProgressBar;
74 
75     private boolean mNativeLibraryReady;
76     private boolean mUrlHasFocus;
77 
78     private long mFirstDrawTimeMs;
79 
80     private boolean mFindInPageToolbarShowing;
81 
82     private ThemeColorProvider mThemeColorProvider;
83     private MenuButtonCoordinator mMenuButtonCoordinator;
84     private AppMenuButtonHelper mAppMenuButtonHelper;
85 
86     private Callback<Boolean> mOverlayVisibilityCallback;
87     private Runnable mTabOrModelChangeRunnable;
88 
89     /**
90      * Basic constructor for {@link ToolbarLayout}.
91      */
ToolbarLayout(Context context, AttributeSet attrs)92     public ToolbarLayout(Context context, AttributeSet attrs) {
93         super(context, attrs);
94         mDefaultTint = ToolbarColors.getThemedToolbarIconTint(getContext(), false);
95         mProgressBar = createProgressBar();
96 
97         addOnLayoutChangeListener(new OnLayoutChangeListener() {
98             @Override
99             public void onLayoutChange(View view, int left, int top, int right, int bottom,
100                     int oldLeft, int oldTop, int oldRight, int oldBottom) {
101                 if (isNativeLibraryReady() && mProgressBar.getParent() != null) {
102                     mProgressBar.initializeAnimation();
103                 }
104 
105                 // Since this only needs to happen once, remove this listener from the view.
106                 removeOnLayoutChangeListener(this);
107             }
108         });
109     }
110 
111     /**
112      * Initialize the external dependencies required for view interaction.
113      * @param toolbarDataProvider The provider for toolbar data.
114      * @param tabController       The controller that handles interactions with the tab.
115      * @param menuButtonCoordinator Coordinator for interacting with the MenuButton.
116      */
117     @CallSuper
initialize(ToolbarDataProvider toolbarDataProvider, ToolbarTabController tabController, MenuButtonCoordinator menuButtonCoordinator, Runnable tabOrModelChangeRunnable)118     protected void initialize(ToolbarDataProvider toolbarDataProvider,
119             ToolbarTabController tabController, MenuButtonCoordinator menuButtonCoordinator,
120             Runnable tabOrModelChangeRunnable) {
121         mToolbarDataProvider = toolbarDataProvider;
122         mToolbarTabController = tabController;
123         mMenuButtonCoordinator = menuButtonCoordinator;
124         mTabOrModelChangeRunnable = tabOrModelChangeRunnable;
125     }
126 
127     /**
128      * @param callback Callback to invoke on visibility change of the texture version
129      *        of the top toolbar.
130      */
setOverlayVisibilityCallback(Callback<Boolean> callback)131     public void setOverlayVisibilityCallback(Callback<Boolean> callback) {
132         mOverlayVisibilityCallback = callback;
133         mOverlayVisibilityCallback.onResult(getVisibility() == View.VISIBLE);
134     }
135 
136     @Override
setVisibility(int visibility)137     public void setVisibility(int visibility) {
138         super.setVisibility(visibility);
139         if (mOverlayVisibilityCallback != null) {
140             mOverlayVisibilityCallback.onResult(visibility == View.VISIBLE);
141         }
142     }
143 
144     /**
145      * @param appMenuButtonHelper The helper for managing menu button interactions.
146      */
setAppMenuButtonHelper(AppMenuButtonHelper appMenuButtonHelper)147     void setAppMenuButtonHelper(AppMenuButtonHelper appMenuButtonHelper) {
148         mAppMenuButtonHelper = appMenuButtonHelper;
149     }
150 
151     // TODO(pnoland, https://crbug.com/865801): Move this from ToolbarLayout to forthcoming
152     // BrowsingModeToolbarCoordinator.
setLocationBarCoordinator(LocationBarCoordinator locationBarCoordinator)153     public void setLocationBarCoordinator(LocationBarCoordinator locationBarCoordinator) {}
154 
155     /**
156      * Cleans up any code as necessary.
157      */
destroy()158     void destroy() {
159         if (mThemeColorProvider != null) {
160             mThemeColorProvider.removeTintObserver(this);
161             mThemeColorProvider.removeThemeColorObserver(this);
162             mThemeColorProvider = null;
163         }
164     }
165 
166     /**
167      * @param urlExpansionObserver The observer that observes URL expansion progress change.
168      */
addUrlExpansionObserver(UrlExpansionObserver urlExpansionObserver)169     void addUrlExpansionObserver(UrlExpansionObserver urlExpansionObserver) {
170         mUrlExpansionObservers.addObserver(urlExpansionObserver);
171     }
172 
173     /**
174      * @param urlExpansionObserver The observer that observes URL expansion progress change.
175      */
removeUrlExpansionObserver(UrlExpansionObserver urlExpansionObserver)176     void removeUrlExpansionObserver(UrlExpansionObserver urlExpansionObserver) {
177         mUrlExpansionObservers.removeObserver(urlExpansionObserver);
178     }
179 
180     /**
181      * @param themeColorProvider The {@link ThemeColorProvider} used for tinting the toolbar
182      *                           buttons.
183      */
setThemeColorProvider(ThemeColorProvider themeColorProvider)184     void setThemeColorProvider(ThemeColorProvider themeColorProvider) {
185         mThemeColorProvider = themeColorProvider;
186         mThemeColorProvider.addTintObserver(this);
187         mThemeColorProvider.addThemeColorObserver(this);
188     }
189 
190     /**
191      * @return The tint the toolbar buttons should use.
192      */
getTint()193     protected ColorStateList getTint() {
194         return mThemeColorProvider == null ? mDefaultTint : mThemeColorProvider.getTint();
195     }
196 
197     /**
198      * @return Whether to use light assets.
199      */
useLight()200     protected boolean useLight() {
201         return mThemeColorProvider != null && mThemeColorProvider.useLight();
202     }
203 
204     @Override
onTintChanged(ColorStateList tint, boolean useLight)205     public void onTintChanged(ColorStateList tint, boolean useLight) {}
206 
207     @Override
onThemeColorChanged(int color, boolean shouldAnimate)208     public void onThemeColorChanged(int color, boolean shouldAnimate) {}
209 
210     /**
211      * Set the height that the progress bar should be.
212      * @return The progress bar height in px.
213      */
getProgressBarHeight()214     int getProgressBarHeight() {
215         return getResources().getDimensionPixelSize(R.dimen.toolbar_progress_bar_height);
216     }
217 
218     /**
219      * @return A progress bar for Chrome to use.
220      */
createProgressBar()221     ToolbarProgressBar createProgressBar() {
222         return new ToolbarProgressBar(getContext(), getProgressBarHeight(), this, false);
223     }
224 
225     /**
226      * TODO comment
227      */
228     @CallSuper
onMenuButtonDisabled()229     protected void onMenuButtonDisabled() {}
230 
231     @Override
onFinishInflate()232     protected void onFinishInflate() {
233         super.onFinishInflate();
234 
235         // Initialize the provider to an empty version to avoid null checking everywhere.
236         mToolbarDataProvider = new ToolbarDataProvider() {
237             @Override
238             public boolean isIncognito() {
239                 return false;
240             }
241 
242             @Override
243             public boolean isInOverviewAndShowingOmnibox() {
244                 return false;
245             }
246 
247             @Override
248             public boolean shouldShowLocationBarInOverviewMode() {
249                 return false;
250             }
251 
252             @Override
253             public Profile getProfile() {
254                 return null;
255             }
256 
257             @Override
258             public Tab getTab() {
259                 return null;
260             }
261 
262             @Override
263             public String getCurrentUrl() {
264                 return "";
265             }
266 
267             @Override
268             public UrlBarData getUrlBarData() {
269                 return UrlBarData.EMPTY;
270             }
271 
272             @Override
273             public NewTabPageDelegate getNewTabPageDelegate() {
274                 return NewTabPageDelegate.EMPTY;
275             }
276 
277             @Override
278             public int getPrimaryColor() {
279                 return 0;
280             }
281 
282             @Override
283             public boolean isUsingBrandColor() {
284                 return false;
285             }
286         };
287     }
288 
289     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)290     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
291         try (TraceEvent e = TraceEvent.scoped("ToolbarLayout.onMeasure")) {
292             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
293         }
294     }
295 
296     @Override
onLayout(boolean changed, int left, int top, int right, int bottom)297     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
298         try (TraceEvent e = TraceEvent.scoped("ToolbarLayout.onLayout")) {
299             super.onLayout(changed, left, top, right, bottom);
300         }
301     }
302 
303     @Override
draw(Canvas canvas)304     public void draw(Canvas canvas) {
305         try (TraceEvent e = TraceEvent.scoped("ToolbarLayout.draw")) {
306             super.draw(canvas);
307         }
308     }
309 
310     /**
311      * Quick getter for LayoutParams for a View inside a FrameLayout.
312      * @param view {@link View} to fetch the layout params for.
313      * @return {@link LayoutParams} the given {@link View} is currently using.
314      */
getFrameLayoutParams(View view)315     FrameLayout.LayoutParams getFrameLayoutParams(View view) {
316         return ((FrameLayout.LayoutParams) view.getLayoutParams());
317     }
318 
319     /**
320      *  This function handles native dependent initialization for this class.
321      */
onNativeLibraryReady()322     protected void onNativeLibraryReady() {
323         mNativeLibraryReady = true;
324         if (mProgressBar.getParent() != null) mProgressBar.initializeAnimation();
325     }
326 
327     @Override
onAttachedToWindow()328     protected void onAttachedToWindow() {
329         super.onAttachedToWindow();
330         // TODO(crbug.com/1021877): lazy initialize progress bar.
331         // Posting adding progress bar can prevent parent view group from using a stale children
332         // count, which can cause a crash in rare cases.
333         post(this::addProgressBarToHierarchy);
334     }
335 
336     /**
337      * @return The view containing the menu button and menu button badge.
338      */
getMenuButtonCoordinator()339     MenuButtonCoordinator getMenuButtonCoordinator() {
340         return mMenuButtonCoordinator;
341     }
342 
343     @VisibleForTesting
setMenuButtonCoordinatorForTesting(MenuButtonCoordinator menuButtonCoordinator)344     void setMenuButtonCoordinatorForTesting(MenuButtonCoordinator menuButtonCoordinator) {
345         mMenuButtonCoordinator = menuButtonCoordinator;
346     }
347 
348     /**
349      * @return The {@link ProgressBar} this layout uses.
350      */
351     @Nullable
getProgressBar()352     protected ToolbarProgressBar getProgressBar() {
353         return mProgressBar;
354     }
355 
getPositionRelativeToContainer(View containerView, int[] position)356     void getPositionRelativeToContainer(View containerView, int[] position) {
357         ViewUtils.getRelativeDrawPosition(containerView, this, position);
358     }
359 
360     /**
361      * @return The helper for menu button UI interactions.
362      */
getMenuButtonHelper()363     AppMenuButtonHelper getMenuButtonHelper() {
364         return mAppMenuButtonHelper;
365     }
366 
367     /**
368      * @return Whether or not the native library is loaded and ready.
369      */
isNativeLibraryReady()370     boolean isNativeLibraryReady() {
371         return mNativeLibraryReady;
372     }
373 
374     @Override
onDraw(Canvas canvas)375     protected void onDraw(Canvas canvas) {
376         super.onDraw(canvas);
377         recordFirstDrawTime();
378     }
379 
380     /**
381      * Add the toolbar's progress bar to the view hierarchy.
382      */
addProgressBarToHierarchy()383     void addProgressBarToHierarchy() {
384         ViewGroup controlContainer = (ViewGroup) getRootView().findViewById(R.id.control_container);
385         int progressBarPosition =
386                 UiUtils.insertAfter(controlContainer, mProgressBar, (View) getParent());
387         assert progressBarPosition >= 0;
388         mProgressBar.setProgressBarContainer(controlContainer);
389     }
390 
391     /**
392      * @return The provider for toolbar related data.
393      */
getToolbarDataProvider()394     public ToolbarDataProvider getToolbarDataProvider() {
395         return mToolbarDataProvider;
396     }
397 
398     /**
399      * Sets the {@link Invalidator} that will be called when the toolbar attempts to invalidate the
400      * drawing surface.  This will give the object that registers as the host for the
401      * {@link Invalidator} a chance to defer the actual invalidate to sync drawing.
402      * @param invalidator An {@link Invalidator} instance.
403      */
setInvalidatorCallback(Callback<Runnable> invalidator)404     void setInvalidatorCallback(Callback<Runnable> invalidator) {
405         mInvalidator = invalidator;
406     }
407 
408     /**
409      * Triggers a paint but allows the {@link Invalidator} set by
410      * {@link #setPaintInvalidator(Invalidator)} to decide when to actually invalidate.
411      * @param client A {@link Invalidator.Client} instance that wants to be invalidated.
412      */
triggerPaintInvalidate(Runnable clientInvalidator)413     protected void triggerPaintInvalidate(Runnable clientInvalidator) {
414         mInvalidator.onResult(clientInvalidator);
415     }
416 
417     /**
418      * Gives inheriting classes the chance to respond to
419      * {@link FindToolbar} state changes.
420      * @param showing Whether or not the {@code FindToolbar} will be showing.
421      */
handleFindLocationBarStateChange(boolean showing)422     void handleFindLocationBarStateChange(boolean showing) {
423         mFindInPageToolbarShowing = showing;
424     }
425 
426     /**
427      * Sets the OnClickListener that will be notified when the TabSwitcher button is pressed.
428      * @param listener The callback that will be notified when the TabSwitcher button is pressed.
429      */
setOnTabSwitcherClickHandler(OnClickListener listener)430     void setOnTabSwitcherClickHandler(OnClickListener listener) {}
431 
432     /**
433      * Sets the OnLongClickListener that will be notified when the TabSwitcher button is long
434      *         pressed.
435      * @param listener The callback that will be notified when the TabSwitcher button is long
436      *         pressed.
437      */
setOnTabSwitcherLongClickHandler(OnLongClickListener listener)438     void setOnTabSwitcherLongClickHandler(OnLongClickListener listener) {}
439 
440     /**
441      * Sets the OnClickListener that will be notified when the bookmark button is pressed.
442      * @param listener The callback that will be notified when the bookmark button is pressed.
443      */
setBookmarkClickHandler(OnClickListener listener)444     void setBookmarkClickHandler(OnClickListener listener) {}
445 
446     /**
447      * Sets the OnClickListener to notify when the close button is pressed in a custom tab.
448      * @param listener The callback that will be notified when the close button is pressed.
449      */
setCustomTabCloseClickHandler(OnClickListener listener)450     protected void setCustomTabCloseClickHandler(OnClickListener listener) {}
451 
452     /**
453      * Sets whether the urlbar should be hidden on first page load.
454      */
setUrlBarHidden(boolean hide)455     protected void setUrlBarHidden(boolean hide) {}
456 
457     /**
458      * @return The name of the publisher of the content if it can be reliably extracted, or null
459      *         otherwise.
460      */
461     @Nullable
getContentPublisher()462     protected String getContentPublisher() {
463         return null;
464     }
465 
466     /**
467      * Tells the Toolbar to update what buttons it is currently displaying.
468      */
updateButtonVisibility()469     void updateButtonVisibility() {}
470 
471     /**
472      * Gives inheriting classes the chance to update the visibility of the
473      * back button.
474      * @param canGoBack Whether or not the current tab has any history to go back to.
475      */
updateBackButtonVisibility(boolean canGoBack)476     void updateBackButtonVisibility(boolean canGoBack) {}
477 
478     /**
479      * Gives inheriting classes the chance to update the visibility of the
480      * forward button.
481      * @param canGoForward Whether or not the current tab has any history to go forward to.
482      */
updateForwardButtonVisibility(boolean canGoForward)483     void updateForwardButtonVisibility(boolean canGoForward) {}
484 
485     /**
486      * Gives inheriting classes the chance to update the visibility of the
487      * reload button.
488      * @param isReloading Whether or not the current tab is loading.
489      */
updateReloadButtonVisibility(boolean isReloading)490     void updateReloadButtonVisibility(boolean isReloading) {}
491 
492     /**
493      * Gives inheriting classes the chance to update the visual status of the
494      * bookmark button.
495      * @param isBookmarked Whether or not the current tab is already bookmarked.
496      * @param editingAllowed Whether or not bookmarks can be modified (added, edited, or removed).
497      */
updateBookmarkButton(boolean isBookmarked, boolean editingAllowed)498     void updateBookmarkButton(boolean isBookmarked, boolean editingAllowed) {}
499 
500     /**
501      * Gives inheriting classes the chance to respond to accessibility state changes.
502      * @param enabled Whether or not accessibility is enabled.
503      */
onAccessibilityStatusChanged(boolean enabled)504     void onAccessibilityStatusChanged(boolean enabled) {}
505 
506     /**
507      * Gives inheriting classes the chance to do the necessary UI operations after Chrome is
508      * restored to a previously saved state.
509      */
onStateRestored()510     void onStateRestored() {}
511 
512     /**
513      * Gives inheriting classes the chance to update home button UI if home button preference is
514      * changed.
515      * @param homeButtonEnabled Whether or not home button is enabled in preference.
516      */
onHomeButtonUpdate(boolean homeButtonEnabled)517     void onHomeButtonUpdate(boolean homeButtonEnabled) {}
518 
519     /**
520      * Triggered when the current tab or model has changed.
521      * <p>
522      * As there are cases where you can select a model with no tabs (i.e. having incognito
523      * tabs but no normal tabs will still allow you to select the normal model), this should
524      * not guarantee that the model's current tab is non-null.
525      */
onTabOrModelChanged()526     void onTabOrModelChanged() {
527         mTabOrModelChangeRunnable.run();
528         getLocationBar().updateMicButtonState();
529     }
530 
531     /**
532      * For extending classes to override and carry out the changes related with the primary color
533      * for the current tab changing.
534      */
onPrimaryColorChanged(boolean shouldAnimate)535     protected void onPrimaryColorChanged(boolean shouldAnimate) {}
536 
537     /**
538      * Sets the icon drawable that the close button in the toolbar (if any) should show, or hides
539      * it if {@code drawable} is {@code null}.
540      */
setCloseButtonImageResource(@ullable Drawable drawable)541     protected void setCloseButtonImageResource(@Nullable Drawable drawable) {}
542 
543     /**
544      * Adds a custom action button to the toolbar layout, if it is supported.
545      * @param drawable The icon for the button.
546      * @param description The content description for the button.
547      * @param listener The {@link OnClickListener} to use for clicks to the button.
548      */
addCustomActionButton( Drawable drawable, String description, OnClickListener listener)549     protected void addCustomActionButton(
550             Drawable drawable, String description, OnClickListener listener) {
551         // This method should only be called for subclasses that override it.
552         assert false;
553     }
554 
555     /**
556      * Updates the visual appearance of a custom action button in the toolbar layout,
557      * if it is supported.
558      * @param index The index of the button.
559      * @param drawable The icon for the button.
560      * @param description The content description for the button.
561      */
updateCustomActionButton(int index, Drawable drawable, String description)562     protected void updateCustomActionButton(int index, Drawable drawable, String description) {
563         // This method should only be called for subclasses that override it.
564         assert false;
565     }
566 
567     /**
568      * @return The height of the tab strip. Return 0 for toolbars that do not have a tabstrip.
569      */
getTabStripHeight()570     protected int getTabStripHeight() {
571         return getResources().getDimensionPixelSize(R.dimen.tab_strip_height);
572     }
573 
574     /**
575      * Triggered when the content view for the specified tab has changed.
576      */
onTabContentViewChanged()577     void onTabContentViewChanged() {
578         mTabOrModelChangeRunnable.run();
579     }
580 
isReadyForTextureCapture()581     boolean isReadyForTextureCapture() {
582         return true;
583     }
584 
setForceTextureCapture(boolean forceTextureCapture)585     boolean setForceTextureCapture(boolean forceTextureCapture) {
586         return false;
587     }
588 
setLayoutUpdater(Runnable layoutUpdater)589     void setLayoutUpdater(Runnable layoutUpdater) {}
590 
591     /**
592      * @param attached Whether or not the web content is attached to the view heirarchy.
593      */
setContentAttached(boolean attached)594     void setContentAttached(boolean attached) {}
595 
596     /**
597      * Called when tab switcher mode is entered or exited.
598      * @param inTabSwitcherMode Whether or not tab switcher mode is being shown or hidden.
599      * @param showToolbar    Whether or not to show the normal toolbar while animating.
600      * @param delayAnimation Whether or not to delay the animation until after the transition has
601      *                       finished (which can be detected by a call to
602      *                       {@link #onTabSwitcherTransitionFinished()}).
603      */
setTabSwitcherMode(boolean inTabSwitcherMode, boolean showToolbar, boolean delayAnimation, MenuButtonCoordinator menuButtonCoordinator)604     void setTabSwitcherMode(boolean inTabSwitcherMode, boolean showToolbar, boolean delayAnimation,
605             MenuButtonCoordinator menuButtonCoordinator) {}
606 
607     /**
608      * Gives inheriting classes the chance to update their state when the TabSwitcher transition has
609      * finished.
610      */
onTabSwitcherTransitionFinished()611     void onTabSwitcherTransitionFinished() {}
612 
613     /**
614      * Gives inheriting classes the chance to observe tab count changes.
615      * @param tabCountProvider The {@link TabCountProvider} subclasses can observe.
616      */
setTabCountProvider(TabCountProvider tabCountProvider)617     void setTabCountProvider(TabCountProvider tabCountProvider) {}
618 
619     /**
620      * Gives inheriting classes the chance to update themselves based on default search engine
621      * changes.
622      */
onDefaultSearchEngineChanged()623     void onDefaultSearchEngineChanged() {}
624 
625     @Override
onGenericMotionEvent(MotionEvent event)626     public boolean onGenericMotionEvent(MotionEvent event) {
627         // Consumes mouse button events on toolbar so they don't get leaked to content layer.
628         // See https://crbug.com/740855.
629         if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
630                 && event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
631             int action = event.getActionMasked();
632             if (action == MotionEvent.ACTION_BUTTON_PRESS
633                     || action == MotionEvent.ACTION_BUTTON_RELEASE) {
634                 return true;
635             }
636         }
637         return super.onGenericMotionEvent(event);
638     }
639 
getLocationBarContentRect(Rect outRect)640     void getLocationBarContentRect(Rect outRect) {
641         View container = getLocationBar().getContainerView();
642         outRect.set(container.getPaddingLeft(), container.getPaddingTop(),
643                 container.getWidth() - container.getPaddingRight(),
644                 container.getHeight() - container.getPaddingBottom());
645         ViewUtils.getRelativeDrawPosition(this, getLocationBar().getContainerView(), mTempPosition);
646         outRect.offset(mTempPosition[0], mTempPosition[1]);
647     }
648 
setTextureCaptureMode(boolean textureMode)649     void setTextureCaptureMode(boolean textureMode) {}
650 
shouldIgnoreSwipeGesture()651     boolean shouldIgnoreSwipeGesture() {
652         if (mUrlHasFocus || mFindInPageToolbarShowing) return true;
653         return mAppMenuButtonHelper != null && mAppMenuButtonHelper.isAppMenuActive();
654     }
655 
656     /**
657      * @return Whether or not the url bar has focus.
658      */
urlHasFocus()659     boolean urlHasFocus() {
660         return mUrlHasFocus;
661     }
662 
663     /**
664      * Triggered when the URL input field has gained or lost focus.
665      * @param hasFocus Whether the URL field has gained focus.
666      */
onUrlFocusChange(boolean hasFocus)667     void onUrlFocusChange(boolean hasFocus) {
668         mUrlHasFocus = hasFocus;
669     }
670 
671     /**
672      * Keeps track of the first time the toolbar is drawn.
673      */
recordFirstDrawTime()674     private void recordFirstDrawTime() {
675         if (mFirstDrawTimeMs == 0) mFirstDrawTimeMs = SystemClock.elapsedRealtime();
676     }
677 
678     /**
679      * Returns the elapsed realtime in ms of the time at which first draw for the toolbar occurred.
680      */
getFirstDrawTime()681     long getFirstDrawTime() {
682         return mFirstDrawTimeMs;
683     }
684 
685     /**
686      * Notified when a navigation to a different page has occurred.
687      */
onNavigatedToDifferentPage()688     protected void onNavigatedToDifferentPage() {}
689 
690     /**
691      * Starts load progress.
692      */
startLoadProgress()693     void startLoadProgress() {
694         mProgressBar.start();
695     }
696 
697     /**
698      * Sets load progress.
699      * @param progress The load progress between 0 and 1.
700      */
setLoadProgress(float progress)701     void setLoadProgress(float progress) {
702         mProgressBar.setProgress(progress);
703     }
704 
705     /**
706      * Finishes load progress.
707      * @param delayed Whether hiding progress bar should be delayed to give enough time for user to
708      *                        recognize the last state.
709      */
finishLoadProgress(boolean delayed)710     void finishLoadProgress(boolean delayed) {
711         mProgressBar.finish(delayed);
712     }
713 
714     /**
715      * @return True if the progress bar is started.
716      */
isProgressStarted()717     boolean isProgressStarted() {
718         return mProgressBar.isStarted();
719     }
720 
721     /**
722      * Finish any toolbar animations.
723      */
finishAnimations()724     void finishAnimations() {}
725 
726     /**
727      * @return The current View showing in the Tab.
728      */
getCurrentTabView()729     View getCurrentTabView() {
730         Tab tab = mToolbarDataProvider.getTab();
731         if (tab != null) {
732             return tab.getView();
733         }
734         return null;
735     }
736 
737     /**
738      * @return Whether or not the toolbar is incognito.
739      */
isIncognito()740     protected boolean isIncognito() {
741         return mToolbarDataProvider.isIncognito();
742     }
743 
744     /**
745      * @return {@link LocationBar} object this {@link ToolbarLayout} contains.
746      */
747     @VisibleForTesting
getLocationBar()748     public abstract LocationBar getLocationBar();
749 
750     /**
751      * Navigates the current Tab back.
752      * @return Whether or not the current Tab did go back.
753      */
back()754     boolean back() {
755         maybeUnfocusUrlBar();
756         return mToolbarTabController != null && mToolbarTabController.back();
757     }
758 
759     /**
760      * Navigates the current Tab forward.
761      * @return Whether or not the current Tab did go forward.
762      */
forward()763     boolean forward() {
764         maybeUnfocusUrlBar();
765         return mToolbarTabController != null ? mToolbarTabController.forward() : false;
766     }
767 
768     /**
769      * If the page is currently loading, this will trigger the tab to stop.  If the page is fully
770      * loaded, this will trigger a refresh.
771      *
772      * <p>The buttons of the toolbar will be updated as a result of making this call.
773      */
stopOrReloadCurrentTab()774     void stopOrReloadCurrentTab() {
775         maybeUnfocusUrlBar();
776         if (mToolbarTabController != null) mToolbarTabController.stopOrReloadCurrentTab();
777     }
778 
779     /**
780      * Opens hompage in the current tab.
781      */
openHomepage()782     void openHomepage() {
783         maybeUnfocusUrlBar();
784         if (mToolbarTabController != null) mToolbarTabController.openHomepage();
785     }
786 
maybeUnfocusUrlBar()787     private void maybeUnfocusUrlBar() {
788         if (getLocationBar() != null && getLocationBar().getFakeboxDelegate() != null) {
789             getLocationBar().getFakeboxDelegate().setUrlBarFocus(
790                     false, null, OmniboxFocusReason.UNFOCUS);
791         }
792     }
793 
794     /**
795      * Update the optional toolbar button, showing it if currently hidden.
796      * @param buttonData Display data for the button, e.g. the Drawable and content description.
797      */
updateOptionalButton(ButtonData buttonData)798     void updateOptionalButton(ButtonData buttonData) {}
799 
800     /**
801      * Hide the optional toolbar button.
802      */
hideOptionalButton()803     void hideOptionalButton() {}
804 
805     /**
806      * @return Optional button view.
807      */
808     @VisibleForTesting
getOptionalButtonView()809     public View getOptionalButtonView() {
810         return null;
811     }
812 
813     /**
814      * Sets the current TabModelSelector so the toolbar can pass it into buttons that need access to
815      * it.
816      */
setTabModelSelector(TabModelSelector selector)817     void setTabModelSelector(TabModelSelector selector) {}
818 
819     /**
820      * @return {@link HomeButton} this {@link ToolbarLayout} contains.
821      */
getHomeButton()822     public HomeButton getHomeButton() {
823         return null;
824     }
825 }
826