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.
5 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h"
11 #include "base/i18n/number_formatting.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/app/chrome_command_ids.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/command_updater.h"
17 #include "chrome/browser/extensions/extension_commands_global_registry.h"
18 #include "chrome/browser/extensions/extension_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/themes/theme_service.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_command_controller.h"
23 #include "chrome/browser/ui/browser_commands.h"
24 #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h"
25 #include "chrome/browser/ui/browser_instant_controller.h"
26 #include "chrome/browser/ui/browser_tabstrip.h"
27 #include "chrome/browser/ui/browser_window.h"
28 #include "chrome/browser/ui/global_error/global_error_service.h"
29 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
30 #include "chrome/browser/ui/omnibox/omnibox_view.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
33 #include "chrome/browser/ui/view_ids.h"
34 #include "chrome/browser/ui/views/extensions/extension_message_bubble_view.h"
35 #include "chrome/browser/ui/views/extensions/extension_popup.h"
36 #include "chrome/browser/ui/views/frame/browser_view.h"
37 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
38 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
39 #include "chrome/browser/ui/views/location_bar/star_view.h"
40 #include "chrome/browser/ui/views/location_bar/translate_icon_view.h"
41 #include "chrome/browser/ui/views/outdated_upgrade_bubble_view.h"
42 #include "chrome/browser/ui/views/toolbar/back_button.h"
43 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
44 #include "chrome/browser/ui/views/toolbar/home_button.h"
45 #include "chrome/browser/ui/views/toolbar/reload_button.h"
46 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
47 #include "chrome/browser/ui/views/toolbar/wrench_menu.h"
48 #include "chrome/browser/ui/views/toolbar/wrench_toolbar_button.h"
49 #include "chrome/common/chrome_switches.h"
50 #include "chrome/common/pref_names.h"
51 #include "chrome/grit/chromium_strings.h"
52 #include "chrome/grit/generated_resources.h"
53 #include "content/public/browser/browser_accessibility_state.h"
54 #include "content/public/browser/notification_service.h"
55 #include "content/public/browser/render_view_host.h"
56 #include "content/public/browser/user_metrics.h"
57 #include "content/public/browser/web_contents.h"
58 #include "grit/theme_resources.h"
59 #include "ui/accessibility/ax_view_state.h"
60 #include "ui/aura/window.h"
61 #include "ui/base/l10n/l10n_util.h"
62 #include "ui/base/theme_provider.h"
63 #include "ui/base/window_open_disposition.h"
64 #include "ui/compositor/layer.h"
65 #include "ui/gfx/canvas.h"
66 #include "ui/gfx/image/canvas_image_source.h"
67 #include "ui/keyboard/keyboard_controller.h"
68 #include "ui/native_theme/native_theme_aura.h"
69 #include "ui/views/controls/menu/menu_listener.h"
70 #include "ui/views/focus/view_storage.h"
71 #include "ui/views/view_targeter.h"
72 #include "ui/views/widget/tooltip_manager.h"
73 #include "ui/views/widget/widget.h"
74 #include "ui/views/window/non_client_view.h"
77 #include "chrome/browser/ui/views/conflicting_module_view_win.h"
78 #include "chrome/browser/ui/views/critical_notification_bubble_view.h"
81 #if !defined(OS_CHROMEOS)
82 #include "chrome/browser/signin/signin_global_error_factory.h"
83 #include "chrome/browser/sync/sync_global_error_factory.h"
87 #include "ash/shell.h"
90 using base::UserMetricsAction;
91 using content::WebContents;
95 // The edge graphics have some built-in spacing/shadowing, so we have to adjust
96 // our spacing to make it match.
97 const int kLeftEdgeSpacing = 3;
98 const int kRightEdgeSpacing = 2;
100 // Ash doesn't use a rounded content area and its top edge has an extra shadow.
101 const int kContentShadowHeightAsh = 2;
103 // Non-ash uses a rounded content area with no shadow in the assets.
104 const int kContentShadowHeight = 0;
106 #if !defined(OS_CHROMEOS)
109 return ash::Shell::HasInstance();
114 #endif // OS_CHROMEOS
119 const char ToolbarView::kViewClassName[] = "ToolbarView";
121 ////////////////////////////////////////////////////////////////////////////////
122 // ToolbarView, public:
124 ToolbarView::ToolbarView(Browser* browser)
130 browser_actions_(NULL),
133 badge_controller_(browser->profile(), this),
134 extension_message_bubble_factory_(
135 new extensions::ExtensionMessageBubbleFactory(browser->profile(),
137 set_id(VIEW_ID_TOOLBAR);
140 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
142 chrome::AddCommandObserver(browser_, IDC_BACK, this);
143 chrome::AddCommandObserver(browser_, IDC_FORWARD, this);
144 chrome::AddCommandObserver(browser_, IDC_RELOAD, this);
145 chrome::AddCommandObserver(browser_, IDC_HOME, this);
146 chrome::AddCommandObserver(browser_, IDC_LOAD_NEW_TAB_PAGE, this);
148 display_mode_ = DISPLAYMODE_LOCATION;
149 if (browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP) ||
150 (browser->is_app() && extensions::util::IsStreamlinedHostedAppsEnabled()))
151 display_mode_ = DISPLAYMODE_NORMAL;
153 if (OutdatedUpgradeBubbleView::IsAvailable()) {
154 registrar_.Add(this, chrome::NOTIFICATION_OUTDATED_INSTALL,
155 content::NotificationService::AllSources());
156 registrar_.Add(this, chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
157 content::NotificationService::AllSources());
160 registrar_.Add(this, chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
161 content::NotificationService::AllSources());
165 ToolbarView::~ToolbarView() {
166 // NOTE: Don't remove the command observers here. This object gets destroyed
167 // after the Browser (which owns the CommandUpdater), so the CommandUpdater is
171 void ToolbarView::Init() {
172 GetWidget()->AddObserver(this);
174 back_ = new BackButton(this, new BackForwardMenuModel(
175 browser_, BackForwardMenuModel::BACKWARD_MENU));
176 back_->set_triggerable_event_flags(
177 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON);
178 back_->set_tag(IDC_BACK);
179 back_->SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_BACK));
180 back_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_BACK));
181 back_->set_id(VIEW_ID_BACK_BUTTON);
184 forward_ = new ToolbarButton(this, new BackForwardMenuModel(
185 browser_, BackForwardMenuModel::FORWARD_MENU));
186 forward_->set_triggerable_event_flags(
187 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON);
188 forward_->set_tag(IDC_FORWARD);
189 forward_->SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_FORWARD));
190 forward_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_FORWARD));
191 forward_->set_id(VIEW_ID_FORWARD_BUTTON);
194 location_bar_ = new LocationBarView(
195 browser_, browser_->profile(),
196 browser_->command_controller()->command_updater(), this,
197 display_mode_ == DISPLAYMODE_LOCATION);
199 reload_ = new ReloadButton(browser_->command_controller()->command_updater());
200 reload_->set_triggerable_event_flags(
201 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON);
202 reload_->set_tag(IDC_RELOAD);
203 reload_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_RELOAD));
204 reload_->set_id(VIEW_ID_RELOAD_BUTTON);
207 home_ = new HomeButton(this, browser_);
208 home_->set_triggerable_event_flags(
209 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON);
210 home_->set_tag(IDC_HOME);
211 home_->SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_HOME));
212 home_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_HOME));
213 home_->set_id(VIEW_ID_HOME_BUTTON);
216 browser_actions_ = new BrowserActionsContainer(
218 NULL); // No master container for this one (it is master).
220 app_menu_ = new WrenchToolbarButton(this);
221 app_menu_->EnableCanvasFlippingForRTLUI(true);
222 app_menu_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_APP));
223 app_menu_->SetTooltipText(l10n_util::GetStringUTF16(IDS_APPMENU_TOOLTIP));
224 app_menu_->set_id(VIEW_ID_APP_MENU);
226 // Always add children in order from left to right, for accessibility.
228 AddChildView(forward_);
229 AddChildView(reload_);
231 AddChildView(location_bar_);
232 AddChildView(browser_actions_);
233 AddChildView(app_menu_);
237 // Start global error services now so we badge the menu correctly in non-Ash.
238 #if !defined(OS_CHROMEOS)
239 if (!HasAshShell()) {
240 SigninGlobalErrorFactory::GetForProfile(browser_->profile());
241 #if !defined(OS_ANDROID)
242 SyncGlobalErrorFactory::GetForProfile(browser_->profile());
245 #endif // OS_CHROMEOS
247 // Add any necessary badges to the menu item based on the system state.
248 // Do this after |app_menu_| has been added as a bubble may be shown that
249 // needs the widget (widget found by way of app_menu_->GetWidget()).
250 badge_controller_.UpdateDelegate();
252 location_bar_->Init();
254 show_home_button_.Init(prefs::kShowHomeButton,
255 browser_->profile()->GetPrefs(),
256 base::Bind(&ToolbarView::OnShowHomeButtonChanged,
257 base::Unretained(this)));
259 browser_actions_->Init();
261 // Accessibility specific tooltip text.
262 if (content::BrowserAccessibilityState::GetInstance()->
263 IsAccessibleBrowser()) {
264 back_->SetTooltipText(
265 l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLTIP_BACK));
266 forward_->SetTooltipText(
267 l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLTIP_FORWARD));
271 void ToolbarView::OnWidgetVisibilityChanged(views::Widget* widget,
274 // Safe to call multiple times; the bubble will only appear once.
275 extension_message_bubble_factory_->MaybeShow(app_menu_);
279 void ToolbarView::OnWidgetActivationChanged(views::Widget* widget,
281 extensions::ExtensionCommandsGlobalRegistry* registry =
282 extensions::ExtensionCommandsGlobalRegistry::Get(browser_->profile());
285 registry->set_registry_for_active_window(
286 browser_actions_->extension_keybinding_registry());
287 } else if (registry->registry_for_active_window() ==
288 browser_actions_->extension_keybinding_registry()) {
289 registry->set_registry_for_active_window(NULL);
294 void ToolbarView::Update(WebContents* tab) {
296 location_bar_->Update(tab);
297 if (browser_actions_)
298 browser_actions_->RefreshToolbarActionViews();
300 reload_->set_menu_enabled(chrome::IsDebuggerAttachedToCurrentTab(browser_));
303 void ToolbarView::SetPaneFocusAndFocusAppMenu() {
304 SetPaneFocus(app_menu_);
307 bool ToolbarView::IsAppMenuFocused() {
308 return app_menu_->HasFocus();
311 void ToolbarView::AddMenuListener(views::MenuListener* listener) {
312 menu_listeners_.AddObserver(listener);
315 void ToolbarView::RemoveMenuListener(views::MenuListener* listener) {
316 menu_listeners_.RemoveObserver(listener);
319 views::View* ToolbarView::GetBookmarkBubbleAnchor() {
320 views::View* star_view = location_bar()->star_view();
321 return (star_view && star_view->visible()) ? star_view : app_menu_;
324 views::View* ToolbarView::GetTranslateBubbleAnchor() {
325 views::View* translate_icon_view = location_bar()->translate_icon_view();
326 return (translate_icon_view && translate_icon_view->visible()) ?
327 translate_icon_view : app_menu_;
330 void ToolbarView::ExecuteExtensionCommand(
331 const extensions::Extension* extension,
332 const extensions::Command& command) {
333 browser_actions_->ExecuteExtensionCommand(extension, command);
336 void ToolbarView::ShowAppMenu(bool for_drop) {
337 if (wrench_menu_.get() && wrench_menu_->IsShowing())
340 if (keyboard::KeyboardController::GetInstance() &&
341 keyboard::KeyboardController::GetInstance()->keyboard_visible()) {
342 keyboard::KeyboardController::GetInstance()->HideKeyboard(
343 keyboard::KeyboardController::HIDE_REASON_AUTOMATIC);
347 new WrenchMenu(browser_, for_drop ? WrenchMenu::FOR_DROP : 0));
348 wrench_menu_model_.reset(new WrenchMenuModel(this, browser_));
349 wrench_menu_->Init(wrench_menu_model_.get());
351 FOR_EACH_OBSERVER(views::MenuListener, menu_listeners_, OnMenuOpened());
353 wrench_menu_->RunMenu(app_menu_);
356 views::MenuButton* ToolbarView::app_menu() const {
360 ////////////////////////////////////////////////////////////////////////////////
361 // ToolbarView, AccessiblePaneView overrides:
363 bool ToolbarView::SetPaneFocus(views::View* initial_focus) {
364 if (!AccessiblePaneView::SetPaneFocus(initial_focus))
367 location_bar_->SetShowFocusRect(true);
371 void ToolbarView::GetAccessibleState(ui::AXViewState* state) {
372 state->role = ui::AX_ROLE_TOOLBAR;
373 state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLBAR);
376 ////////////////////////////////////////////////////////////////////////////////
377 // ToolbarView, Menu::Delegate overrides:
379 bool ToolbarView::GetAcceleratorInfo(int id, ui::Accelerator* accel) {
380 return GetWidget()->GetAccelerator(id, accel);
383 ////////////////////////////////////////////////////////////////////////////////
384 // ToolbarView, views::MenuButtonListener implementation:
386 void ToolbarView::OnMenuButtonClicked(views::View* source,
387 const gfx::Point& point) {
388 TRACE_EVENT0("views", "ToolbarView::OnMenuButtonClicked");
389 DCHECK_EQ(VIEW_ID_APP_MENU, source->id());
390 ShowAppMenu(false); // Not for drop.
393 ////////////////////////////////////////////////////////////////////////////////
394 // ToolbarView, LocationBarView::Delegate implementation:
396 WebContents* ToolbarView::GetWebContents() {
397 return browser_->tab_strip_model()->GetActiveWebContents();
400 ToolbarModel* ToolbarView::GetToolbarModel() {
401 return browser_->toolbar_model();
404 const ToolbarModel* ToolbarView::GetToolbarModel() const {
405 return browser_->toolbar_model();
408 InstantController* ToolbarView::GetInstant() {
409 return browser_->instant_controller() ?
410 browser_->instant_controller()->instant() : NULL;
413 ContentSettingBubbleModelDelegate*
414 ToolbarView::GetContentSettingBubbleModelDelegate() {
415 return browser_->content_setting_bubble_model_delegate();
418 void ToolbarView::ShowWebsiteSettings(content::WebContents* web_contents,
420 const content::SSLStatus& ssl) {
421 chrome::ShowWebsiteSettings(browser_, web_contents, url, ssl);
424 views::Widget* ToolbarView::CreateViewsBubble(
425 views::BubbleDelegateView* bubble_delegate) {
426 return views::BubbleDelegateView::CreateBubble(bubble_delegate);
429 PageActionImageView* ToolbarView::CreatePageActionImageView(
430 LocationBarView* owner, ExtensionAction* action) {
431 return new PageActionImageView(owner, action, browser_);
434 ////////////////////////////////////////////////////////////////////////////////
435 // ToolbarView, CommandObserver implementation:
437 void ToolbarView::EnabledStateChangedForCommand(int id, bool enabled) {
438 views::Button* button = NULL;
454 button->SetEnabled(enabled);
457 ////////////////////////////////////////////////////////////////////////////////
458 // ToolbarView, views::Button::ButtonListener implementation:
460 void ToolbarView::ButtonPressed(views::Button* sender,
461 const ui::Event& event) {
462 chrome::ExecuteCommandWithDisposition(
463 browser_, sender->tag(), ui::DispositionFromEventFlags(event.flags()));
466 ////////////////////////////////////////////////////////////////////////////////
467 // ToolbarView, content::NotificationObserver implementation:
469 void ToolbarView::Observe(int type,
470 const content::NotificationSource& source,
471 const content::NotificationDetails& details) {
473 case chrome::NOTIFICATION_OUTDATED_INSTALL:
474 ShowOutdatedInstallNotification(true);
476 case chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU:
477 ShowOutdatedInstallNotification(false);
480 case chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED:
481 ShowCriticalNotification();
489 ////////////////////////////////////////////////////////////////////////////////
490 // ToolbarView, ui::AcceleratorProvider implementation:
492 bool ToolbarView::GetAcceleratorForCommandId(int command_id,
493 ui::Accelerator* accelerator) {
494 return GetWidget()->GetAccelerator(command_id, accelerator);
497 ////////////////////////////////////////////////////////////////////////////////
498 // ToolbarView, views::View overrides:
500 gfx::Size ToolbarView::GetPreferredSize() const {
501 gfx::Size size(location_bar_->GetPreferredSize());
502 if (is_display_mode_normal()) {
503 int content_width = kLeftEdgeSpacing + back_->GetPreferredSize().width() +
504 forward_->GetPreferredSize().width() +
505 reload_->GetPreferredSize().width() +
506 (show_home_button_.GetValue() ? home_->GetPreferredSize().width() : 0) +
507 kStandardSpacing + browser_actions_->GetPreferredSize().width() +
508 app_menu_->GetPreferredSize().width() + kRightEdgeSpacing;
509 size.Enlarge(content_width, 0);
511 return SizeForContentSize(size);
514 gfx::Size ToolbarView::GetMinimumSize() const {
515 gfx::Size size(location_bar_->GetMinimumSize());
516 if (is_display_mode_normal()) {
517 int content_width = kLeftEdgeSpacing + back_->GetMinimumSize().width() +
518 forward_->GetMinimumSize().width() + reload_->GetMinimumSize().width() +
519 (show_home_button_.GetValue() ? home_->GetMinimumSize().width() : 0) +
520 kStandardSpacing + browser_actions_->GetMinimumSize().width() +
521 app_menu_->GetMinimumSize().width() + kRightEdgeSpacing;
522 size.Enlarge(content_width, 0);
524 return SizeForContentSize(size);
527 void ToolbarView::Layout() {
528 // If we have not been initialized yet just do nothing.
532 if (!is_display_mode_normal()) {
533 location_bar_->SetBounds(0, PopupTopSpacing(), width(),
534 location_bar_->GetPreferredSize().height());
538 // We assume all child elements except the location bar are the same height.
539 // Set child_y such that buttons appear vertically centered. We put any excess
540 // padding above the buttons.
542 std::min(back_->GetPreferredSize().height(), height());
543 int child_y = (height() - child_height + 1) / 2;
545 // If the window is maximized, we extend the back button to the left so that
546 // clicking on the left-most pixel will activate the back button.
547 // TODO(abarth): If the window becomes maximized but is not resized,
548 // then Layout() might not be called and the back button
549 // will be slightly the wrong size. We should force a
550 // Layout() in this case.
551 // http://crbug.com/5540
552 bool maximized = browser_->window() && browser_->window()->IsMaximized();
553 int back_width = back_->GetPreferredSize().width();
555 back_->SetBounds(0, child_y, back_width + kLeftEdgeSpacing, child_height);
556 back_->SetLeadingMargin(kLeftEdgeSpacing);
558 back_->SetBounds(kLeftEdgeSpacing, child_y, back_width, child_height);
559 back_->SetLeadingMargin(0);
561 int next_element_x = back_->bounds().right();
563 forward_->SetBounds(next_element_x, child_y,
564 forward_->GetPreferredSize().width(), child_height);
565 next_element_x = forward_->bounds().right();
567 reload_->SetBounds(next_element_x, child_y,
568 reload_->GetPreferredSize().width(), child_height);
569 next_element_x = reload_->bounds().right();
571 if (show_home_button_.GetValue() ||
572 (browser_->is_app() &&
573 extensions::util::IsStreamlinedHostedAppsEnabled())) {
574 home_->SetVisible(true);
575 home_->SetBounds(next_element_x, child_y,
576 home_->GetPreferredSize().width(), child_height);
578 home_->SetVisible(false);
579 home_->SetBounds(next_element_x, child_y, 0, child_height);
581 next_element_x = home_->bounds().right() + kStandardSpacing;
583 int browser_actions_width = browser_actions_->GetPreferredSize().width();
584 int app_menu_width = app_menu_->GetPreferredSize().width();
585 int available_width = std::max(0, width() - kRightEdgeSpacing -
586 app_menu_width - browser_actions_width - next_element_x);
588 int location_height = location_bar_->GetPreferredSize().height();
589 int location_y = (height() - location_height + 1) / 2;
590 location_bar_->SetBounds(next_element_x, location_y,
591 std::max(available_width, 0), location_height);
592 next_element_x = location_bar_->bounds().right();
594 browser_actions_->SetBounds(
595 next_element_x, child_y, browser_actions_width, child_height);
596 next_element_x = browser_actions_->bounds().right();
598 // The browser actions need to do a layout explicitly, because when an
599 // extension is loaded/unloaded/changed, BrowserActionContainer removes and
600 // re-adds everything, regardless of whether it has a page action. For a
601 // page action, browser action bounds do not change, as a result of which
602 // SetBounds does not do a layout at all.
603 // TODO(sidchat): Rework the above behavior so that explicit layout is not
605 browser_actions_->Layout();
607 // Extend the app menu to the screen's right edge in maximized mode just like
608 // we extend the back button to the left edge.
610 app_menu_width += kRightEdgeSpacing;
611 app_menu_->SetBounds(next_element_x, child_y, app_menu_width, child_height);
614 void ToolbarView::OnPaint(gfx::Canvas* canvas) {
615 View::OnPaint(canvas);
617 if (is_display_mode_normal())
620 // For glass, we need to draw a black line below the location bar to separate
621 // it from the content area. For non-glass, the NonClientView draws the
622 // toolbar background below the location bar for us.
623 // NOTE: Keep this in sync with BrowserView::GetInfoBarSeparatorColor()!
624 if (GetWidget()->ShouldWindowContentsBeTransparent())
625 canvas->FillRect(gfx::Rect(0, height() - 1, width(), 1), SK_ColorBLACK);
628 void ToolbarView::OnThemeChanged() {
632 const char* ToolbarView::GetClassName() const {
633 return kViewClassName;
636 bool ToolbarView::AcceleratorPressed(const ui::Accelerator& accelerator) {
637 const views::View* focused_view = focus_manager()->GetFocusedView();
638 if (focused_view && (focused_view->id() == VIEW_ID_OMNIBOX))
639 return false; // Let the omnibox handle all accelerator events.
640 return AccessiblePaneView::AcceleratorPressed(accelerator);
643 bool ToolbarView::IsWrenchMenuShowing() const {
644 return wrench_menu_.get() && wrench_menu_->IsShowing();
647 bool ToolbarView::ShouldPaintBackground() const {
648 return display_mode_ == DISPLAYMODE_NORMAL;
651 ////////////////////////////////////////////////////////////////////////////////
652 // ToolbarView, protected:
654 // Override this so that when the user presses F6 to rotate toolbar panes,
655 // the location bar gets focus, not the first control in the toolbar - and
656 // also so that it selects all content in the location bar.
657 bool ToolbarView::SetPaneFocusAndFocusDefault() {
658 if (!location_bar_->HasFocus()) {
659 SetPaneFocus(location_bar_);
660 location_bar_->FocusLocation(true);
664 if (!AccessiblePaneView::SetPaneFocusAndFocusDefault())
666 browser_->window()->RotatePaneFocus(true);
670 void ToolbarView::RemovePaneFocus() {
671 AccessiblePaneView::RemovePaneFocus();
672 location_bar_->SetShowFocusRect(false);
675 ////////////////////////////////////////////////////////////////////////////////
676 // ToolbarView, private:
678 // views::ViewTargeterDelegate:
679 bool ToolbarView::DoesIntersectRect(const views::View* target,
680 const gfx::Rect& rect) const {
681 CHECK_EQ(target, this);
683 // Fall through to the tab strip above us if none of |rect| intersects
684 // with this view (intersection with the top shadow edge does not
685 // count as intersection with this view).
686 if (rect.bottom() < content_shadow_height())
688 // Otherwise let our superclass take care of it.
689 return ViewTargeterDelegate::DoesIntersectRect(this, rect);
692 void ToolbarView::UpdateBadgeSeverity(WrenchMenuBadgeController::BadgeType type,
693 WrenchIconPainter::Severity severity,
695 // Showing the bubble requires |app_menu_| to be in a widget. See comment
696 // in ConflictingModuleView for details.
697 DCHECK(app_menu_->GetWidget());
699 base::string16 accname_app = l10n_util::GetStringUTF16(IDS_ACCNAME_APP);
700 if (type == WrenchMenuBadgeController::BADGE_TYPE_UPGRADE_NOTIFICATION) {
701 accname_app = l10n_util::GetStringFUTF16(
702 IDS_ACCNAME_APP_UPGRADE_RECOMMENDED, accname_app);
704 app_menu_->SetAccessibleName(accname_app);
705 app_menu_->SetSeverity(severity, animate);
707 // Keep track of whether we were showing the badge before, so we don't send
708 // multiple UMA events for example when multiple Chrome windows are open.
709 static bool incompatibility_badge_showing = false;
710 // Save the old value before resetting it.
711 bool was_showing = incompatibility_badge_showing;
712 incompatibility_badge_showing = false;
714 if (type == WrenchMenuBadgeController::BADGE_TYPE_INCOMPATIBILITY_WARNING) {
716 content::RecordAction(UserMetricsAction("ConflictBadge"));
718 ConflictingModuleView::MaybeShow(browser_, app_menu_);
721 incompatibility_badge_showing = true;
726 int ToolbarView::PopupTopSpacing() const {
727 const int kPopupTopSpacingNonGlass = 3;
728 return GetWidget()->ShouldWindowContentsBeTransparent() ?
729 0 : kPopupTopSpacingNonGlass;
732 gfx::Size ToolbarView::SizeForContentSize(gfx::Size size) const {
733 if (is_display_mode_normal()) {
734 gfx::ImageSkia* normal_background =
735 GetThemeProvider()->GetImageSkiaNamed(IDR_CONTENT_TOP_CENTER);
737 gfx::Size(0, normal_background->height() - content_shadow_height()));
739 const int kPopupBottomSpacingGlass = 1;
740 const int kPopupBottomSpacingNonGlass = 2;
743 PopupTopSpacing() + (GetWidget()->ShouldWindowContentsBeTransparent() ?
744 kPopupBottomSpacingGlass : kPopupBottomSpacingNonGlass));
749 void ToolbarView::LoadImages() {
750 ui::ThemeProvider* tp = GetThemeProvider();
752 back_->SetImage(views::Button::STATE_NORMAL,
753 *(tp->GetImageSkiaNamed(IDR_BACK)));
754 back_->SetImage(views::Button::STATE_DISABLED,
755 *(tp->GetImageSkiaNamed(IDR_BACK_D)));
757 forward_->SetImage(views::Button::STATE_NORMAL,
758 *(tp->GetImageSkiaNamed(IDR_FORWARD)));
759 forward_->SetImage(views::Button::STATE_DISABLED,
760 *(tp->GetImageSkiaNamed(IDR_FORWARD_D)));
762 reload_->LoadImages();
764 home_->SetImage(views::Button::STATE_NORMAL,
765 *(tp->GetImageSkiaNamed(IDR_HOME)));
768 void ToolbarView::ShowCriticalNotification() {
770 CriticalNotificationBubbleView* bubble_delegate =
771 new CriticalNotificationBubbleView(app_menu_);
772 views::BubbleDelegateView::CreateBubble(bubble_delegate)->Show();
776 void ToolbarView::ShowOutdatedInstallNotification(bool auto_update_enabled) {
777 if (OutdatedUpgradeBubbleView::IsAvailable()) {
778 OutdatedUpgradeBubbleView::ShowBubble(
779 app_menu_, browser_, auto_update_enabled);
783 void ToolbarView::OnShowHomeButtonChanged() {
788 int ToolbarView::content_shadow_height() const {
789 return browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH ?
790 kContentShadowHeightAsh : kContentShadowHeight;