1 // Copyright 2013 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 #ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_
6 #define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/macros.h"
12 #include "base/observer_list.h"
13 #include "base/optional.h"
14 #include "base/scoped_observer.h"
15 #include "chrome/browser/command_observer.h"
16 #include "chrome/browser/ui/page_action/page_action_icon_type.h"
17 #include "chrome/browser/ui/toolbar/app_menu_icon_controller.h"
18 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
19 #include "chrome/browser/ui/views/frame/browser_root_view.h"
20 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
21 #include "chrome/browser/ui/views/intent_picker_bubble_view.h"
22 #include "chrome/browser/ui/views/location_bar/custom_tab_bar_view.h"
23 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
24 #include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h"
25 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
26 #include "chrome/browser/upgrade_detector/upgrade_observer.h"
27 #include "components/prefs/pref_member.h"
28 #include "ui/base/accelerators/accelerator.h"
29 #include "ui/base/pointer/touch_ui_controller.h"
30 #include "ui/views/accessible_pane_view.h"
31 #include "ui/views/animation/animation_delegate_views.h"
32 #include "ui/views/controls/button/menu_button.h"
33 #include "ui/views/view.h"
34 #include "url/origin.h"
35 
36 #if defined(OS_CHROMEOS)
37 #include "chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h"
38 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
39 #include "components/arc/mojom/intent_helper.mojom-forward.h"  // nogncheck https://crbug.com/784179
40 #endif  // defined(OS_CHROMEOS)
41 
42 class AppMenuButton;
43 class AvatarToolbarButton;
44 class BrowserAppMenuButton;
45 class Browser;
46 class ExtensionsToolbarButton;
47 class ExtensionsToolbarContainer;
48 class HomeButton;
49 class MediaToolbarButtonView;
50 class ReloadButton;
51 class ToolbarButton;
52 class ToolbarAccountIconContainerView;
53 
54 namespace bookmarks {
55 class BookmarkBubbleObserver;
56 }
57 
58 namespace media_router {
59 class CastToolbarButton;
60 }
61 
62 namespace views {
63 class FlexLayout;
64 }
65 
66 // The Browser Window's toolbar.
67 class ToolbarView : public views::AccessiblePaneView,
68                     public ui::AcceleratorProvider,
69                     public views::AnimationDelegateViews,
70                     public LocationBarView::Delegate,
71                     public BrowserActionsContainer::Delegate,
72                     public CommandObserver,
73                     public AppMenuIconController::Delegate,
74                     public UpgradeObserver,
75                     public ToolbarButtonProvider,
76                     public BrowserRootView::DropTarget {
77  public:
78   // Types of display mode this toolbar can have.
79   enum class DisplayMode {
80     NORMAL,     // Normal toolbar with buttons, etc.
81     LOCATION,   // Slimline toolbar showing only compact location
82                 // bar, used for popups.
83     CUSTOM_TAB  // Custom tab bar, used in PWAs when a location
84                 // needs to be displayed.
85   };
86 
87   // The view class name.
88   static const char kViewClassName[];
89 
90   explicit ToolbarView(Browser* browser, BrowserView* browser_view);
91   ~ToolbarView() override;
92 
93   // Create the contents of the Browser Toolbar.
94   void Init();
95 
96   // Forces the toolbar (and transitively the location bar) to update its
97   // current state.  If |tab| is non-NULL, we're switching (back?) to this tab
98   // and should restore any previous location bar state (such as user editing)
99   // as well.
100   void Update(content::WebContents* tab);
101 
102   // Updates the visibility of the custom tab bar, potentially animating the
103   // transition.
104   void UpdateCustomTabBarVisibility(bool visible, bool animate);
105 
106   // We may or may not be using a WebUI tab strip. Make sure toolbar items are
107   // added or removed accordingly.
108   void UpdateForWebUITabStrip();
109 
110   // Clears the current state for |tab|.
111   void ResetTabState(content::WebContents* tab);
112 
113   // Set focus to the toolbar with complete keyboard access, with the
114   // focus initially set to the app menu. Focus will be restored
115   // to the last focused view if the user escapes.
116   void SetPaneFocusAndFocusAppMenu();
117 
118   // Returns true if the app menu is focused.
119   bool IsAppMenuFocused();
120 
121   void ShowIntentPickerBubble(
122       std::vector<IntentPickerBubbleView::AppInfo> app_info,
123       bool show_stay_in_chrome,
124       bool show_remember_selection,
125       PageActionIconType icon_type,
126       const base::Optional<url::Origin>& initiating_origin,
127       IntentPickerResponse callback);
128 
129   // Shows a bookmark bubble and anchors it appropriately.
130   void ShowBookmarkBubble(const GURL& url,
131                           bool already_bookmarked,
132                           bookmarks::BookmarkBubbleObserver* observer);
133 
134   // Accessors.
browser()135   Browser* browser() const { return browser_; }
browser_actions()136   BrowserActionsContainer* browser_actions() const { return browser_actions_; }
extensions_container()137   ExtensionsToolbarContainer* extensions_container() const {
138     return extensions_container_;
139   }
140   ExtensionsToolbarButton* GetExtensionsButton() const;
back_button()141   ToolbarButton* back_button() const { return back_; }
reload_button()142   ReloadButton* reload_button() const { return reload_; }
location_bar()143   LocationBarView* location_bar() const { return location_bar_; }
custom_tab_bar()144   CustomTabBarView* custom_tab_bar() { return custom_tab_bar_; }
cast_button()145   media_router::CastToolbarButton* cast_button() const { return cast_; }
media_button()146   MediaToolbarButtonView* media_button() const { return media_button_; }
toolbar_account_icon_container()147   ToolbarAccountIconContainerView* toolbar_account_icon_container() const {
148     return toolbar_account_icon_container_;
149   }
app_menu_button()150   BrowserAppMenuButton* app_menu_button() const { return app_menu_button_; }
home_button()151   HomeButton* home_button() const { return home_; }
app_menu_icon_controller()152   AppMenuIconController* app_menu_icon_controller() {
153     return &app_menu_icon_controller_;
154   }
155 
156   // LocationBarView::Delegate:
157   content::WebContents* GetWebContents() override;
158   LocationBarModel* GetLocationBarModel() override;
159   const LocationBarModel* GetLocationBarModel() const override;
160   ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate()
161       override;
162 
163   // BrowserActionsContainer::Delegate:
164   views::LabelButton* GetOverflowReferenceView() override;
165   base::Optional<int> GetMaxBrowserActionsWidth() const override;
166   std::unique_ptr<ToolbarActionsBar> CreateToolbarActionsBar(
167       ToolbarActionsBarDelegate* delegate,
168       Browser* browser,
169       ToolbarActionsBar* main_bar) const override;
170 
171   // CommandObserver:
172   void EnabledStateChangedForCommand(int id, bool enabled) override;
173 
174   // UpgradeObserver toolbar_button_view_provider.
175   void OnOutdatedInstall() override;
176   void OnOutdatedInstallNoAutoUpdate() override;
177   void OnCriticalUpgradeInstalled() override;
178 
179   // ui::AcceleratorProvider:
180   bool GetAcceleratorForCommandId(int command_id,
181                                   ui::Accelerator* accelerator) const override;
182 
183   // views::View:
184   gfx::Size CalculatePreferredSize() const override;
185   gfx::Size GetMinimumSize() const override;
186   void Layout() override;
187   void OnThemeChanged() override;
188   const char* GetClassName() const override;
189   bool AcceleratorPressed(const ui::Accelerator& acc) override;
190   void ChildPreferredSizeChanged(views::View* child) override;
191 
192  protected:
193   // AccessiblePaneView:
194   bool SetPaneFocusAndFocusDefault() override;
195 
196   // This controls Toolbar, LocationBar and CustomTabBar visibility.
197   // If we don't set all three, tab navigation from the app menu breaks
198   // on Chrome OS.
199   void SetToolbarVisibility(bool visible);
200 
201  private:
202   // AnimationDelegateViews:
203   void AnimationEnded(const gfx::Animation* animation) override;
204   void AnimationProgressed(const gfx::Animation* animation) override;
205 
206   // Declarative layout for child controls.
207   void InitLayout();
208 
209   // Logic that must be done on initialization and then on layout.
210   void LayoutCommon();
211 
212   // AppMenuIconController::Delegate:
213   void UpdateTypeAndSeverity(
214       AppMenuIconController::TypeAndSeverity type_and_severity) override;
215   SkColor GetDefaultColorForSeverity(
216       AppMenuIconController::Severity severity) const override;
217 
218   // ToolbarButtonProvider:
219   BrowserActionsContainer* GetBrowserActionsContainer() override;
220   ExtensionsToolbarContainer* GetExtensionsToolbarContainer() override;
221   gfx::Size GetToolbarButtonSize() const override;
222   views::View* GetDefaultExtensionDialogAnchorView() override;
223   PageActionIconView* GetPageActionIconView(PageActionIconType type) override;
224   AppMenuButton* GetAppMenuButton() override;
225   gfx::Rect GetFindBarBoundingBox(int contents_bottom) override;
226   void FocusToolbar() override;
227   views::AccessiblePaneView* GetAsAccessiblePaneView() override;
228   views::View* GetAnchorView(PageActionIconType type) override;
229   void ZoomChangedForActiveTab(bool can_show_bubble) override;
230   AvatarToolbarButton* GetAvatarToolbarButton() override;
231   ToolbarButton* GetBackButton() override;
232   ReloadButton* GetReloadButton() override;
233 
234   // BrowserRootView::DropTarget
235   BrowserRootView::DropIndex GetDropIndex(
236       const ui::DropTargetEvent& event) override;
237   views::View* GetViewForDrop() override;
238 
239   // Loads the images for all the child views.
240   void LoadImages();
241 
242   // Shows the critical notification bubble against the app menu.
243   void ShowCriticalNotification();
244 
245   // Shows the outdated install notification bubble against the app menu.
246   // |auto_update_enabled| is set to true when auto-upate is on.
247   void ShowOutdatedInstallNotification(bool auto_update_enabled);
248 
249   void OnShowHomeButtonChanged();
250   void UpdateHomeButtonVisibility();
251 
252   void OnTouchUiChanged();
253 
254   void AppMenuButtonPressed(const ui::Event& event);
255 
256   gfx::SlideAnimation size_animation_{this};
257 
258   // Controls. Most of these can be null, e.g. in popup windows. Only
259   // |location_bar_| is guaranteed to exist. These pointers are owned by the
260   // view hierarchy.
261   ToolbarButton* back_ = nullptr;
262   ToolbarButton* forward_ = nullptr;
263   ReloadButton* reload_ = nullptr;
264   HomeButton* home_ = nullptr;
265   CustomTabBarView* custom_tab_bar_ = nullptr;
266   LocationBarView* location_bar_ = nullptr;
267   BrowserActionsContainer* browser_actions_ = nullptr;
268   ExtensionsToolbarContainer* extensions_container_ = nullptr;
269   media_router::CastToolbarButton* cast_ = nullptr;
270   ToolbarAccountIconContainerView* toolbar_account_icon_container_ = nullptr;
271   AvatarToolbarButton* avatar_ = nullptr;
272   MediaToolbarButtonView* media_button_ = nullptr;
273   BrowserAppMenuButton* app_menu_button_ = nullptr;
274 
275   Browser* const browser_;
276   BrowserView* const browser_view_;
277 
278   views::FlexLayout* layout_manager_ = nullptr;
279 
280   AppMenuIconController app_menu_icon_controller_;
281 
282   // Controls whether or not a home button should be shown on the toolbar.
283   BooleanPrefMember show_home_button_;
284 
285   // The display mode used when laying out the toolbar.
286   const DisplayMode display_mode_;
287 
288   std::unique_ptr<ui::TouchUiController::Subscription> subscription_ =
289       ui::TouchUiController::Get()->RegisterCallback(
290           base::BindRepeating(&ToolbarView::OnTouchUiChanged,
291                               base::Unretained(this)));
292 
293   // Whether this toolbar has been initialized.
294   bool initialized_ = false;
295 
296   DISALLOW_IMPLICIT_CONSTRUCTORS(ToolbarView);
297 };
298 
299 #endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_
300