/** Called when the orientation of the activity has changed. */
 public void onOrientationChange() {
   mContextualMenuBar.showControlsOnOrientationChange();
 }
  /**
   * Creates a ToolbarManager object.
   *
   * @param controlContainer The container of the toolbar.
   * @param menuHandler The handler for interacting with the menu.
   */
  public ToolbarManager(
      final ChromeActivity activity,
      ToolbarControlContainer controlContainer,
      final AppMenuHandler menuHandler,
      final ChromeAppMenuPropertiesDelegate appMenuPropertiesDelegate,
      Invalidator invalidator) {
    mActionBarDelegate =
        new ContextualMenuBar.ActionBarDelegate() {
          @Override
          public void setControlTopMargin(int margin) {
            FrameLayout.LayoutParams lp =
                (FrameLayout.LayoutParams) mControlContainer.getLayoutParams();
            lp.topMargin = margin;
            mControlContainer.setLayoutParams(lp);
          }

          @Override
          public int getControlTopMargin() {
            FrameLayout.LayoutParams lp =
                (FrameLayout.LayoutParams) mControlContainer.getLayoutParams();
            return lp.topMargin;
          }

          @Override
          public ActionBar getSupportActionBar() {
            return activity.getSupportActionBar();
          }

          @Override
          public void setActionBarBackgroundVisibility(boolean visible) {
            int visibility = visible ? View.VISIBLE : View.GONE;
            activity.findViewById(R.id.action_bar_black_background).setVisibility(visibility);
            // TODO(tedchoc): Add support for changing the color based on the brand color.
          }
        };

    mToolbarModel = new ToolbarModelImpl();
    mControlContainer = controlContainer;
    assert mControlContainer != null;

    mToolbar = (ToolbarLayout) controlContainer.findViewById(R.id.toolbar);

    mToolbar.setPaintInvalidator(invalidator);

    mContextualMenuBar = new ContextualMenuBar(activity, mActionBarDelegate);
    mContextualMenuBar.setCustomSelectionActionModeCallback(
        new CustomSelectionActionModeCallback());
    mContextualMenuBar.setTabStripHeight(mToolbar.getTabStripHeight());

    MenuDelegatePhone menuDelegate =
        new MenuDelegatePhone() {
          @Override
          public void updateReloadButtonState(boolean isLoading) {
            if (appMenuPropertiesDelegate != null) {
              appMenuPropertiesDelegate.loadingStateChanged(isLoading);
              menuHandler.menuItemContentChanged(R.id.icon_row_menu_id);
            }
          }
        };
    setMenuDelegatePhone(menuDelegate);

    mLocationBar = mToolbar.getLocationBar();
    mLocationBar.setToolbarDataProvider(mToolbarModel);
    mLocationBar.setUrlFocusChangeListener(this);
    mLocationBar.setDefaultTextEditActionModeCallback(
        mContextualMenuBar.getCustomSelectionActionModeCallback());
    mLocationBar.initializeControls(
        new WindowDelegate(activity.getWindow()),
        mContextualMenuBar.getActionBarDelegate(),
        activity.getWindowAndroid());
    mLocationBar.setIgnoreURLBarModification(false);

    setMenuHandler(menuHandler);
    mToolbar.initialize(mToolbarModel, this, mAppMenuButtonHelper);

    mHomepageStateListener =
        new HomepageStateListener() {
          @Override
          public void onHomepageStateUpdated() {
            mToolbar.onHomeButtonUpdate(HomepageManager.isHomepageEnabled(mToolbar.getContext()));
          }
        };
    HomepageManager.getInstance(mToolbar.getContext()).addListener(mHomepageStateListener);

    mTabModelSelectorObserver =
        new EmptyTabModelSelectorObserver() {
          @Override
          public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
            refreshSelectedTab();
            updateTabCount();
            mControlContainer.invalidateBitmap();
          }

          @Override
          public void onTabStateInitialized() {
            mTabRestoreCompleted = true;
            handleTabRestoreCompleted();
          }
        };

    mTabModelObserver =
        new EmptyTabModelObserver() {
          @Override
          public void didAddTab(Tab tab, TabLaunchType type) {
            updateTabCount();
          }

          @Override
          public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
            mPreselectedTabId = Tab.INVALID_TAB_ID;
            refreshSelectedTab();
          }

          @Override
          public void tabClosureUndone(Tab tab) {
            updateTabCount();
            refreshSelectedTab();
          }

          @Override
          public void didCloseTab(Tab tab) {
            updateTabCount();
            refreshSelectedTab();
          }

          @Override
          public void tabPendingClosure(Tab tab) {
            updateTabCount();
            refreshSelectedTab();
          }

          @Override
          public void allTabsPendingClosure(List<Integer> tabIds) {
            updateTabCount();
            refreshSelectedTab();
          }
        };

    mTabObserver =
        new EmptyTabObserver() {
          @Override
          public void onSSLStateUpdated(Tab tab) {
            super.onSSLStateUpdated(tab);
            assert tab == mToolbarModel.getTab();
            mLocationBar.updateSecurityIcon(tab.getSecurityLevel());
          }

          @Override
          public void onWebContentsInstantSupportDisabled() {
            mLocationBar.setUrlToPageUrl();
          }

          @Override
          public void onDidNavigateMainFrame(
              Tab tab,
              String url,
              String baseUrl,
              boolean isNavigationToDifferentPage,
              boolean isFragmentNavigation,
              int statusCode) {
            if (isNavigationToDifferentPage) {
              mToolbar.onNavigatedToDifferentPage();
            }
          }

          @Override
          public void onPageLoadStarted(Tab tab, String url) {
            updateButtonStatus();
            updateTabLoadingState(true, true);
          }

          @Override
          public void onPageLoadFinished(Tab tab) {
            ToolbarManager.this.onPageLoadFinished();
          }

          @Override
          public void onPageLoadFailed(Tab tab, int errorCode) {
            ToolbarManager.this.onPageLoadFailed();
          }

          @Override
          public void onTitleUpdated(Tab tab) {
            mLocationBar.setTitleToPageTitle();
          }

          @Override
          public void onUrlUpdated(Tab tab) {
            // Update the SSL security state as a result of this notification as it will
            // sometimes be the only update we receive.
            updateTabLoadingState(false, true);

            // A URL update is a decent enough indicator that the toolbar widget is in
            // a stable state to capture its bitmap for use in fullscreen.
            mControlContainer.setReadyForBitmapCapture(true);
          }

          @Override
          public void onCrash(Tab tab, boolean sadTabShown) {
            onTabCrash();
          }

          @Override
          public void onLoadProgressChanged(Tab tab, int progress) {
            updateLoadProgress(progress);
          }

          @Override
          public void onContentChanged(Tab tab) {
            mToolbar.onTabContentViewChanged();
          }

          @Override
          public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) {
            if (!didStartLoad) return;

            ChromeTab chromeTab = ChromeTab.fromTab(tab);
            if (!chromeTab.getBackgroundContentViewHelper().isPageSwappingInProgress()
                && didFinishLoad) {
              mLoadProgressSimulator.start();
            }
          }

          @Override
          public void onDidStartNavigationToPendingEntry(Tab tab, String url) {
            // Update URL as soon as it becomes available when it's a new tab.
            // But we want to update only when it's a new tab. So we check whether the current
            // navigation entry is initial, meaning whether it has the same target URL as the
            // initial URL of the tab.
            WebContents webContents = tab.getWebContents();
            if (webContents == null) return;
            NavigationController navigationController = webContents.getNavigationController();
            if (navigationController == null) return;
            if (navigationController.isInitialNavigation()) {
              mLocationBar.setUrlToPageUrl();
            }
          }

          @Override
          public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {
            NewTabPage ntp = mToolbarModel.getNewTabPageForCurrentTab();
            if (ntp == null) return;
            if (!NewTabPage.isNTPUrl(params.getUrl())
                && loadType != TabLoadStatus.PAGE_LOAD_FAILED) {
              ntp.setUrlFocusAnimationsDisabled(true);
              mToolbar.onTabOrModelChanged();
            }
          }

          @Override
          public void onDidFailLoad(
              Tab tab,
              boolean isProvisionalLoad,
              boolean isMainFrame,
              int errorCode,
              String description,
              String failingUrl) {
            NewTabPage ntp = mToolbarModel.getNewTabPageForCurrentTab();
            if (ntp == null) return;
            if (isProvisionalLoad && isMainFrame) {
              ntp.setUrlFocusAnimationsDisabled(false);
              mToolbar.onTabOrModelChanged();
            }
          }

          @Override
          public void onContextualActionBarVisibilityChanged(Tab tab, boolean visible) {
            if (visible) RecordUserAction.record("MobileActionBarShown");
            ActionBar actionBar = mActionBarDelegate.getSupportActionBar();
            if (!visible && actionBar != null) actionBar.hide();
            if (DeviceFormFactor.isTablet(activity)) {
              if (visible) {
                mContextualMenuBar.showControls();
              } else {
                mContextualMenuBar.hideControls();
              }
            }
          }
        };

    mBookmarksObserver =
        new BookmarksBridge.BookmarkModelObserver() {
          @Override
          public void bookmarkModelChanged() {
            updateBookmarkButtonStatus();
          }
        };

    mFindToolbarObserver =
        new FindToolbarObserver() {
          @Override
          public void onFindToolbarShown() {
            mToolbar.handleFindToolbarStateChange(true);
            if (mFullscreenManager != null) {
              mFullscreenFindInPageToken =
                  mFullscreenManager.showControlsPersistentAndClearOldToken(
                      mFullscreenFindInPageToken);
            }
          }

          @Override
          public void onFindToolbarHidden() {
            mToolbar.handleFindToolbarStateChange(false);
            if (mFullscreenManager != null) {
              mFullscreenManager.hideControlsPersistent(mFullscreenFindInPageToken);
              mFullscreenFindInPageToken = FullscreenManager.INVALID_TOKEN;
            }
          }
        };

    mOverviewModeObserver =
        new EmptyOverviewModeObserver() {
          @Override
          public void onOverviewModeStartedShowing(boolean showToolbar) {
            mToolbar.setTabSwitcherMode(true, showToolbar, false);
            updateButtonStatus();
          }

          @Override
          public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
            mToolbar.setTabSwitcherMode(false, showToolbar, delayAnimation);
            updateButtonStatus();
          }

          @Override
          public void onOverviewModeFinishedHiding() {
            mToolbar.onTabSwitcherTransitionFinished();
          }
        };

    mSceneChangeObserver =
        new SceneChangeObserver() {
          @Override
          public void onTabSelectionHinted(int tabId) {
            mPreselectedTabId = tabId;
            refreshSelectedTab();
          }

          @Override
          public void onSceneChange(Layout layout) {
            mToolbar.setContentAttached(layout.shouldDisplayContentOverlay());
          }
        };

    mLoadProgressSimulator = new LoadProgressSimulator(this);
  }