blob: bc76e1dafca42732a2d46700807c39af39b70592 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.toolbar.top;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewStub;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.CallbackController;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ThemeColorProvider;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.identity_disc.IdentityDiscController;
import org.chromium.chrome.browser.incognito.IncognitoUtils;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
import org.chromium.chrome.browser.toolbar.TabCountProvider;
import org.chromium.chrome.browser.toolbar.TabSwitcherButtonCoordinator;
import org.chromium.chrome.browser.toolbar.TabSwitcherButtonView;
import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator;
import org.chromium.chrome.browser.user_education.UserEducationHelper;
import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
/**
* The controller for the StartSurfaceToolbar. This class handles all interactions that the
* StartSurfaceToolbar has with the outside world. Lazily creates the tab toolbar the first time
* it's needed.
*/
public class StartSurfaceToolbarCoordinator {
private final StartSurfaceToolbarMediator mToolbarMediator;
private final ViewStub mStub;
private final PropertyModel mPropertyModel;
private PropertyModelChangeProcessor mPropertyModelChangeProcessor;
private StartSurfaceToolbarView mView;
private TabModelSelector mTabModelSelector;
private IncognitoSwitchCoordinator mIncognitoSwitchCoordinator;
private TabSwitcherButtonCoordinator mTabSwitcherButtonCoordinator;
private TabSwitcherButtonView mTabSwitcherButtonView;
private TabCountProvider mTabCountProvider;
private ThemeColorProvider mThemeColorProvider;
private OnClickListener mTabSwitcherClickListener;
private OnLongClickListener mTabSwitcherLongClickListener;
private MenuButtonCoordinator mMenuButtonCoordinator;
private CallbackController mCallbackController = new CallbackController();
StartSurfaceToolbarCoordinator(ViewStub startSurfaceToolbarStub,
IdentityDiscController identityDiscController, UserEducationHelper userEducationHelper,
OneshotSupplier<OverviewModeBehavior> overviewModeBehaviorSupplier,
ThemeColorProvider provider, MenuButtonCoordinator menuButtonCoordinator) {
mStub = startSurfaceToolbarStub;
overviewModeBehaviorSupplier.onAvailable(
mCallbackController.makeCancelable(this::setOverviewModeBehavior));
mPropertyModel =
new PropertyModel.Builder(StartSurfaceToolbarProperties.ALL_KEYS)
.with(StartSurfaceToolbarProperties.INCOGNITO_SWITCHER_VISIBLE,
StartSurfaceConfiguration.START_SURFACE_SHOW_STACK_TAB_SWITCHER
.getValue()
? false
: true)
.with(StartSurfaceToolbarProperties.IN_START_SURFACE_MODE, false)
.with(StartSurfaceToolbarProperties.MENU_IS_VISIBLE, true)
.with(StartSurfaceToolbarProperties.IS_VISIBLE, true)
.build();
// START_SURFACE_HIDE_INCOGNITO_SWITCH and START_SURFACE_SHOW_STACK_TAB_SWITCHER should not
// be both true.
assert !(StartSurfaceConfiguration.START_SURFACE_HIDE_INCOGNITO_SWITCH.getValue()
&& StartSurfaceConfiguration.START_SURFACE_SHOW_STACK_TAB_SWITCHER.getValue());
mToolbarMediator = new StartSurfaceToolbarMediator(mPropertyModel, identityDiscController,
(iphCommandBuilder)
-> {
// TODO(crbug.com/865801): Replace the null check with an assert after fixing or
// removing the ShareButtonControllerTest that necessitated it.
if (mView == null) return;
userEducationHelper.requestShowIPH(
iphCommandBuilder.setAnchorView(mView.getIdentityDiscView()).build());
},
StartSurfaceConfiguration.START_SURFACE_HIDE_INCOGNITO_SWITCH.getValue(),
StartSurfaceConfiguration.START_SURFACE_SHOW_STACK_TAB_SWITCHER.getValue(),
menuButtonCoordinator);
mThemeColorProvider = provider;
mMenuButtonCoordinator = menuButtonCoordinator;
}
/**
* Cleans up any code and removes observers as necessary.
*/
void destroy() {
mToolbarMediator.destroy();
if (mIncognitoSwitchCoordinator != null) mIncognitoSwitchCoordinator.destroy();
if (mTabSwitcherButtonCoordinator != null) mTabSwitcherButtonCoordinator.destroy();
if (mMenuButtonCoordinator != null) {
mMenuButtonCoordinator.destroy();
mMenuButtonCoordinator = null;
}
if (mCallbackController != null) {
mCallbackController.destroy();
mCallbackController = null;
}
mTabSwitcherButtonCoordinator = null;
mTabSwitcherButtonView = null;
mTabCountProvider = null;
mThemeColorProvider = null;
mTabSwitcherClickListener = null;
mTabSwitcherLongClickListener = null;
}
/**
* Sets the OnClickListener that will be notified when the New Tab button is pressed.
* @param listener The callback that will be notified when the New Tab button is pressed.
*/
void setOnNewTabClickHandler(View.OnClickListener listener) {
mToolbarMediator.setOnNewTabClickHandler(listener);
}
/**
* Sets the current {@Link TabModelSelector} so the toolbar can pass it into buttons that need
* access to it.
*/
void setTabModelSelector(TabModelSelector selector) {
mTabModelSelector = selector;
mToolbarMediator.setTabModelSelector(selector);
}
/**
* Called when Start Surface mode is entered or exited.
* @param inStartSurfaceMode Whether or not start surface mode should be shown or hidden.
*/
void setStartSurfaceMode(boolean inStartSurfaceMode) {
if (!isInflated()) {
inflate();
}
mToolbarMediator.setStartSurfaceMode(inStartSurfaceMode);
}
/**
* @param provider The provider used to determine incognito state.
*/
void setIncognitoStateProvider(IncognitoStateProvider provider) {
mToolbarMediator.setIncognitoStateProvider(provider);
}
/**
* Called to set the visibility in Start Surface mode.
* @param shouldShowStartSurfaceToolbar whether the toolbar should be visible.
*/
void setStartSurfaceToolbarVisibility(boolean shouldShowStartSurfaceToolbar) {
mToolbarMediator.setStartSurfaceToolbarVisibility(shouldShowStartSurfaceToolbar);
}
/**
* Called when accessibility status changes.
* @param enabled whether accessibility status is enabled.
*/
void onAccessibilityStatusChanged(boolean enabled) {
mToolbarMediator.onAccessibilityStatusChanged(enabled);
}
/**
* @param overviewModeBehavior The {@link OverviewModeBehavior} to observe overview state
* changes.
*/
private void setOverviewModeBehavior(OverviewModeBehavior overviewModeBehavior) {
assert overviewModeBehavior != null;
mToolbarMediator.setOverviewModeBehavior(overviewModeBehavior);
}
/**
* @param tabCountProvider The {@link TabCountProvider} to update the tab switcher button.
*/
void setTabCountProvider(TabCountProvider tabCountProvider) {
if (mTabSwitcherButtonCoordinator != null) {
mTabSwitcherButtonCoordinator.setTabCountProvider(tabCountProvider);
} else {
mTabCountProvider = tabCountProvider;
}
}
/**
* @param onClickListener The {@link OnClickListener} for the tab switcher button.
*/
void setTabSwitcherListener(OnClickListener onClickListener) {
if (mTabSwitcherButtonCoordinator != null) {
mTabSwitcherButtonCoordinator.setTabSwitcherListener(onClickListener);
} else {
mTabSwitcherClickListener = onClickListener;
}
}
/**
* @param listener The {@link OnLongClickListener} for the tab switcher button.
*/
void setOnTabSwitcherLongClickHandler(OnLongClickListener listener) {
if (mTabSwitcherButtonView != null) {
mTabSwitcherButtonView.setOnLongClickListener(listener);
} else {
mTabSwitcherLongClickListener = listener;
}
}
void onNativeLibraryReady() {
// It is possible that the {@link mIncognitoSwitchCoordinator} isn't created because
// inflate() is called when the native library isn't ready. So create it now.
if (isInflated()) {
assert mTabModelSelector != null;
maybeCreateIncognitoSwitchCoordinator();
}
mToolbarMediator.onNativeLibraryReady();
}
private void inflate() {
mStub.setLayoutResource(R.layout.start_top_toolbar);
mView = (StartSurfaceToolbarView) mStub.inflate();
mMenuButtonCoordinator.setMenuButton(mView.findViewById(R.id.menu_button_wrapper));
mMenuButtonCoordinator.setVisibility(
mPropertyModel.get(StartSurfaceToolbarProperties.MENU_IS_VISIBLE) ? View.VISIBLE
: View.GONE);
mPropertyModelChangeProcessor = PropertyModelChangeProcessor.create(
mPropertyModel, mView, StartSurfaceToolbarViewBinder::bind);
if (LibraryLoader.getInstance().isInitialized()) {
maybeCreateIncognitoSwitchCoordinator();
}
if (StartSurfaceConfiguration.START_SURFACE_SHOW_STACK_TAB_SWITCHER.getValue()) {
mTabSwitcherButtonView = mView.findViewById(R.id.start_tab_switcher_button);
if (mTabSwitcherLongClickListener != null) {
mTabSwitcherButtonView.setOnLongClickListener(mTabSwitcherLongClickListener);
mTabSwitcherLongClickListener = null;
}
mTabSwitcherButtonCoordinator =
new TabSwitcherButtonCoordinator(mTabSwitcherButtonView);
mTabSwitcherButtonCoordinator.setThemeColorProvider(mThemeColorProvider);
mTabSwitcherButtonView.setVisibility(View.VISIBLE);
if (mTabCountProvider != null) {
mTabSwitcherButtonCoordinator.setTabCountProvider(mTabCountProvider);
mTabCountProvider = null;
}
if (mTabSwitcherClickListener != null) {
mTabSwitcherButtonCoordinator.setTabSwitcherListener(mTabSwitcherClickListener);
mTabSwitcherClickListener = null;
}
}
}
private void maybeCreateIncognitoSwitchCoordinator() {
if (mIncognitoSwitchCoordinator != null || mTabModelSelector == null) {
return;
}
if (IncognitoUtils.isIncognitoModeEnabled()
&& !StartSurfaceConfiguration.START_SURFACE_SHOW_STACK_TAB_SWITCHER.getValue()) {
mIncognitoSwitchCoordinator = new IncognitoSwitchCoordinator(mView, mTabModelSelector);
}
}
private boolean isInflated() {
return mView != null;
}
@VisibleForTesting
public IncognitoSwitchCoordinator getIncognitoSwitchCoordinatorForTesting() {
return mIncognitoSwitchCoordinator;
}
}