blob: 5932f90f6627d06ae536b1c80d0f4cc5f2fce4c7 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_
#include <memory>
#include <optional>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/command_observer.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "chrome/browser/ui/toolbar/app_menu_icon_controller.h"
#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
#include "chrome/browser/ui/views/frame/browser_root_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/intent_picker_bubble_view.h"
#include "chrome/browser/ui/views/location_bar/custom_tab_bar_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h"
#include "chrome/browser/ui/views/toolbar/overflow_button.h"
#include "chrome/browser/ui/views/toolbar/pinned_action_toolbar_button.h"
#include "chrome/browser/ui/views/toolbar/split_tabs_button.h"
#include "components/prefs/pref_member.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/pointer/touch_ui_controller.h"
#include "ui/views/accessible_pane_view.h"
#include "ui/views/animation/animation_delegate_views.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/view.h"
#include "url/origin.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/ash/experiences/arc/intent_helper/arc_intent_helper_bridge.h"
#include "chromeos/ash/experiences/arc/mojom/intent_helper.mojom-forward.h" // nogncheck https://crbug.com/784179
#endif // BUILDFLAG(IS_CHROMEOS)
class AppMenuButton;
class AvatarToolbarButton;
class BatterySaverButton;
class BrowserAppMenuButton;
class Browser;
class ExtensionsToolbarButton;
class ExtensionsToolbarContainer;
class HomeButton;
class IntentChipButton;
class ExtensionsToolbarCoordinator;
class MediaToolbarButtonView;
class ReloadButton;
class ReloadButtonWebView;
class PinnedToolbarActionsContainer;
class ToolbarButton;
class AvatarToolbarButtonBrowserTest;
class ToolbarController;
class OverflowButton;
class PerformanceInterventionButton;
namespace views {
class FlexLayout;
}
// The Browser Window's toolbar.
class ToolbarView : public views::AccessiblePaneView,
public ui::AcceleratorProvider,
public views::AnimationDelegateViews,
public LocationBarView::Delegate,
public CommandObserver,
public AppMenuIconController::Delegate,
public ToolbarButtonProvider,
public BrowserRootView::DropTarget,
public TabStripModelObserver {
METADATA_HEADER(ToolbarView, views::AccessiblePaneView)
public:
// Types of display mode this toolbar can have.
enum class DisplayMode {
NORMAL, // Normal toolbar with buttons, etc.
LOCATION, // Slimline toolbar showing only compact location
// bar, used for popups.
CUSTOM_TAB // Custom tab bar, used in PWAs when a location
// needs to be displayed.
};
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kToolbarElementId);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kToolbarContainerElementId);
ToolbarView(Browser* browser, BrowserView* browser_view);
ToolbarView(const ToolbarView&) = delete;
ToolbarView& operator=(const ToolbarView&) = delete;
~ToolbarView() override;
// Create the contents of the Browser Toolbar.
void Init();
// Forces the toolbar (and transitively the location bar) to update its
// current state. If |tab| is non-NULL, we're switching (back?) to this tab
// and should restore any previous location bar state (such as user editing)
// as well.
void Update(content::WebContents* tab);
// Updates the toolbar's visible security state if the state has changed
// since the last update. Returns true if the toolbar was updated.
bool UpdateSecurityState();
// Updates the visibility of the custom tab bar, potentially animating the
// transition.
void UpdateCustomTabBarVisibility(bool visible, bool animate);
// We may or may not be using a WebUI tab strip. Make sure toolbar items are
// added or removed accordingly.
void UpdateForWebUITabStrip();
// Clears the current state for |tab|.
void ResetTabState(content::WebContents* tab);
// Set focus to the toolbar with complete keyboard access, with the
// focus initially set to the app menu. Focus will be restored
// to the last focused view if the user escapes.
void SetPaneFocusAndFocusAppMenu();
// Returns true if the app menu is focused.
bool GetAppMenuFocused() const;
void ShowIntentPickerBubble(
std::vector<IntentPickerBubbleView::AppInfo> app_info,
bool show_stay_in_chrome,
bool show_remember_selection,
IntentPickerBubbleView::BubbleType bubble_type,
const std::optional<url::Origin>& initiating_origin,
IntentPickerResponse callback);
// Shows a bookmark bubble and anchors it appropriately.
void ShowBookmarkBubble(const GURL& url, bool already_bookmarked);
// Accessors.
Browser* browser() const { return browser_; }
views::Button* GetChromeLabsButton() const;
ExtensionsToolbarContainer* extensions_container() const {
return extensions_container_;
}
ToolbarButton* forward_button() const { return forward_; }
ExtensionsToolbarButton* GetExtensionsButton() const;
ReloadButton* reload_button() const { return reload_; }
LocationBarView* location_bar() const { return location_bar_; }
CustomTabBarView* custom_tab_bar() { return custom_tab_bar_; }
BatterySaverButton* battery_saver_button() const {
return battery_saver_button_;
}
PerformanceInterventionButton* performance_intervention_button() const {
return performance_intervention_button_;
}
ToolbarButton* GetCastButton() const;
PinnedToolbarActionsContainer* pinned_toolbar_actions_container() const {
return pinned_toolbar_actions_container_;
}
MediaToolbarButtonView* media_button() const { return media_button_; }
BrowserAppMenuButton* app_menu_button() const { return app_menu_button_; }
HomeButton* home_button() const { return home_; }
PinnedActionToolbarButton* tab_search_button() const {
return tab_search_button_;
}
AppMenuIconController* app_menu_icon_controller() {
return &app_menu_icon_controller_;
}
const ToolbarController* toolbar_controller() const {
return toolbar_controller_.get();
}
views::View* new_tab_button_for_testing() { return new_tab_button_; }
// LocationBarView::Delegate:
content::WebContents* GetWebContents() override;
LocationBarModel* GetLocationBarModel() override;
const LocationBarModel* GetLocationBarModel() const override;
ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate()
override;
// CommandObserver:
void EnabledStateChangedForCommand(int id, bool enabled) override;
// ui::AcceleratorProvider:
bool GetAcceleratorForCommandId(int command_id,
ui::Accelerator* accelerator) const override;
// views::View:
gfx::Size CalculatePreferredSize(
const views::SizeBounds& available_size) const override;
gfx::Size GetMinimumSize() const override;
void Layout(PassKey) override;
void OnThemeChanged() override;
bool AcceleratorPressed(const ui::Accelerator& acc) override;
void ChildPreferredSizeChanged(views::View* child) override;
// TabStripModelObserver:
void OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) override;
friend class AvatarToolbarButtonBaseBrowserTest;
protected:
// This controls Toolbar, LocationBar and CustomTabBar visibility.
// If we don't set all three, tab navigation from the app menu breaks
// on Chrome OS.
void SetToolbarVisibility(bool visible);
private:
// Forwards view overrides to this class.
class ContainerView;
// AccessiblePaneView:
views::View* GetDefaultFocusableChild() override;
// AnimationDelegateViews:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
// Declarative layout for child controls.
void InitLayout();
// Logic that must be done on initialization and then on layout.
void LayoutCommon();
// AppMenuIconController::Delegate:
void UpdateTypeAndSeverity(
AppMenuIconController::TypeAndSeverity type_and_severity) override;
// ToolbarButtonProvider:
ExtensionsToolbarContainer* GetExtensionsToolbarContainer() override;
PinnedToolbarActionsContainer* GetPinnedToolbarActionsContainer() override;
gfx::Size GetToolbarButtonSize() const override;
views::View* GetDefaultExtensionDialogAnchorView() override;
PageActionIconView* GetPageActionIconView(PageActionIconType type) override;
IconLabelBubbleView* GetPageActionView(actions::ActionId action_id) override;
AppMenuButton* GetAppMenuButton() override;
gfx::Rect GetFindBarBoundingBox(int contents_bottom) override;
void FocusToolbar() override;
views::AccessiblePaneView* GetAsAccessiblePaneView() override;
views::View* GetAnchorView(
std::optional<actions::ActionId> action_id) override;
void ZoomChangedForActiveTab(bool can_show_bubble) override;
AvatarToolbarButton* GetAvatarToolbarButton() override;
ToolbarButton* GetBackButton() override;
ReloadButton* GetReloadButton() override;
IntentChipButton* GetIntentChipButton() override;
ToolbarButton* GetDownloadButton() override;
// BrowserRootView::DropTarget
std::optional<BrowserRootView::DropIndex> GetDropIndex(
const ui::DropTargetEvent& event) override;
BrowserRootView::DropTarget* GetDropTarget(
gfx::Point loc_in_local_coords) override;
views::View* GetViewForDrop() override;
// Changes the visibility of the Chrome Labs entry point based on prefs.
void OnChromeLabsPrefChanged();
// Loads the images for all the child views.
void LoadImages();
void OnShowForwardButtonChanged();
void OnShowHomeButtonChanged();
void OnTouchUiChanged();
void UpdateClipPath();
// Called when active state for the window changes.
void ActiveStateChanged();
void NewTabButtonPressed(const ui::Event& event);
void UpdateRecedingCornerRadius();
gfx::SlideAnimation size_animation_{this};
// Controls. Most of these can be null, e.g. in popup windows. Only
// |location_bar_| is guaranteed to exist. These pointers are owned by the
// view hierarchy.
raw_ptr<ToolbarButton> back_ = nullptr;
raw_ptr<ToolbarButton> forward_ = nullptr;
raw_ptr<ReloadButton> reload_ = nullptr;
raw_ptr<ReloadButtonWebView> reload_webview_ = nullptr;
raw_ptr<HomeButton> home_ = nullptr;
raw_ptr<SplitTabsToolbarButton> split_tabs_ = nullptr;
raw_ptr<CustomTabBarView> custom_tab_bar_ = nullptr;
raw_ptr<LocationBarView> location_bar_ = nullptr;
raw_ptr<ExtensionsToolbarContainer> extensions_container_ = nullptr;
raw_ptr<views::View> toolbar_divider_ = nullptr;
raw_ptr<BatterySaverButton> battery_saver_button_ = nullptr;
raw_ptr<PerformanceInterventionButton> performance_intervention_button_ =
nullptr;
raw_ptr<PinnedToolbarActionsContainer> pinned_toolbar_actions_container_ =
nullptr;
raw_ptr<AvatarToolbarButton> avatar_ = nullptr;
raw_ptr<MediaToolbarButtonView> media_button_ = nullptr;
raw_ptr<BrowserAppMenuButton> app_menu_button_ = nullptr;
raw_ptr<views::View> new_tab_button_ = nullptr;
raw_ptr<PinnedActionToolbarButton> tab_search_button_ = nullptr;
const raw_ptr<Browser> browser_;
const raw_ptr<BrowserView> browser_view_;
raw_ptr<views::FlexLayout> layout_manager_ = nullptr;
AppMenuIconController app_menu_icon_controller_;
std::unique_ptr<ExtensionsToolbarCoordinator> extensions_toolbar_coordinator_;
BooleanPrefMember show_forward_button_;
// Controls whether or not a home button should be shown on the toolbar.
BooleanPrefMember show_home_button_;
BooleanPrefMember show_chrome_labs_button_;
// The display mode used when laying out the toolbar.
const DisplayMode display_mode_;
std::unique_ptr<ToolbarController> toolbar_controller_;
base::CallbackListSubscription subscription_ =
ui::TouchUiController::Get()->RegisterCallback(
base::BindRepeating(&ToolbarView::OnTouchUiChanged,
base::Unretained(this)));
// Whether this toolbar has been initialized.
bool initialized_ = false;
// container_view_ is transparent with the same dimensions as ToolbarView.
// All children are added to container_view_ and layout_manager_ applies to
// container_view_. The reason for this layer of indiretion is because
// container_view_ has a clip path set in UpdateClipPath() which adds rounded
// corners. This leaves some unpainted pixels, which are painted by
// background_view_left_ and background_view_right_.
// the future.
raw_ptr<ContainerView> container_view_ = nullptr;
// A chevron button that indicates some toolbar elements have overflowed
// due to small toolbar view width. Visibility controlled by
// `toolbar_controller_`.
raw_ptr<OverflowButton> overflow_button_ = nullptr;
// The toolbar's top corners recede lower into the toolbar bounds, and need to
// have the frame's color painted into it. The receding_corner_radius_ is the
// size of the corner radius that's clipped out, and the background_view_left_
// background_view_right_ are the area painted behind the toolbar which give
// the effect of the toolbar raising up into the tabstrip region.
// The receding_corner_radius_ can change based on whether if WebUiTabStrip is
// being used and if the first tab is active or not.
int receding_corner_radius_ = 0;
raw_ptr<View> background_view_left_ = nullptr;
raw_ptr<View> background_view_right_ = nullptr;
// Listens to changes to window active state to update background_view_right_
// and background_view_left_, as their background depends on active state.
base::CallbackListSubscription active_state_subscription_;
};
extern const ui::ClassProperty<bool>* const kActionItemUnderlineIndicatorKey;
#endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_