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