Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: chrome/browser/ui/views/toolbar_view.cc

Issue 71743002: [Toolbar Views] Move toolbar files to a new subdirectory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2012 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 #include "chrome/browser/ui/views/toolbar_view.h"
6
7 #include "base/command_line.h"
8 #include "base/debug/trace_event.h"
9 #include "base/i18n/number_formatting.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/app/chrome_command_ids.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/command_updater.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/themes/theme_service.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_command_controller.h"
19 #include "chrome/browser/ui/browser_commands.h"
20 #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h"
21 #include "chrome/browser/ui/browser_instant_controller.h"
22 #include "chrome/browser/ui/browser_tabstrip.h"
23 #include "chrome/browser/ui/browser_window.h"
24 #include "chrome/browser/ui/global_error/global_error_service.h"
25 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
26 #include "chrome/browser/ui/omnibox/omnibox_view.h"
27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
28 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
29 #include "chrome/browser/ui/view_ids.h"
30 #include "chrome/browser/ui/views/browser_actions_container.h"
31 #include "chrome/browser/ui/views/frame/browser_view.h"
32 #include "chrome/browser/ui/views/home_button.h"
33 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
34 #include "chrome/browser/ui/views/location_bar/star_view.h"
35 #include "chrome/browser/ui/views/location_bar/translate_icon_view.h"
36 #include "chrome/browser/ui/views/outdated_upgrade_bubble_view.h"
37 #include "chrome/browser/ui/views/wrench_menu.h"
38 #include "chrome/browser/ui/views/wrench_toolbar_button.h"
39 #include "chrome/browser/upgrade_detector.h"
40 #include "chrome/common/chrome_switches.h"
41 #include "chrome/common/pref_names.h"
42 #include "content/public/browser/browser_accessibility_state.h"
43 #include "content/public/browser/notification_service.h"
44 #include "content/public/browser/render_view_host.h"
45 #include "content/public/browser/user_metrics.h"
46 #include "content/public/browser/web_contents.h"
47 #include "content/public/browser/web_contents_view.h"
48 #include "grit/chromium_strings.h"
49 #include "grit/generated_resources.h"
50 #include "grit/theme_resources.h"
51 #include "ui/base/accessibility/accessible_view_state.h"
52 #include "ui/base/l10n/l10n_util.h"
53 #include "ui/base/layout.h"
54 #include "ui/base/theme_provider.h"
55 #include "ui/base/window_open_disposition.h"
56 #include "ui/gfx/canvas.h"
57 #include "ui/gfx/image/canvas_image_source.h"
58 #include "ui/views/controls/button/button_dropdown.h"
59 #include "ui/views/controls/menu/menu_listener.h"
60 #include "ui/views/focus/view_storage.h"
61 #include "ui/views/widget/tooltip_manager.h"
62 #include "ui/views/widget/widget.h"
63 #include "ui/views/window/non_client_view.h"
64
65 #if defined(OS_WIN)
66 #include "base/win/windows_version.h"
67 #include "chrome/browser/enumerate_modules_model_win.h"
68 #include "chrome/browser/ui/views/conflicting_module_view_win.h"
69 #include "chrome/browser/ui/views/critical_notification_bubble_view.h"
70 #if !defined(USE_AURA)
71 #include "chrome/browser/ui/views/app_menu_button_win.h"
72 #endif
73 #endif
74
75 #if defined(USE_AURA)
76 #include "ui/aura/window.h"
77 #include "ui/compositor/layer.h"
78 #include "ui/native_theme/native_theme_aura.h"
79 #endif
80
81 using content::UserMetricsAction;
82 using content::WebContents;
83
84 namespace {
85
86 // The edge graphics have some built-in spacing/shadowing, so we have to adjust
87 // our spacing to make it match.
88 const int kLeftEdgeSpacing = 3;
89 const int kRightEdgeSpacing = 2;
90
91 // Ash doesn't use a rounded content area and its top edge has an extra shadow.
92 const int kContentShadowHeightAsh = 2;
93
94 // Non-ash uses a rounded content area with no shadow in the assets.
95 const int kContentShadowHeight = 0;
96
97 int GetButtonSpacing() {
98 return (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) ?
99 ToolbarView::kStandardSpacing : 0;
100 }
101
102 bool IsStreamlinedHostedAppsEnabled() {
103 return CommandLine::ForCurrentProcess()->HasSwitch(
104 switches::kEnableStreamlinedHostedApps);
105 }
106
107 } // namespace
108
109 // static
110 const char ToolbarView::kViewClassName[] = "ToolbarView";
111
112 // The space between items is 3 px in general.
113 const int ToolbarView::kStandardSpacing = 3;
114 // The top of the toolbar has an edge we have to skip over in addition to the
115 // above spacing.
116 const int ToolbarView::kVertSpacing = 5;
117
118 ////////////////////////////////////////////////////////////////////////////////
119 // ToolbarView, public:
120
121 ToolbarView::ToolbarView(Browser* browser)
122 : back_(NULL),
123 forward_(NULL),
124 reload_(NULL),
125 home_(NULL),
126 location_bar_(NULL),
127 browser_actions_(NULL),
128 app_menu_(NULL),
129 browser_(browser) {
130 set_id(VIEW_ID_TOOLBAR);
131
132 chrome::AddCommandObserver(browser_, IDC_BACK, this);
133 chrome::AddCommandObserver(browser_, IDC_FORWARD, this);
134 chrome::AddCommandObserver(browser_, IDC_RELOAD, this);
135 chrome::AddCommandObserver(browser_, IDC_HOME, this);
136 chrome::AddCommandObserver(browser_, IDC_LOAD_NEW_TAB_PAGE, this);
137
138 display_mode_ = DISPLAYMODE_LOCATION;
139 if (browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP) ||
140 (browser->is_app() && IsStreamlinedHostedAppsEnabled()))
141 display_mode_ = DISPLAYMODE_NORMAL;
142
143 registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
144 content::NotificationService::AllSources());
145 if (OutdatedUpgradeBubbleView::IsAvailable()) {
146 registrar_.Add(this, chrome::NOTIFICATION_OUTDATED_INSTALL,
147 content::NotificationService::AllSources());
148 }
149 #if defined(OS_WIN)
150 registrar_.Add(this, chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
151 content::NotificationService::AllSources());
152 if (base::win::GetVersion() == base::win::VERSION_XP) {
153 registrar_.Add(this, chrome::NOTIFICATION_MODULE_LIST_ENUMERATED,
154 content::NotificationService::AllSources());
155 }
156 #endif
157 registrar_.Add(this,
158 chrome::NOTIFICATION_MODULE_INCOMPATIBILITY_BADGE_CHANGE,
159 content::NotificationService::AllSources());
160 registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED,
161 content::Source<Profile>(browser_->profile()));
162 }
163
164 ToolbarView::~ToolbarView() {
165 // NOTE: Don't remove the command observers here. This object gets destroyed
166 // after the Browser (which owns the CommandUpdater), so the CommandUpdater is
167 // already gone.
168 }
169
170 void ToolbarView::Init() {
171 back_ = new views::ButtonDropDown(this, new BackForwardMenuModel(
172 browser_, BackForwardMenuModel::BACKWARD_MENU));
173 back_->set_triggerable_event_flags(
174 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON);
175 back_->set_tag(IDC_BACK);
176 back_->SetImageAlignment(views::ImageButton::ALIGN_RIGHT,
177 views::ImageButton::ALIGN_TOP);
178 back_->SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_BACK));
179 back_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_BACK));
180 back_->set_id(VIEW_ID_BACK_BUTTON);
181
182 forward_ = new views::ButtonDropDown(
183 this,
184 new BackForwardMenuModel(browser_, BackForwardMenuModel::FORWARD_MENU));
185 forward_->set_triggerable_event_flags(
186 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON);
187 forward_->set_tag(IDC_FORWARD);
188 forward_->SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_FORWARD));
189 forward_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_FORWARD));
190 forward_->set_id(VIEW_ID_FORWARD_BUTTON);
191
192 // Have to create this before |reload_| as |reload_|'s constructor needs it.
193 location_bar_ = new LocationBarView(
194 browser_, browser_->profile(),
195 browser_->command_controller()->command_updater(), this,
196 display_mode_ == DISPLAYMODE_LOCATION ||
197 (browser_->is_app() && IsStreamlinedHostedAppsEnabled()));
198
199 reload_ = new ReloadButton(location_bar_,
200 browser_->command_controller()->command_updater());
201 reload_->set_triggerable_event_flags(
202 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON);
203 reload_->set_tag(IDC_RELOAD);
204 reload_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_RELOAD));
205 reload_->set_id(VIEW_ID_RELOAD_BUTTON);
206
207 home_ = new HomeImageButton(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);
214
215 browser_actions_ = new BrowserActionsContainer(browser_, this);
216
217 #if defined(OS_WIN) && !defined(USE_AURA)
218 app_menu_ = new AppMenuButtonWin(this);
219 #else
220 app_menu_ = new WrenchToolbarButton(this);
221 #endif
222 app_menu_->set_border(NULL);
223 app_menu_->EnableCanvasFlippingForRTLUI(true);
224 app_menu_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_APP));
225 app_menu_->SetTooltipText(l10n_util::GetStringUTF16(IDS_APPMENU_TOOLTIP));
226 app_menu_->set_id(VIEW_ID_APP_MENU);
227
228 LoadImages();
229
230 // Always add children in order from left to right, for accessibility.
231 AddChildView(back_);
232 AddChildView(forward_);
233 AddChildView(reload_);
234 AddChildView(home_);
235 AddChildView(location_bar_);
236 AddChildView(browser_actions_);
237 AddChildView(app_menu_);
238
239 // Add any necessary badges to the menu item based on the system state.
240 // Do this after |app_menu_| has been added as a bubble may be shown that
241 // needs the widget (widget found by way of app_menu_->GetWidget()).
242 UpdateAppMenuState();
243
244 location_bar_->Init();
245 show_home_button_.Init(prefs::kShowHomeButton,
246 browser_->profile()->GetPrefs(),
247 base::Bind(&ToolbarView::OnShowHomeButtonChanged,
248 base::Unretained(this)));
249
250 browser_actions_->Init();
251
252 // Accessibility specific tooltip text.
253 if (content::BrowserAccessibilityState::GetInstance()->
254 IsAccessibleBrowser()) {
255 back_->SetTooltipText(
256 l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLTIP_BACK));
257 forward_->SetTooltipText(
258 l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLTIP_FORWARD));
259 }
260 }
261
262 void ToolbarView::Update(WebContents* tab) {
263 if (location_bar_)
264 location_bar_->Update(tab);
265
266 if (browser_actions_)
267 browser_actions_->RefreshBrowserActionViews();
268
269 if (reload_)
270 reload_->set_menu_enabled(chrome::IsDebuggerAttachedToCurrentTab(browser_));
271 }
272
273 void ToolbarView::SetPaneFocusAndFocusAppMenu() {
274 SetPaneFocus(app_menu_);
275 }
276
277 bool ToolbarView::IsAppMenuFocused() {
278 return app_menu_->HasFocus();
279 }
280
281 void ToolbarView::AddMenuListener(views::MenuListener* listener) {
282 menu_listeners_.AddObserver(listener);
283 }
284
285 void ToolbarView::RemoveMenuListener(views::MenuListener* listener) {
286 menu_listeners_.RemoveObserver(listener);
287 }
288
289 views::View* ToolbarView::GetBookmarkBubbleAnchor() {
290 views::View* star_view = location_bar()->star_view();
291 return (star_view && star_view->visible()) ? star_view : app_menu_;
292 }
293
294 views::View* ToolbarView::GetTranslateBubbleAnchor() {
295 views::View* translate_icon_view = location_bar()->translate_icon_view();
296 return (translate_icon_view && translate_icon_view->visible()) ?
297 translate_icon_view : app_menu_;
298 }
299
300 views::MenuButton* ToolbarView::app_menu() const {
301 return app_menu_;
302 }
303
304 ////////////////////////////////////////////////////////////////////////////////
305 // ToolbarView, AccessiblePaneView overrides:
306
307 bool ToolbarView::SetPaneFocus(views::View* initial_focus) {
308 if (!AccessiblePaneView::SetPaneFocus(initial_focus))
309 return false;
310
311 location_bar_->SetShowFocusRect(true);
312 return true;
313 }
314
315 void ToolbarView::GetAccessibleState(ui::AccessibleViewState* state) {
316 state->role = ui::AccessibilityTypes::ROLE_TOOLBAR;
317 state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLBAR);
318 }
319
320 ////////////////////////////////////////////////////////////////////////////////
321 // ToolbarView, Menu::Delegate overrides:
322
323 bool ToolbarView::GetAcceleratorInfo(int id, ui::Accelerator* accel) {
324 return GetWidget()->GetAccelerator(id, accel);
325 }
326
327 ////////////////////////////////////////////////////////////////////////////////
328 // ToolbarView, views::MenuButtonListener implementation:
329
330 void ToolbarView::OnMenuButtonClicked(views::View* source,
331 const gfx::Point& point) {
332 TRACE_EVENT0("views", "ToolbarView::OnMenuButtonClicked");
333 DCHECK_EQ(VIEW_ID_APP_MENU, source->id());
334
335 bool use_new_menu = false;
336 bool supports_new_separators = false;
337 // TODO: remove this.
338 #if defined(USE_AURA)
339 supports_new_separators =
340 GetNativeTheme() == ui::NativeThemeAura::instance();
341 use_new_menu = supports_new_separators;
342 #endif
343 #if defined(OS_WIN)
344 use_new_menu = use_new_menu || ui::GetDisplayLayout() == ui::LAYOUT_TOUCH;
345 #endif
346
347 wrench_menu_.reset(new WrenchMenu(browser_, use_new_menu,
348 supports_new_separators));
349 wrench_menu_model_.reset(new WrenchMenuModel(this, browser_, use_new_menu));
350 wrench_menu_->Init(wrench_menu_model_.get());
351
352 FOR_EACH_OBSERVER(views::MenuListener, menu_listeners_, OnMenuOpened());
353
354 wrench_menu_->RunMenu(app_menu_);
355 }
356
357 ////////////////////////////////////////////////////////////////////////////////
358 // ToolbarView, LocationBarView::Delegate implementation:
359
360 WebContents* ToolbarView::GetWebContents() {
361 return browser_->tab_strip_model()->GetActiveWebContents();
362 }
363
364 ToolbarModel* ToolbarView::GetToolbarModel() {
365 return browser_->toolbar_model();
366 }
367
368 const ToolbarModel* ToolbarView::GetToolbarModel() const {
369 return browser_->toolbar_model();
370 }
371
372 InstantController* ToolbarView::GetInstant() {
373 return browser_->instant_controller() ?
374 browser_->instant_controller()->instant() : NULL;
375 }
376
377 ContentSettingBubbleModelDelegate*
378 ToolbarView::GetContentSettingBubbleModelDelegate() {
379 return browser_->content_setting_bubble_model_delegate();
380 }
381
382 void ToolbarView::ShowWebsiteSettings(content::WebContents* web_contents,
383 const GURL& url,
384 const content::SSLStatus& ssl) {
385 chrome::ShowWebsiteSettings(browser_, web_contents, url, ssl);
386 }
387
388 views::Widget* ToolbarView::CreateViewsBubble(
389 views::BubbleDelegateView* bubble_delegate) {
390 return views::BubbleDelegateView::CreateBubble(bubble_delegate);
391 }
392
393 PageActionImageView* ToolbarView::CreatePageActionImageView(
394 LocationBarView* owner, ExtensionAction* action) {
395 return new PageActionImageView(owner, action, browser_);
396 }
397
398 ////////////////////////////////////////////////////////////////////////////////
399 // ToolbarView, CommandObserver implementation:
400
401 void ToolbarView::EnabledStateChangedForCommand(int id, bool enabled) {
402 views::Button* button = NULL;
403 switch (id) {
404 case IDC_BACK:
405 button = back_;
406 break;
407 case IDC_FORWARD:
408 button = forward_;
409 break;
410 case IDC_RELOAD:
411 button = reload_;
412 break;
413 case IDC_HOME:
414 button = home_;
415 break;
416 }
417 if (button)
418 button->SetEnabled(enabled);
419 }
420
421 ////////////////////////////////////////////////////////////////////////////////
422 // ToolbarView, views::Button::ButtonListener implementation:
423
424 void ToolbarView::ButtonPressed(views::Button* sender,
425 const ui::Event& event) {
426 int command = sender->tag();
427 WindowOpenDisposition disposition =
428 ui::DispositionFromEventFlags(event.flags());
429 if ((disposition == CURRENT_TAB) &&
430 ((command == IDC_BACK) || (command == IDC_FORWARD))) {
431 // Forcibly reset the location bar, since otherwise it won't discard any
432 // ongoing user edits, since it doesn't realize this is a user-initiated
433 // action.
434 location_bar_->Revert();
435 }
436 chrome::ExecuteCommandWithDisposition(browser_, command, disposition);
437 }
438
439 ////////////////////////////////////////////////////////////////////////////////
440 // ToolbarView, content::NotificationObserver implementation:
441
442 void ToolbarView::Observe(int type,
443 const content::NotificationSource& source,
444 const content::NotificationDetails& details) {
445 switch (type) {
446 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED:
447 case chrome::NOTIFICATION_MODULE_INCOMPATIBILITY_BADGE_CHANGE:
448 case chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED:
449 case chrome::NOTIFICATION_MODULE_LIST_ENUMERATED:
450 UpdateAppMenuState();
451 break;
452 case chrome::NOTIFICATION_OUTDATED_INSTALL:
453 ShowOutdatedInstallNotification();
454 break;
455 #if defined(OS_WIN)
456 case chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED:
457 ShowCriticalNotification();
458 break;
459 #endif
460 default:
461 NOTREACHED();
462 }
463 }
464
465 ////////////////////////////////////////////////////////////////////////////////
466 // ToolbarView, ui::AcceleratorProvider implementation:
467
468 bool ToolbarView::GetAcceleratorForCommandId(int command_id,
469 ui::Accelerator* accelerator) {
470 return GetWidget()->GetAccelerator(command_id, accelerator);
471 }
472
473 ////////////////////////////////////////////////////////////////////////////////
474 // ToolbarView, views::View overrides:
475
476 gfx::Size ToolbarView::GetPreferredSize() {
477 if (is_display_mode_normal()) {
478 int button_spacing = GetButtonSpacing();
479 int min_width = kLeftEdgeSpacing +
480 back_->GetPreferredSize().width() + button_spacing +
481 forward_->GetPreferredSize().width() + button_spacing +
482 reload_->GetPreferredSize().width() + kStandardSpacing +
483 (show_home_button_.GetValue() ?
484 (home_->GetPreferredSize().width() + button_spacing) : 0) +
485 location_bar_->GetPreferredSize().width() +
486 browser_actions_->GetPreferredSize().width() +
487 app_menu_->GetPreferredSize().width() + kRightEdgeSpacing;
488 gfx::ImageSkia* normal_background =
489 GetThemeProvider()->GetImageSkiaNamed(IDR_CONTENT_TOP_CENTER);
490 return gfx::Size(min_width,
491 normal_background->height() - content_shadow_height());
492 }
493
494 const int kPopupBottomSpacingGlass = 1;
495 const int kPopupBottomSpacingNonGlass = 2;
496 int vertical_spacing = PopupTopSpacing() +
497 (GetWidget()->ShouldUseNativeFrame() ?
498 kPopupBottomSpacingGlass : kPopupBottomSpacingNonGlass);
499 return gfx::Size(0, location_bar_->GetPreferredSize().height() +
500 vertical_spacing);
501 }
502
503 void ToolbarView::Layout() {
504 // If we have not been initialized yet just do nothing.
505 if (back_ == NULL)
506 return;
507
508 if (!is_display_mode_normal()) {
509 location_bar_->SetBounds(0, PopupTopSpacing(), width(),
510 location_bar_->GetPreferredSize().height());
511 return;
512 }
513
514 // We assume all child elements except the location bar are the same height.
515 // Set child_y such that buttons appear vertically centered. We put any excess
516 // padding above the buttons.
517 int child_height =
518 std::min(back_->GetPreferredSize().height(), height());
519 int child_y = (height() - child_height + 1) / 2;
520
521 // If the window is maximized, we extend the back button to the left so that
522 // clicking on the left-most pixel will activate the back button.
523 // TODO(abarth): If the window becomes maximized but is not resized,
524 // then Layout() might not be called and the back button
525 // will be slightly the wrong size. We should force a
526 // Layout() in this case.
527 // http://crbug.com/5540
528 bool maximized = browser_->window() && browser_->window()->IsMaximized();
529 int back_width = back_->GetPreferredSize().width();
530 if (maximized)
531 back_->SetBounds(0, child_y, back_width + kLeftEdgeSpacing, child_height);
532 else
533 back_->SetBounds(kLeftEdgeSpacing, child_y, back_width, child_height);
534
535 int button_spacing = GetButtonSpacing();
536 forward_->SetBounds(back_->x() + back_->width() + button_spacing,
537 child_y, forward_->GetPreferredSize().width(), child_height);
538
539 reload_->SetBounds(forward_->x() + forward_->width() + button_spacing,
540 child_y, reload_->GetPreferredSize().width(), child_height);
541
542 if (show_home_button_.GetValue()) {
543 home_->SetVisible(true);
544 home_->SetBounds(reload_->x() + reload_->width() + button_spacing,
545 child_y, home_->GetPreferredSize().width(), child_height);
546 } else {
547 home_->SetVisible(false);
548 home_->SetBounds(reload_->x() + reload_->width(), child_y, 0, child_height);
549 }
550
551 int browser_actions_width = browser_actions_->GetPreferredSize().width();
552 int app_menu_width = app_menu_->GetPreferredSize().width();
553 int location_x = home_->x() + home_->width() + kStandardSpacing;
554 int available_width = std::max(0, width() - kRightEdgeSpacing -
555 app_menu_width - browser_actions_width - location_x);
556
557 int location_height = location_bar_->GetPreferredSize().height();
558 int location_y = (height() - location_height + 1) / 2;
559 location_bar_->SetBounds(location_x, location_y, std::max(available_width, 0),
560 location_height);
561
562 browser_actions_->SetBounds(location_bar_->x() + location_bar_->width(), 0,
563 browser_actions_width, height());
564 // The browser actions need to do a layout explicitly, because when an
565 // extension is loaded/unloaded/changed, BrowserActionContainer removes and
566 // re-adds everything, regardless of whether it has a page action. For a
567 // page action, browser action bounds do not change, as a result of which
568 // SetBounds does not do a layout at all.
569 // TODO(sidchat): Rework the above behavior so that explicit layout is not
570 // required.
571 browser_actions_->Layout();
572
573 // Extend the app menu to the screen's right edge in maximized mode just like
574 // we extend the back button to the left edge.
575 if (maximized)
576 app_menu_width += kRightEdgeSpacing;
577 app_menu_->SetBounds(browser_actions_->x() + browser_actions_width, child_y,
578 app_menu_width, child_height);
579 }
580
581 bool ToolbarView::HitTestRect(const gfx::Rect& rect) const {
582 // Fall through to the tab strip above us if none of |rect| intersects
583 // with this view (intersection with the top shadow edge does not
584 // count as intersection with this view).
585 if (rect.bottom() < content_shadow_height())
586 return false;
587 // Otherwise let our superclass take care of it.
588 return AccessiblePaneView::HitTestRect(rect);
589 }
590
591 void ToolbarView::OnPaint(gfx::Canvas* canvas) {
592 View::OnPaint(canvas);
593
594 if (is_display_mode_normal())
595 return;
596
597 // For glass, we need to draw a black line below the location bar to separate
598 // it from the content area. For non-glass, the NonClientView draws the
599 // toolbar background below the location bar for us.
600 // NOTE: Keep this in sync with BrowserView::GetInfoBarSeparatorColor()!
601 if (GetWidget()->ShouldUseNativeFrame())
602 canvas->FillRect(gfx::Rect(0, height() - 1, width(), 1), SK_ColorBLACK);
603 }
604
605 // Note this method is ignored on Windows, but needs to be implemented for
606 // linux, where it is called before CanDrop().
607 bool ToolbarView::GetDropFormats(
608 int* formats,
609 std::set<OSExchangeData::CustomFormat>* custom_formats) {
610 *formats = ui::OSExchangeData::URL | ui::OSExchangeData::STRING;
611 return true;
612 }
613
614 bool ToolbarView::CanDrop(const ui::OSExchangeData& data) {
615 // To support loading URLs by dropping into the toolbar, we need to support
616 // dropping URLs and/or text.
617 return data.HasURL() || data.HasString();
618 }
619
620 int ToolbarView::OnDragUpdated(const ui::DropTargetEvent& event) {
621 if (event.source_operations() & ui::DragDropTypes::DRAG_COPY) {
622 return ui::DragDropTypes::DRAG_COPY;
623 } else if (event.source_operations() & ui::DragDropTypes::DRAG_LINK) {
624 return ui::DragDropTypes::DRAG_LINK;
625 }
626 return ui::DragDropTypes::DRAG_NONE;
627 }
628
629 int ToolbarView::OnPerformDrop(const ui::DropTargetEvent& event) {
630 return location_bar_->GetLocationEntry()->OnPerformDrop(event);
631 }
632
633 void ToolbarView::OnThemeChanged() {
634 LoadImages();
635 }
636
637 const char* ToolbarView::GetClassName() const {
638 return kViewClassName;
639 }
640
641 bool ToolbarView::AcceleratorPressed(const ui::Accelerator& accelerator) {
642 const views::View* focused_view = focus_manager()->GetFocusedView();
643 if (focused_view && (focused_view->id() == VIEW_ID_OMNIBOX))
644 return false; // Let the omnibox handle all accelerator events.
645 return AccessiblePaneView::AcceleratorPressed(accelerator);
646 }
647
648 bool ToolbarView::IsWrenchMenuShowing() const {
649 return wrench_menu_.get() && wrench_menu_->IsShowing();
650 }
651
652 bool ToolbarView::ShouldPaintBackground() const {
653 return display_mode_ == DISPLAYMODE_NORMAL;
654 }
655
656 ////////////////////////////////////////////////////////////////////////////////
657 // ToolbarView, protected:
658
659 // Override this so that when the user presses F6 to rotate toolbar panes,
660 // the location bar gets focus, not the first control in the toolbar - and
661 // also so that it selects all content in the location bar.
662 bool ToolbarView::SetPaneFocusAndFocusDefault() {
663 if (!location_bar_->HasFocus()) {
664 SetPaneFocus(location_bar_);
665 location_bar_->FocusLocation(true);
666 return true;
667 }
668
669 if (!AccessiblePaneView::SetPaneFocusAndFocusDefault())
670 return false;
671 browser_->window()->RotatePaneFocus(true);
672 return true;
673 }
674
675 void ToolbarView::RemovePaneFocus() {
676 AccessiblePaneView::RemovePaneFocus();
677 location_bar_->SetShowFocusRect(false);
678 }
679
680 ////////////////////////////////////////////////////////////////////////////////
681 // ToolbarView, private:
682
683 bool ToolbarView::ShouldShowUpgradeRecommended() {
684 #if defined(OS_CHROMEOS)
685 // In chromeos, the update recommendation is shown in the system tray. So it
686 // should not be displayed in the wrench menu.
687 return false;
688 #else
689 return (UpgradeDetector::GetInstance()->notify_upgrade());
690 #endif
691 }
692
693 bool ToolbarView::ShouldShowIncompatibilityWarning() {
694 #if defined(OS_WIN)
695 EnumerateModulesModel* loaded_modules = EnumerateModulesModel::GetInstance();
696 loaded_modules->MaybePostScanningTask();
697 return loaded_modules->ShouldShowConflictWarning();
698 #else
699 return false;
700 #endif
701 }
702
703 int ToolbarView::PopupTopSpacing() const {
704 const int kPopupTopSpacingNonGlass = 3;
705 return GetWidget()->ShouldUseNativeFrame() ? 0 : kPopupTopSpacingNonGlass;
706 }
707
708 void ToolbarView::LoadImages() {
709 ui::ThemeProvider* tp = GetThemeProvider();
710
711 back_->SetImage(views::CustomButton::STATE_NORMAL,
712 tp->GetImageSkiaNamed(IDR_BACK));
713 back_->SetImage(views::CustomButton::STATE_HOVERED,
714 tp->GetImageSkiaNamed(IDR_BACK_H));
715 back_->SetImage(views::CustomButton::STATE_PRESSED,
716 tp->GetImageSkiaNamed(IDR_BACK_P));
717 back_->SetImage(views::CustomButton::STATE_DISABLED,
718 tp->GetImageSkiaNamed(IDR_BACK_D));
719
720 forward_->SetImage(views::CustomButton::STATE_NORMAL,
721 tp->GetImageSkiaNamed(IDR_FORWARD));
722 forward_->SetImage(views::CustomButton::STATE_HOVERED,
723 tp->GetImageSkiaNamed(IDR_FORWARD_H));
724 forward_->SetImage(views::CustomButton::STATE_PRESSED,
725 tp->GetImageSkiaNamed(IDR_FORWARD_P));
726 forward_->SetImage(views::CustomButton::STATE_DISABLED,
727 tp->GetImageSkiaNamed(IDR_FORWARD_D));
728
729 reload_->LoadImages(tp);
730
731 home_->SetImage(views::CustomButton::STATE_NORMAL,
732 tp->GetImageSkiaNamed(IDR_HOME));
733 home_->SetImage(views::CustomButton::STATE_HOVERED,
734 tp->GetImageSkiaNamed(IDR_HOME_H));
735 home_->SetImage(views::CustomButton::STATE_PRESSED,
736 tp->GetImageSkiaNamed(IDR_HOME_P));
737 }
738
739 void ToolbarView::ShowCriticalNotification() {
740 #if defined(OS_WIN)
741 CriticalNotificationBubbleView* bubble_delegate =
742 new CriticalNotificationBubbleView(app_menu_);
743 views::BubbleDelegateView::CreateBubble(bubble_delegate);
744 bubble_delegate->StartFade(true);
745 #endif
746 }
747
748 void ToolbarView::ShowOutdatedInstallNotification() {
749 if (OutdatedUpgradeBubbleView::IsAvailable())
750 OutdatedUpgradeBubbleView::ShowBubble(app_menu_, browser_);
751 }
752
753 void ToolbarView::UpdateAppMenuState() {
754 string16 accname_app = l10n_util::GetStringUTF16(IDS_ACCNAME_APP);
755 if (ShouldShowUpgradeRecommended()) {
756 accname_app = l10n_util::GetStringFUTF16(
757 IDS_ACCNAME_APP_UPGRADE_RECOMMENDED, accname_app);
758 }
759 app_menu_->SetAccessibleName(accname_app);
760
761 UpdateWrenchButtonSeverity();
762 SchedulePaint();
763 }
764
765 void ToolbarView::UpdateWrenchButtonSeverity() {
766 // Showing the bubble requires |app_menu_| to be in a widget. See comment
767 // in ConflictingModuleView for details.
768 DCHECK(app_menu_->GetWidget());
769
770 // Keep track of whether we were showing the badge before, so we don't send
771 // multiple UMA events for example when multiple Chrome windows are open.
772 static bool incompatibility_badge_showing = false;
773 // Save the old value before resetting it.
774 bool was_showing = incompatibility_badge_showing;
775 incompatibility_badge_showing = false;
776
777 if (ShouldShowUpgradeRecommended()) {
778 UpgradeDetector::UpgradeNotificationAnnoyanceLevel level =
779 UpgradeDetector::GetInstance()->upgrade_notification_stage();
780 app_menu_->SetSeverity(WrenchIconPainter::SeverityFromUpgradeLevel(level),
781 WrenchIconPainter::ShouldAnimateUpgradeLevel(level));
782 return;
783 }
784
785 if (ShouldShowIncompatibilityWarning()) {
786 if (!was_showing) {
787 content::RecordAction(UserMetricsAction("ConflictBadge"));
788 #if defined(OS_WIN)
789 ConflictingModuleView::MaybeShow(browser_, app_menu_);
790 #endif
791 }
792 app_menu_->SetSeverity(WrenchIconPainter::SEVERITY_MEDIUM, true);
793 incompatibility_badge_showing = true;
794 return;
795 }
796
797 GlobalErrorService* service =
798 GlobalErrorServiceFactory::GetForProfile(browser_->profile());
799 GlobalError* error =
800 service->GetHighestSeverityGlobalErrorWithWrenchMenuItem();
801 if (error) {
802 app_menu_->SetSeverity(WrenchIconPainter::GlobalErrorSeverity(), true);
803 return;
804 }
805
806 app_menu_->SetSeverity(WrenchIconPainter::SEVERITY_NONE, true);
807 }
808
809 void ToolbarView::OnShowHomeButtonChanged() {
810 Layout();
811 SchedulePaint();
812 }
813
814 int ToolbarView::content_shadow_height() const {
815 return browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH ?
816 kContentShadowHeightAsh : kContentShadowHeight;
817 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698