OLD | NEW |
(Empty) | |
| 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; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.os.Handler; |
| 9 import android.os.Looper; |
| 10 import android.os.Message; |
| 11 import android.text.TextUtils; |
| 12 import android.view.View; |
| 13 import android.view.View.OnAttachStateChangeListener; |
| 14 |
| 15 import com.google.android.apps.chrome.R; |
| 16 |
| 17 import org.chromium.base.metrics.RecordUserAction; |
| 18 import org.chromium.chrome.browser.BookmarksBridge; |
| 19 import org.chromium.chrome.browser.ChromeBrowserProviderClient; |
| 20 import org.chromium.chrome.browser.CustomSelectionActionModeCallback; |
| 21 import org.chromium.chrome.browser.EmptyTabObserver; |
| 22 import org.chromium.chrome.browser.Tab; |
| 23 import org.chromium.chrome.browser.TabLoadStatus; |
| 24 import org.chromium.chrome.browser.TabObserver; |
| 25 import org.chromium.chrome.browser.UrlConstants; |
| 26 import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper; |
| 27 import org.chromium.chrome.browser.appmenu.AppMenuHandler; |
| 28 import org.chromium.chrome.browser.appmenu.AppMenuObserver; |
| 29 import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; |
| 30 import org.chromium.chrome.browser.compositor.layouts.Layout; |
| 31 import org.chromium.chrome.browser.compositor.layouts.LayoutManager; |
| 32 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; |
| 33 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.Overv
iewModeObserver; |
| 34 import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver; |
| 35 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; |
| 36 import org.chromium.chrome.browser.fullscreen.FullscreenManager; |
| 37 import org.chromium.chrome.browser.ntp.NativePageFactory; |
| 38 import org.chromium.chrome.browser.ntp.NewTabPage; |
| 39 import org.chromium.chrome.browser.omnibox.LocationBar; |
| 40 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; |
| 41 import org.chromium.chrome.browser.partnercustomizations.HomepageManager; |
| 42 import org.chromium.chrome.browser.partnercustomizations.HomepageManager.Homepag
eStateListener; |
| 43 import org.chromium.chrome.browser.profiles.Profile; |
| 44 import org.chromium.chrome.browser.search_engines.TemplateUrlService; |
| 45 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl
; |
| 46 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl
ServiceObserver; |
| 47 import org.chromium.chrome.browser.tab.ChromeTab; |
| 48 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; |
| 49 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; |
| 50 import org.chromium.chrome.browser.tabmodel.TabModel; |
| 51 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
| 52 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; |
| 53 import org.chromium.chrome.browser.tabmodel.TabModelObserver; |
| 54 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
| 55 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; |
| 56 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager; |
| 57 import org.chromium.chrome.browser.widget.findinpage.FindToolbarObserver; |
| 58 import org.chromium.content_public.browser.LoadUrlParams; |
| 59 import org.chromium.content_public.browser.NavigationController; |
| 60 import org.chromium.content_public.browser.WebContents; |
| 61 import org.chromium.ui.base.PageTransition; |
| 62 |
| 63 import java.util.List; |
| 64 |
| 65 /** |
| 66 * Contains logic for managing the toolbar visual component. This class manages
the interactions |
| 67 * with the rest of the application to ensure the toolbar is always visually up
to date. |
| 68 */ |
| 69 class ToolbarManager implements ToolbarTabController, UrlFocusChangeListener { |
| 70 |
| 71 /** |
| 72 * Handle UI updates of menu icons. Only applicable for phones. |
| 73 */ |
| 74 public interface MenuDelegatePhone { |
| 75 |
| 76 /** |
| 77 * Called when current tab's loading status changes. |
| 78 * |
| 79 * @param isLoading Whether the current tab is loading. |
| 80 */ |
| 81 public void updateReloadButtonState(boolean isLoading); |
| 82 } |
| 83 |
| 84 /** |
| 85 * The minimum load progress that can be shown when a page is loading. This
is not 0 so that |
| 86 * it's obvious to the user that something is attempting to load. |
| 87 */ |
| 88 public static final int MINIMUM_LOAD_PROGRESS = 5; |
| 89 |
| 90 private final ToolbarLayout mToolbar; |
| 91 private final ToolbarControlContainer mControlContainer; |
| 92 |
| 93 private TabModelSelector mTabModelSelector; |
| 94 private TabModelSelectorObserver mTabModelSelectorObserver; |
| 95 private TabModelObserver mTabModelObserver; |
| 96 private MenuDelegatePhone mMenuDelegatePhone; |
| 97 private final ToolbarModelImpl mToolbarModel; |
| 98 private Profile mCurrentProfile; |
| 99 private BookmarksBridge mBookmarksBridge; |
| 100 private TemplateUrlServiceObserver mTemplateUrlObserver; |
| 101 private final LocationBar mLocationBar; |
| 102 private FindToolbarManager mFindToolbarManager; |
| 103 |
| 104 private final TabObserver mTabObserver; |
| 105 private final BookmarksBridge.BookmarkModelObserver mBookmarksObserver; |
| 106 private final FindToolbarObserver mFindToolbarObserver; |
| 107 private final OverviewModeObserver mOverviewModeObserver; |
| 108 private final SceneChangeObserver mSceneChangeObserver; |
| 109 |
| 110 private final LoadProgressSimulator mLoadProgressSimulator; |
| 111 |
| 112 private ChromeFullscreenManager mFullscreenManager; |
| 113 private int mFullscreenFocusToken = FullscreenManager.INVALID_TOKEN; |
| 114 private int mFullscreenFindInPageToken = FullscreenManager.INVALID_TOKEN; |
| 115 private int mFullscreenMenuToken = FullscreenManager.INVALID_TOKEN; |
| 116 |
| 117 private int mPreselectedTabId = Tab.INVALID_TAB_ID; |
| 118 |
| 119 private boolean mNativeLibraryReady; |
| 120 private boolean mTabRestoreCompleted; |
| 121 |
| 122 private AppMenuButtonHelper mAppMenuButtonHelper; |
| 123 |
| 124 private HomepageStateListener mHomepageStateListener; |
| 125 |
| 126 /** |
| 127 * Creates a ToolbarManager object. |
| 128 * @param controlContainer The container of the toolbar. |
| 129 * @param menuHandler The handler for interacting with the menu. |
| 130 */ |
| 131 ToolbarManager(ToolbarControlContainer controlContainer, AppMenuHandler menu
Handler) { |
| 132 mToolbarModel = new ToolbarModelImpl(); |
| 133 mControlContainer = controlContainer; |
| 134 assert mControlContainer != null; |
| 135 |
| 136 mToolbar = (ToolbarLayout) controlContainer.findViewById(R.id.toolbar); |
| 137 mLocationBar = mToolbar.getLocationBar(); |
| 138 mLocationBar.setToolbarDataProvider(mToolbarModel); |
| 139 mLocationBar.setUrlFocusChangeListener(this); |
| 140 |
| 141 setMenuHandler(menuHandler); |
| 142 mToolbar.initialize(mToolbarModel, this, mAppMenuButtonHelper); |
| 143 |
| 144 mHomepageStateListener = new HomepageStateListener() { |
| 145 @Override |
| 146 public void onHomepageStateUpdated() { |
| 147 mToolbar.onHomeButtonUpdate( |
| 148 HomepageManager.isHomepageEnabled(mToolbar.getContext())
); |
| 149 } |
| 150 }; |
| 151 HomepageManager.getInstance(mToolbar.getContext()).addListener(mHomepage
StateListener); |
| 152 |
| 153 mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() { |
| 154 @Override |
| 155 public void onTabModelSelected(TabModel newModel, TabModel oldModel)
{ |
| 156 refreshSelectedTab(); |
| 157 updateTabCount(); |
| 158 mControlContainer.invalidateBitmap(); |
| 159 } |
| 160 |
| 161 @Override |
| 162 public void onTabStateInitialized() { |
| 163 mTabRestoreCompleted = true; |
| 164 handleTabRestoreCompleted(); |
| 165 } |
| 166 }; |
| 167 |
| 168 mTabModelObserver = new EmptyTabModelObserver() { |
| 169 @Override |
| 170 public void didAddTab(Tab tab, TabLaunchType type) { |
| 171 updateTabCount(); |
| 172 } |
| 173 |
| 174 @Override |
| 175 public void didSelectTab(Tab tab, TabSelectionType type, int lastId)
{ |
| 176 mPreselectedTabId = Tab.INVALID_TAB_ID; |
| 177 refreshSelectedTab(); |
| 178 } |
| 179 |
| 180 @Override |
| 181 public void tabClosureUndone(Tab tab) { |
| 182 updateTabCount(); |
| 183 refreshSelectedTab(); |
| 184 } |
| 185 |
| 186 @Override |
| 187 public void didCloseTab(Tab tab) { |
| 188 updateTabCount(); |
| 189 refreshSelectedTab(); |
| 190 } |
| 191 |
| 192 @Override |
| 193 public void tabPendingClosure(Tab tab) { |
| 194 updateTabCount(); |
| 195 refreshSelectedTab(); |
| 196 } |
| 197 |
| 198 @Override |
| 199 public void allTabsPendingClosure(List<Integer> tabIds) { |
| 200 updateTabCount(); |
| 201 refreshSelectedTab(); |
| 202 } |
| 203 }; |
| 204 |
| 205 mTabObserver = new EmptyTabObserver() { |
| 206 @Override |
| 207 public void onSSLStateUpdated(Tab tab) { |
| 208 super.onSSLStateUpdated(tab); |
| 209 assert tab == mToolbarModel.getTab(); |
| 210 mLocationBar.updateSecurityIcon(tab.getSecurityLevel()); |
| 211 } |
| 212 |
| 213 @Override |
| 214 public void onWebContentsInstantSupportDisabled() { |
| 215 mLocationBar.setUrlToPageUrl(); |
| 216 } |
| 217 |
| 218 @Override |
| 219 public void onDidNavigateMainFrame(Tab tab, String url, String baseU
rl, |
| 220 boolean isNavigationToDifferentPage, boolean isFragmentNavig
ation, |
| 221 int statusCode) { |
| 222 if (isNavigationToDifferentPage) { |
| 223 mToolbar.onNavigatedToDifferentPage(); |
| 224 } |
| 225 } |
| 226 |
| 227 @Override |
| 228 public void onPageLoadStarted(Tab tab) { |
| 229 updateButtonStatus(); |
| 230 updateTabLoadingState(true, true); |
| 231 } |
| 232 |
| 233 @Override |
| 234 public void onPageLoadFinished(Tab tab) { |
| 235 ToolbarManager.this.onPageLoadFinished(); |
| 236 } |
| 237 |
| 238 @Override |
| 239 public void onPageLoadFailed(Tab tab, int errorCode) { |
| 240 ToolbarManager.this.onPageLoadFailed(); |
| 241 } |
| 242 |
| 243 @Override |
| 244 public void onUrlUpdated(Tab tab) { |
| 245 // Update the SSL security state as a result of this notificatio
n as it will |
| 246 // sometimes be the only update we receive. |
| 247 updateTabLoadingState(false, true); |
| 248 |
| 249 // A URL update is a decent enough indicator that the toolbar wi
dget is in |
| 250 // a stable state to capture its bitmap for use in fullscreen. |
| 251 mControlContainer.setReadyForBitmapCapture(true); |
| 252 } |
| 253 |
| 254 @Override |
| 255 public void onCrash(Tab tab, boolean sadTabShown) { |
| 256 onTabCrash(); |
| 257 } |
| 258 |
| 259 @Override |
| 260 public void onLoadProgressChanged(Tab tab, int progress) { |
| 261 updateLoadProgress(progress); |
| 262 } |
| 263 |
| 264 @Override |
| 265 public void onContentChanged(Tab tab) { |
| 266 mToolbar.onTabContentViewChanged(); |
| 267 } |
| 268 |
| 269 @Override |
| 270 public void onWebContentsSwapped(Tab tab, boolean didStartLoad, bool
ean didFinishLoad) { |
| 271 if (!didStartLoad) return; |
| 272 |
| 273 ChromeTab chromeTab = ChromeTab.fromTab(tab); |
| 274 if (!chromeTab.getBackgroundContentViewHelper().isPageSwappingIn
Progress() |
| 275 && didFinishLoad) { |
| 276 mLoadProgressSimulator.start(); |
| 277 } |
| 278 } |
| 279 |
| 280 @Override |
| 281 public void onDidStartNavigationToPendingEntry(Tab tab, String url)
{ |
| 282 // Update URL as soon as it becomes available when it's a new ta
b. |
| 283 // But we want to update only when it's a new tab. So we check w
hether the current |
| 284 // navigation entry is initial, meaning whether it has the same
target URL as the |
| 285 // initial URL of the tab. |
| 286 WebContents webContents = tab.getWebContents(); |
| 287 if (webContents == null) return; |
| 288 NavigationController navigationController = webContents.getNavig
ationController(); |
| 289 if (navigationController == null) return; |
| 290 if (navigationController.isInitialNavigation()) { |
| 291 mLocationBar.setUrlToPageUrl(); |
| 292 } |
| 293 } |
| 294 |
| 295 @Override |
| 296 public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) { |
| 297 NewTabPage ntp = mToolbarModel.getNewTabPageForCurrentTab(); |
| 298 if (ntp == null) return; |
| 299 if (!NewTabPage.isNTPUrl(params.getUrl()) |
| 300 && loadType != TabLoadStatus.PAGE_LOAD_FAILED) { |
| 301 ntp.setUrlFocusAnimationsDisabled(true); |
| 302 mToolbar.onTabOrModelChanged(); |
| 303 } |
| 304 } |
| 305 |
| 306 @Override |
| 307 public void onDidFailLoad(Tab tab, boolean isProvisionalLoad, boolea
n isMainFrame, |
| 308 int errorCode, String description, String failingUrl) { |
| 309 NewTabPage ntp = mToolbarModel.getNewTabPageForCurrentTab(); |
| 310 if (ntp == null) return; |
| 311 if (isProvisionalLoad && isMainFrame) { |
| 312 ntp.setUrlFocusAnimationsDisabled(false); |
| 313 mToolbar.onTabOrModelChanged(); |
| 314 } |
| 315 } |
| 316 }; |
| 317 |
| 318 mBookmarksObserver = new BookmarksBridge.BookmarkModelObserver() { |
| 319 @Override |
| 320 public void bookmarkModelChanged() { |
| 321 updateBookmarkButtonStatus(); |
| 322 } |
| 323 }; |
| 324 |
| 325 mFindToolbarObserver = new FindToolbarObserver() { |
| 326 @Override |
| 327 public void onFindToolbarShown() { |
| 328 mToolbar.handleFindToolbarStateChange(true); |
| 329 if (mFullscreenManager != null) { |
| 330 mFullscreenFindInPageToken = |
| 331 mFullscreenManager.showControlsPersistentAndClearOld
Token( |
| 332 mFullscreenFindInPageToken); |
| 333 } |
| 334 } |
| 335 |
| 336 @Override |
| 337 public void onFindToolbarHidden() { |
| 338 mToolbar.handleFindToolbarStateChange(false); |
| 339 if (mFullscreenManager != null) { |
| 340 mFullscreenManager.hideControlsPersistent(mFullscreenFindInP
ageToken); |
| 341 mFullscreenFindInPageToken = FullscreenManager.INVALID_TOKEN
; |
| 342 } |
| 343 } |
| 344 }; |
| 345 |
| 346 mOverviewModeObserver = new EmptyOverviewModeObserver() { |
| 347 @Override |
| 348 public void onOverviewModeStartedShowing(boolean showToolbar) { |
| 349 mToolbar.setTabSwitcherMode(true, showToolbar, false); |
| 350 updateButtonStatus(); |
| 351 } |
| 352 |
| 353 @Override |
| 354 public void onOverviewModeStartedHiding(boolean showToolbar, boolean
delayAnimation) { |
| 355 mToolbar.setTabSwitcherMode(false, showToolbar, delayAnimation); |
| 356 updateButtonStatus(); |
| 357 } |
| 358 |
| 359 @Override |
| 360 public void onOverviewModeFinishedHiding() { |
| 361 mToolbar.onTabSwitcherTransitionFinished(); |
| 362 } |
| 363 }; |
| 364 |
| 365 mSceneChangeObserver = new SceneChangeObserver() { |
| 366 @Override |
| 367 public void onTabSelectionHinted(int tabId) { |
| 368 mPreselectedTabId = tabId; |
| 369 refreshSelectedTab(); |
| 370 } |
| 371 |
| 372 @Override |
| 373 public void onSceneChange(Layout layout) { |
| 374 mToolbar.setContentAttached(layout.shouldDisplayContentOverlay()
); |
| 375 } |
| 376 }; |
| 377 |
| 378 mLoadProgressSimulator = new LoadProgressSimulator(this); |
| 379 } |
| 380 |
| 381 /** |
| 382 * Initialize the manager with the components that had native initialization
dependencies. |
| 383 * <p> |
| 384 * Calling this must occur after the native library have completely loaded. |
| 385 * |
| 386 * @param tabModelSelector The selector that handles tab management. |
| 387 * @param fullscreenManager The manager in charge of interacting with the
fullscreen feature. |
| 388 * @param findToolbarManager The manager for find in page. |
| 389 * @param overviewModeBehavior The overview mode manager. |
| 390 * @param layoutDriver A {@link LayoutManager} instance used to watc
h for scene changes. |
| 391 */ |
| 392 public void initializeWithNative(TabModelSelector tabModelSelector, |
| 393 ChromeFullscreenManager fullscreenManager, |
| 394 final FindToolbarManager findToolbarManager, |
| 395 final OverviewModeBehavior overviewModeBehavior, |
| 396 final LayoutManager layoutDriver) { |
| 397 mTabModelSelector = tabModelSelector; |
| 398 mToolbarModel.initializeWithNative(); |
| 399 mToolbar.addOnAttachStateChangeListener(new OnAttachStateChangeListener(
) { |
| 400 @Override |
| 401 public void onViewDetachedFromWindow(View v) { |
| 402 Context context = mToolbar.getContext(); |
| 403 HomepageManager.getInstance(context).removeListener(mHomepageSta
teListener); |
| 404 mTabModelSelector.removeObserver(mTabModelSelectorObserver); |
| 405 for (TabModel model : mTabModelSelector.getModels()) { |
| 406 model.removeObserver(mTabModelObserver); |
| 407 } |
| 408 if (mBookmarksBridge != null) { |
| 409 mBookmarksBridge.destroy(); |
| 410 mBookmarksBridge = null; |
| 411 } |
| 412 if (mTemplateUrlObserver != null) { |
| 413 TemplateUrlService.getInstance().removeObserver(mTemplateUrl
Observer); |
| 414 mTemplateUrlObserver = null; |
| 415 } |
| 416 |
| 417 findToolbarManager.removeObserver(mFindToolbarObserver); |
| 418 if (overviewModeBehavior != null) { |
| 419 overviewModeBehavior.removeOverviewModeObserver(mOverviewMod
eObserver); |
| 420 } |
| 421 if (layoutDriver != null) { |
| 422 layoutDriver.removeSceneChangeObserver(mSceneChangeObserver)
; |
| 423 } |
| 424 } |
| 425 |
| 426 @Override |
| 427 public void onViewAttachedToWindow(View v) { |
| 428 // As we have only just registered for notifications, any that w
ere sent prior to |
| 429 // this may have been missed. |
| 430 // Calling refreshSelectedTab in case we missed the initial sele
ction notification. |
| 431 refreshSelectedTab(); |
| 432 } |
| 433 }); |
| 434 |
| 435 mFindToolbarManager = findToolbarManager; |
| 436 |
| 437 assert fullscreenManager != null; |
| 438 mFullscreenManager = fullscreenManager; |
| 439 |
| 440 mNativeLibraryReady = false; |
| 441 |
| 442 findToolbarManager.addObserver(mFindToolbarObserver); |
| 443 if (overviewModeBehavior != null) { |
| 444 overviewModeBehavior.addOverviewModeObserver(mOverviewModeObserver); |
| 445 } |
| 446 if (layoutDriver != null) layoutDriver.addSceneChangeObserver(mSceneChan
geObserver); |
| 447 |
| 448 onNativeLibraryReady(); |
| 449 } |
| 450 |
| 451 /** |
| 452 * @return The toolbar interface that this manager handles. |
| 453 */ |
| 454 public Toolbar getToolbar() { |
| 455 return mToolbar; |
| 456 } |
| 457 |
| 458 /** |
| 459 * Called when the accessibility enabled state changes. |
| 460 * @param enabled Whether accessibility is enabled. |
| 461 */ |
| 462 public void onAccessibilityStatusChanged(boolean enabled) { |
| 463 mToolbar.onAccessibilityStatusChanged(enabled); |
| 464 } |
| 465 |
| 466 private void registerTemplateUrlObserver() { |
| 467 final TemplateUrlService templateUrlService = TemplateUrlService.getInst
ance(); |
| 468 assert mTemplateUrlObserver == null; |
| 469 mTemplateUrlObserver = new TemplateUrlServiceObserver() { |
| 470 private TemplateUrl mSearchEngine = |
| 471 templateUrlService.getDefaultSearchEngineTemplateUrl(); |
| 472 |
| 473 @Override |
| 474 public void onTemplateURLServiceChanged() { |
| 475 TemplateUrl searchEngine = templateUrlService.getDefaultSearchEn
gineTemplateUrl(); |
| 476 if ((mSearchEngine == null && searchEngine == null) |
| 477 || (mSearchEngine != null && mSearchEngine.equals(search
Engine))) { |
| 478 return; |
| 479 } |
| 480 |
| 481 mSearchEngine = searchEngine; |
| 482 mToolbar.onDefaultSearchEngineChanged(); |
| 483 } |
| 484 }; |
| 485 templateUrlService.addObserver(mTemplateUrlObserver); |
| 486 } |
| 487 |
| 488 private void onNativeLibraryReady() { |
| 489 mNativeLibraryReady = true; |
| 490 mToolbar.onNativeLibraryReady(); |
| 491 |
| 492 final TemplateUrlService templateUrlService = TemplateUrlService.getInst
ance(); |
| 493 TemplateUrlService.LoadListener mTemplateServiceLoadListener = |
| 494 new TemplateUrlService.LoadListener() { |
| 495 @Override |
| 496 public void onTemplateUrlServiceLoaded() { |
| 497 registerTemplateUrlObserver(); |
| 498 templateUrlService.unregisterLoadListener(this); |
| 499 } |
| 500 }; |
| 501 templateUrlService.registerLoadListener(mTemplateServiceLoadListener); |
| 502 if (templateUrlService.isLoaded()) { |
| 503 mTemplateServiceLoadListener.onTemplateUrlServiceLoaded(); |
| 504 } else { |
| 505 templateUrlService.load(); |
| 506 } |
| 507 |
| 508 mTabModelSelector.addObserver(mTabModelSelectorObserver); |
| 509 for (TabModel model : mTabModelSelector.getModels()) model.addObserver(m
TabModelObserver); |
| 510 |
| 511 refreshSelectedTab(); |
| 512 if (mTabModelSelector.isTabStateInitialized()) mTabRestoreCompleted = tr
ue; |
| 513 handleTabRestoreCompleted(); |
| 514 } |
| 515 |
| 516 private void handleTabRestoreCompleted() { |
| 517 if (!mTabRestoreCompleted || !mNativeLibraryReady) return; |
| 518 mToolbar.onStateRestored(); |
| 519 updateTabCount(); |
| 520 } |
| 521 |
| 522 /** |
| 523 * Sets the handler for any special case handling related with the menu butt
on. |
| 524 * @param menuHandler The handler to be used. |
| 525 */ |
| 526 private void setMenuHandler(AppMenuHandler menuHandler) { |
| 527 menuHandler.addObserver(new AppMenuObserver() { |
| 528 @Override |
| 529 public void onMenuVisibilityChanged(boolean isVisible) { |
| 530 if (mFullscreenManager == null) return; |
| 531 if (isVisible) { |
| 532 mFullscreenMenuToken = |
| 533 mFullscreenManager.showControlsPersistentAndClearOld
Token( |
| 534 mFullscreenMenuToken); |
| 535 } else { |
| 536 mFullscreenManager.hideControlsPersistent(mFullscreenMenuTok
en); |
| 537 mFullscreenMenuToken = FullscreenManager.INVALID_TOKEN; |
| 538 } |
| 539 } |
| 540 }); |
| 541 mAppMenuButtonHelper = new AppMenuButtonHelper(menuHandler); |
| 542 mAppMenuButtonHelper.setOnAppMenuShownListener(new Runnable() { |
| 543 @Override |
| 544 public void run() { |
| 545 RecordUserAction.record("MobileToolbarShowMenu"); |
| 546 } |
| 547 }); |
| 548 mLocationBar.setMenuButtonHelper(mAppMenuButtonHelper); |
| 549 } |
| 550 |
| 551 /** |
| 552 * Set the delegate that will handle updates from toolbar driven state chang
es. |
| 553 * @param menuDelegatePhone The menu delegate to be updated (only applicable
to phones). |
| 554 */ |
| 555 public void setMenuDelegatePhone(MenuDelegatePhone menuDelegatePhone) { |
| 556 mMenuDelegatePhone = menuDelegatePhone; |
| 557 } |
| 558 |
| 559 /** |
| 560 * Sets a custom ActionMode.Callback instance to the LocationBar's UrlBar.
This lets us |
| 561 * get notified when the user tries to do copy, paste, etc. on the UrlBar. |
| 562 * @param callback The ActionMode.Callback instance to be notified when sele
ction ActionMode |
| 563 * is triggered. |
| 564 */ |
| 565 public void setDefaultActionModeCallbackForTextEdit( |
| 566 CustomSelectionActionModeCallback callback) { |
| 567 mLocationBar.setDefaultTextEditActionModeCallback(callback); |
| 568 } |
| 569 |
| 570 @Override |
| 571 public boolean back() { |
| 572 Tab tab = mToolbarModel.getTab(); |
| 573 if (tab != null && tab.canGoBack()) { |
| 574 tab.goBack(); |
| 575 updateButtonStatus(); |
| 576 return true; |
| 577 } |
| 578 return false; |
| 579 } |
| 580 |
| 581 @Override |
| 582 public boolean forward() { |
| 583 Tab tab = mToolbarModel.getTab(); |
| 584 if (tab != null && tab.canGoForward()) { |
| 585 tab.goForward(); |
| 586 updateButtonStatus(); |
| 587 return true; |
| 588 } |
| 589 return false; |
| 590 } |
| 591 |
| 592 @Override |
| 593 public void stopOrReloadCurrentTab() { |
| 594 Tab currentTab = mToolbarModel.getTab(); |
| 595 if (currentTab != null) { |
| 596 if (currentTab.isLoading()) { |
| 597 currentTab.stopLoading(); |
| 598 } else { |
| 599 currentTab.reload(); |
| 600 RecordUserAction.record("MobileToolbarReload"); |
| 601 } |
| 602 } |
| 603 updateButtonStatus(); |
| 604 } |
| 605 |
| 606 @Override |
| 607 public void openHomepage() { |
| 608 Tab currentTab = mToolbarModel.getTab(); |
| 609 assert currentTab != null; |
| 610 Context context = mToolbar.getContext(); |
| 611 String homePageUrl = HomepageManager.getHomepageUri(context); |
| 612 if (TextUtils.isEmpty(homePageUrl)) { |
| 613 homePageUrl = UrlConstants.NTP_URL; |
| 614 } |
| 615 currentTab.loadUrl(new LoadUrlParams(homePageUrl, PageTransition.HOME_PA
GE)); |
| 616 } |
| 617 |
| 618 /** |
| 619 * Triggered when the URL input field has gained or lost focus. |
| 620 * @param hasFocus Whether the URL field has gained focus. |
| 621 */ |
| 622 @Override |
| 623 public void onUrlFocusChange(boolean hasFocus) { |
| 624 mToolbar.onUrlFocusChange(hasFocus); |
| 625 |
| 626 if (mFindToolbarManager != null && hasFocus) mFindToolbarManager.hideToo
lbar(); |
| 627 |
| 628 if (mFullscreenManager == null) return; |
| 629 if (hasFocus) { |
| 630 mFullscreenFocusToken = mFullscreenManager.showControlsPersistentAnd
ClearOldToken( |
| 631 mFullscreenFocusToken); |
| 632 } else { |
| 633 mFullscreenManager.hideControlsPersistent(mFullscreenFocusToken); |
| 634 mFullscreenFocusToken = FullscreenManager.INVALID_TOKEN; |
| 635 } |
| 636 } |
| 637 |
| 638 /** |
| 639 * Update the primary color used by the model to the given color. |
| 640 * @param color The primary color for the current tab. |
| 641 */ |
| 642 public void updatePrimaryColor(int color) { |
| 643 boolean colorChanged = mToolbarModel.getPrimaryColor() != color; |
| 644 if (!colorChanged) return; |
| 645 |
| 646 mToolbarModel.setPrimaryColor(color); |
| 647 mToolbar.onPrimaryColorChanged(); |
| 648 } |
| 649 |
| 650 /** |
| 651 * Updates the current number of Tabs based on the TabModel this Toolbar con
tains. |
| 652 */ |
| 653 private void updateTabCount() { |
| 654 if (!mTabRestoreCompleted) return; |
| 655 mToolbar.updateTabCountVisuals(mTabModelSelector.getCurrentModel().getCo
unt()); |
| 656 } |
| 657 |
| 658 /** |
| 659 * Updates the current button states and calls appropriate abstract visibili
ty methods, giving |
| 660 * inheriting classes the chance to update the button visuals as well. |
| 661 */ |
| 662 private void updateButtonStatus() { |
| 663 Tab currentTab = mToolbarModel.getTab(); |
| 664 boolean tabCrashed = currentTab != null && currentTab.isShowingSadTab(); |
| 665 |
| 666 mToolbar.updateBackButtonVisibility(currentTab != null && currentTab.can
GoBack()); |
| 667 mToolbar.updateForwardButtonVisibility(currentTab != null && currentTab.
canGoForward()); |
| 668 updateReloadState(tabCrashed); |
| 669 updateBookmarkButtonStatus(); |
| 670 |
| 671 mToolbar.getMenuButton().setVisibility( |
| 672 mToolbar.shouldShowMenuButton() ? View.VISIBLE : View.GONE); |
| 673 } |
| 674 |
| 675 private void updateBookmarkButtonStatus() { |
| 676 Tab currentTab = mToolbarModel.getTab(); |
| 677 boolean isBookmarked = currentTab != null |
| 678 && currentTab.getBookmarkId() != ChromeBrowserProviderClient.INV
ALID_BOOKMARK_ID; |
| 679 mToolbar.updateBookmarkButtonVisibility(isBookmarked); |
| 680 } |
| 681 |
| 682 private void updateReloadState(boolean tabCrashed) { |
| 683 Tab currentTab = mToolbarModel.getTab(); |
| 684 boolean isLoading = false; |
| 685 if (!tabCrashed) { |
| 686 isLoading = (currentTab != null && currentTab.isLoading()) || !mNati
veLibraryReady; |
| 687 } |
| 688 mToolbar.updateReloadButtonVisibility(isLoading); |
| 689 if (mMenuDelegatePhone != null) mMenuDelegatePhone.updateReloadButtonSta
te(isLoading); |
| 690 } |
| 691 |
| 692 /** |
| 693 * Triggered when the selected tab has changed. |
| 694 */ |
| 695 private void refreshSelectedTab() { |
| 696 ChromeTab tab = null; |
| 697 if (mPreselectedTabId != Tab.INVALID_TAB_ID) { |
| 698 tab = ChromeTab.fromTab(mTabModelSelector.getTabById(mPreselectedTab
Id)); |
| 699 } |
| 700 if (tab == null) tab = ChromeTab.fromTab(mTabModelSelector.getCurrentTab
()); |
| 701 |
| 702 boolean wasIncognito = mToolbarModel.isIncognito(); |
| 703 ChromeTab previousTab = ChromeTab.fromTab(mToolbarModel.getTab()); |
| 704 |
| 705 boolean isIncognito = |
| 706 tab != null ? tab.isIncognito() : mTabModelSelector.isIncognitoS
elected(); |
| 707 mToolbarModel.setTab(tab, isIncognito); |
| 708 |
| 709 updateCurrentTabDisplayStatus(); |
| 710 if (previousTab != tab || wasIncognito != isIncognito) { |
| 711 if (previousTab != tab) { |
| 712 if (previousTab != null) previousTab.removeObserver(mTabObserver
); |
| 713 if (tab != null) tab.addObserver(mTabObserver); |
| 714 } |
| 715 int defaultPrimaryColor = isIncognito |
| 716 ? mToolbar.getResources().getColor(R.color.incognito_primary
_color) |
| 717 : mToolbar.getResources().getColor(R.color.default_primary_c
olor); |
| 718 int primaryColor = (tab != null && tab.getWebContents() != null) |
| 719 ? tab.getWebContents().getThemeColor(defaultPrimaryColor) :
defaultPrimaryColor; |
| 720 updatePrimaryColor(primaryColor); |
| 721 |
| 722 mToolbar.onTabOrModelChanged(); |
| 723 |
| 724 if (tab != null && tab.getWebContents() != null |
| 725 && tab.getWebContents().isLoadingToDifferentDocument()) { |
| 726 mToolbar.onNavigatedToDifferentPage(); |
| 727 } |
| 728 } |
| 729 |
| 730 Profile profile = mTabModelSelector.getModel(isIncognito).getProfile(); |
| 731 if (mCurrentProfile != profile) { |
| 732 if (mBookmarksBridge != null) mBookmarksBridge.destroy(); |
| 733 mBookmarksBridge = new BookmarksBridge(profile); |
| 734 mBookmarksBridge.addObserver(mBookmarksObserver); |
| 735 mLocationBar.setAutocompleteProfile(profile); |
| 736 mCurrentProfile = profile; |
| 737 } |
| 738 } |
| 739 |
| 740 private void updateCurrentTabDisplayStatus() { |
| 741 Tab currentTab = mToolbarModel.getTab(); |
| 742 mLocationBar.setUrlToPageUrl(); |
| 743 if (currentTab == null) { |
| 744 updateLoadProgressInternal(0); |
| 745 updateButtonStatus(); |
| 746 return; |
| 747 } |
| 748 boolean isLoading = currentTab.isLoading(); |
| 749 updateTabLoadingState(isLoading, true); |
| 750 |
| 751 if (currentTab.getProgress() == 100 || currentTab.isShowingInterstitialP
age()) { |
| 752 // We are switching to a tab that is fully loaded. Don't set the loa
d progress to 1.0, |
| 753 // that would cause the load progress bar to show briefly. |
| 754 updateLoadProgressInternal(0); |
| 755 } else { |
| 756 updateLoadProgress(currentTab.getProgress()); |
| 757 } |
| 758 updateButtonStatus(); |
| 759 } |
| 760 |
| 761 private void onTabCrash() { |
| 762 updateTabLoadingState(false, false); |
| 763 updateLoadProgressInternal(0); |
| 764 updateButtonStatus(); |
| 765 } |
| 766 |
| 767 private void onPageLoadFinished() { |
| 768 Tab currentTab = mToolbarModel.getTab(); |
| 769 updateTabLoadingState(false, true); |
| 770 int currentProgress = currentTab.getProgress(); |
| 771 if (currentProgress != 100) { |
| 772 // If we made some progress, fast-forward to complete, otherwise jus
t dismiss any |
| 773 // MINIMUM_LOAD_PROGRESS that had been set. |
| 774 if (currentProgress > MINIMUM_LOAD_PROGRESS) { |
| 775 updateLoadProgress(100); |
| 776 } else { |
| 777 updateLoadProgressInternal(0); |
| 778 } |
| 779 } |
| 780 updateButtonStatus(); |
| 781 } |
| 782 |
| 783 private void onPageLoadFailed() { |
| 784 updateTabLoadingState(false, true); |
| 785 updateButtonStatus(); |
| 786 updateLoadProgressInternal(0); |
| 787 } |
| 788 |
| 789 private void updateTabLoadingState(boolean isLoading, boolean updateUrl) { |
| 790 Tab currentTab = mToolbarModel.getTab(); |
| 791 mLocationBar.updateLoadingState(updateUrl); |
| 792 if (isLoading) updateLoadProgress(currentTab.getProgress()); |
| 793 if (updateUrl) updateButtonStatus(); |
| 794 } |
| 795 |
| 796 private void updateLoadProgressInternal(int progress) { |
| 797 if (progress == mToolbarModel.getLoadProgress()) return; |
| 798 mToolbarModel.setLoadProgress(progress); |
| 799 mToolbar.setLoadProgress(progress); |
| 800 if (progress == 0) mLoadProgressSimulator.cancel(); |
| 801 } |
| 802 |
| 803 private void updateLoadProgress(int progress) { |
| 804 mLoadProgressSimulator.cancel(); |
| 805 progress = Math.max(progress, MINIMUM_LOAD_PROGRESS); |
| 806 Tab tab = mToolbarModel.getTab(); |
| 807 if (tab != null |
| 808 && NativePageFactory.isNativePageUrl(tab.getUrl(), tab.isIncogni
to())) { |
| 809 progress = 0; |
| 810 } |
| 811 updateLoadProgressInternal(progress); |
| 812 if (progress == 100 || progress == 0) { |
| 813 updateButtonStatus(); |
| 814 } else { |
| 815 // Update the reload state regardless or whether or not the progress
is 100. |
| 816 updateReloadState(false); |
| 817 } |
| 818 } |
| 819 |
| 820 private static class LoadProgressSimulator { |
| 821 private static final int MSG_ID_UPDATE_PROGRESS = 1; |
| 822 |
| 823 private static final int PROGRESS_INCREMENT = 10; |
| 824 private static final int PROGRESS_INCREMENT_DELAY_MS = 10; |
| 825 |
| 826 private final ToolbarManager mToolbar; |
| 827 private final Handler mHandler; |
| 828 |
| 829 private int mProgress; |
| 830 |
| 831 public LoadProgressSimulator(ToolbarManager toolbar) { |
| 832 mToolbar = toolbar; |
| 833 mHandler = new Handler(Looper.getMainLooper()) { |
| 834 @Override |
| 835 public void handleMessage(Message msg) { |
| 836 assert msg.what == MSG_ID_UPDATE_PROGRESS; |
| 837 mProgress = Math.min(100, mProgress += PROGRESS_INCREMENT); |
| 838 mToolbar.updateLoadProgressInternal(mProgress); |
| 839 |
| 840 if (mProgress >= 100) return; |
| 841 sendEmptyMessageDelayed(MSG_ID_UPDATE_PROGRESS, PROGRESS_INC
REMENT_DELAY_MS); |
| 842 } |
| 843 }; |
| 844 } |
| 845 |
| 846 /** |
| 847 * Start simulating load progress from a baseline of 0. |
| 848 */ |
| 849 public void start() { |
| 850 mProgress = 0; |
| 851 mHandler.sendEmptyMessage(MSG_ID_UPDATE_PROGRESS); |
| 852 } |
| 853 |
| 854 /** |
| 855 * Cancels simulating load progress. |
| 856 */ |
| 857 public void cancel() { |
| 858 mHandler.removeMessages(MSG_ID_UPDATE_PROGRESS); |
| 859 } |
| 860 } |
| 861 } |
OLD | NEW |