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

Side by Side Diff: chrome/browser/ui/toolbar/wrench_menu_model.cc

Issue 1417423003: chrome: Rename WrenchMenuModel to AppMenuModel. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
OLDNEW
(Empty)
1 // Copyright (c) 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/toolbar/wrench_menu_model.h"
6
7 #include <algorithm>
8 #include <cmath>
9
10 #include "base/command_line.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/app/chrome_command_ids.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/defaults.h"
19 #include "chrome/browser/extensions/extension_util.h"
20 #include "chrome/browser/prefs/incognito_mode_prefs.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/search/search.h"
24 #include "chrome/browser/signin/signin_manager_factory.h"
25 #include "chrome/browser/signin/signin_ui_util.h"
26 #include "chrome/browser/task_manager/task_manager.h"
27 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
28 #include "chrome/browser/ui/browser.h"
29 #include "chrome/browser/ui/browser_commands.h"
30 #include "chrome/browser/ui/browser_finder.h"
31 #include "chrome/browser/ui/browser_window.h"
32 #include "chrome/browser/ui/global_error/global_error.h"
33 #include "chrome/browser/ui/global_error/global_error_service.h"
34 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
35 #include "chrome/browser/ui/tabs/tab_strip_model.h"
36 #include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h"
37 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
38 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
39 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
40 #include "chrome/browser/upgrade_detector.h"
41 #include "chrome/common/chrome_paths.h"
42 #include "chrome/common/chrome_switches.h"
43 #include "chrome/common/profiling.h"
44 #include "chrome/grit/chromium_strings.h"
45 #include "chrome/grit/generated_resources.h"
46 #include "components/bookmarks/common/bookmark_pref_names.h"
47 #include "components/dom_distiller/core/dom_distiller_switches.h"
48 #include "components/signin/core/browser/signin_manager.h"
49 #include "components/signin/core/common/profile_management_switches.h"
50 #include "components/ui/zoom/zoom_controller.h"
51 #include "components/ui/zoom/zoom_event_manager.h"
52 #include "content/public/browser/host_zoom_map.h"
53 #include "content/public/browser/navigation_entry.h"
54 #include "content/public/browser/notification_service.h"
55 #include "content/public/browser/notification_source.h"
56 #include "content/public/browser/notification_types.h"
57 #include "content/public/browser/user_metrics.h"
58 #include "content/public/browser/web_contents.h"
59 #include "extensions/common/feature_switch.h"
60 #include "grit/theme_resources.h"
61 #include "ui/base/l10n/l10n_util.h"
62 #include "ui/base/layout.h"
63 #include "ui/base/models/button_menu_item_model.h"
64 #include "ui/base/resource/resource_bundle.h"
65 #include "ui/gfx/image/image.h"
66 #include "ui/gfx/image/image_skia.h"
67
68 #if defined(OS_CHROMEOS)
69 #include "chromeos/chromeos_switches.h"
70 #endif
71
72 #if defined(OS_WIN)
73 #include "base/win/metro.h"
74 #include "base/win/windows_version.h"
75 #include "chrome/browser/enumerate_modules_model_win.h"
76 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
77 #include "content/public/browser/gpu_data_manager.h"
78 #endif
79
80 #if defined(USE_ASH)
81 #include "ash/shell.h"
82 #endif
83
84 using base::UserMetricsAction;
85 using content::WebContents;
86
87 namespace {
88
89 #if defined(OS_MACOSX)
90 // An empty command used because of a bug in AppKit menus.
91 // See comment in CreateActionToolbarOverflowMenu().
92 const int kEmptyMenuItemCommand = 0;
93 #endif
94
95 // Conditionally return the update app menu item title based on upgrade detector
96 // state.
97 base::string16 GetUpgradeDialogMenuItemName() {
98 if (UpgradeDetector::GetInstance()->is_outdated_install() ||
99 UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
100 return l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_MENU_ITEM);
101 } else {
102 return l10n_util::GetStringUTF16(IDS_UPDATE_NOW);
103 }
104 }
105
106 #if defined(OS_WIN)
107 bool GetRestartMenuItemIfRequired(const chrome::HostDesktopType& desktop_type,
108 int* command_id,
109 int* string_id) {
110 if (base::win::GetVersion() == base::win::VERSION_WIN8 ||
111 base::win::GetVersion() == base::win::VERSION_WIN8_1) {
112 if (desktop_type != chrome::HOST_DESKTOP_TYPE_ASH) {
113 *command_id = IDC_WIN8_METRO_RESTART;
114 *string_id = IDS_WIN8_METRO_RESTART;
115 } else {
116 *command_id = IDC_WIN_DESKTOP_RESTART;
117 *string_id = IDS_WIN_DESKTOP_RESTART;
118 }
119 return true;
120 }
121
122 // Windows 7 ASH mode is only supported in DEBUG for now.
123 #if !defined(NDEBUG)
124 // Windows 8 can support ASH mode using WARP, but Windows 7 requires a working
125 // GPU compositor.
126 if (base::win::GetVersion() == base::win::VERSION_WIN7 &&
127 content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
128 if (desktop_type != chrome::HOST_DESKTOP_TYPE_ASH) {
129 *command_id = IDC_WIN_CHROMEOS_RESTART;
130 *string_id = IDS_WIN_CHROMEOS_RESTART;
131 } else {
132 *command_id = IDC_WIN_DESKTOP_RESTART;
133 *string_id = IDS_WIN_DESKTOP_RESTART;
134 }
135 return true;
136 }
137 #endif
138 return false;
139 }
140 #endif
141
142 } // namespace
143
144 ////////////////////////////////////////////////////////////////////////////////
145 // EncodingMenuModel
146
147 EncodingMenuModel::EncodingMenuModel(Browser* browser)
148 : ui::SimpleMenuModel(this),
149 browser_(browser) {
150 Build();
151 }
152
153 EncodingMenuModel::~EncodingMenuModel() {
154 }
155
156 void EncodingMenuModel::Build() {
157 EncodingMenuController::EncodingMenuItemList encoding_menu_items;
158 EncodingMenuController encoding_menu_controller;
159 encoding_menu_controller.GetEncodingMenuItems(browser_->profile(),
160 &encoding_menu_items);
161
162 int group_id = 0;
163 EncodingMenuController::EncodingMenuItemList::iterator it =
164 encoding_menu_items.begin();
165 for (; it != encoding_menu_items.end(); ++it) {
166 int id = it->first;
167 base::string16& label = it->second;
168 if (id == 0) {
169 AddSeparator(ui::NORMAL_SEPARATOR);
170 } else {
171 if (id == IDC_ENCODING_AUTO_DETECT) {
172 AddCheckItem(id, label);
173 } else {
174 // Use the id of the first radio command as the id of the group.
175 if (group_id <= 0)
176 group_id = id;
177 AddRadioItem(id, label, group_id);
178 }
179 }
180 }
181 }
182
183 bool EncodingMenuModel::IsCommandIdChecked(int command_id) const {
184 WebContents* current_tab =
185 browser_->tab_strip_model()->GetActiveWebContents();
186 if (!current_tab)
187 return false;
188 EncodingMenuController controller;
189 return controller.IsItemChecked(browser_->profile(),
190 current_tab->GetEncoding(), command_id);
191 }
192
193 bool EncodingMenuModel::IsCommandIdEnabled(int command_id) const {
194 bool enabled = chrome::IsCommandEnabled(browser_, command_id);
195 // Special handling for the contents of the Encoding submenu. On Mac OS,
196 // instead of enabling/disabling the top-level menu item, the submenu's
197 // contents get disabled, per Apple's HIG.
198 #if defined(OS_MACOSX)
199 enabled &= chrome::IsCommandEnabled(browser_, IDC_ENCODING_MENU);
200 #endif
201 return enabled;
202 }
203
204 bool EncodingMenuModel::GetAcceleratorForCommandId(
205 int command_id,
206 ui::Accelerator* accelerator) {
207 return false;
208 }
209
210 void EncodingMenuModel::ExecuteCommand(int command_id, int event_flags) {
211 chrome::ExecuteCommand(browser_, command_id);
212 }
213
214 ////////////////////////////////////////////////////////////////////////////////
215 // ZoomMenuModel
216
217 ZoomMenuModel::ZoomMenuModel(ui::SimpleMenuModel::Delegate* delegate)
218 : SimpleMenuModel(delegate) {
219 Build();
220 }
221
222 ZoomMenuModel::~ZoomMenuModel() {
223 }
224
225 void ZoomMenuModel::Build() {
226 AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS);
227 AddItemWithStringId(IDC_ZOOM_NORMAL, IDS_ZOOM_NORMAL);
228 AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS);
229 }
230
231 ////////////////////////////////////////////////////////////////////////////////
232 // HelpMenuModel
233
234 #if defined(GOOGLE_CHROME_BUILD)
235
236 class WrenchMenuModel::HelpMenuModel : public ui::SimpleMenuModel {
237 public:
238 HelpMenuModel(ui::SimpleMenuModel::Delegate* delegate,
239 Browser* browser)
240 : SimpleMenuModel(delegate) {
241 Build(browser);
242 }
243
244 private:
245 void Build(Browser* browser) {
246 #if defined(OS_CHROMEOS) && defined(OFFICIAL_BUILD)
247 int help_string_id = IDS_GET_HELP;
248 #else
249 int help_string_id = IDS_HELP_PAGE;
250 #endif
251 AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
252 AddItemWithStringId(IDC_HELP_PAGE_VIA_MENU, help_string_id);
253 if (browser_defaults::kShowHelpMenuItemIcon) {
254 ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
255 SetIcon(GetIndexOfCommandId(IDC_HELP_PAGE_VIA_MENU),
256 rb.GetNativeImageNamed(IDR_HELP_MENU));
257 }
258 AddItemWithStringId(IDC_FEEDBACK, IDS_FEEDBACK);
259 }
260
261 DISALLOW_COPY_AND_ASSIGN(HelpMenuModel);
262 };
263
264 #endif // defined(GOOGLE_CHROME_BUILD)
265
266 ////////////////////////////////////////////////////////////////////////////////
267 // ToolsMenuModel
268
269 ToolsMenuModel::ToolsMenuModel(ui::SimpleMenuModel::Delegate* delegate,
270 Browser* browser)
271 : SimpleMenuModel(delegate) {
272 Build(browser);
273 }
274
275 ToolsMenuModel::~ToolsMenuModel() {}
276
277 // More tools submenu is constructed as follows:
278 // - Page specific actions overflow (save page, adding to taskbar).
279 // - Browser / OS level tools (extensions, task manager).
280 // - Developer tools.
281 // - Option to enable profiling.
282 void ToolsMenuModel::Build(Browser* browser) {
283 bool show_create_shortcuts = true;
284 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
285 show_create_shortcuts = false;
286 #elif defined(USE_ASH)
287 if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
288 show_create_shortcuts = false;
289 #endif
290 AddItemWithStringId(IDC_SAVE_PAGE, IDS_SAVE_PAGE);
291 if (extensions::util::IsNewBookmarkAppsEnabled()) {
292 #if defined(OS_MACOSX)
293 int string_id = IDS_ADD_TO_APPLICATIONS;
294 #elif defined(OS_WIN)
295 int string_id = IDS_ADD_TO_TASKBAR;
296 if (base::win::GetVersion() >= base::win::VERSION_WIN10) {
297 // This is currently non-functional on Win10 and above so change it to be
298 // a link to the generic "create shortcuts" dialog which will allow for
299 // a desktop shortcut.
300 AddItemWithStringId(IDC_CREATE_SHORTCUTS, IDS_CREATE_SHORTCUTS);
301 string_id = 0; // Avoids AddItemWithStringId below.
302 }
303 #else
304 int string_id = IDS_ADD_TO_DESKTOP;
305 #endif
306 #if defined(USE_ASH)
307 if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
308 string_id = IDS_ADD_TO_SHELF;
309 #endif
310 if (string_id)
311 AddItemWithStringId(IDC_CREATE_HOSTED_APP, string_id);
312 } else if (show_create_shortcuts) {
313 AddItemWithStringId(IDC_CREATE_SHORTCUTS, IDS_CREATE_SHORTCUTS);
314 }
315
316 AddSeparator(ui::NORMAL_SEPARATOR);
317 AddItemWithStringId(IDC_CLEAR_BROWSING_DATA, IDS_CLEAR_BROWSING_DATA);
318 AddItemWithStringId(IDC_MANAGE_EXTENSIONS, IDS_SHOW_EXTENSIONS);
319 if (chrome::CanOpenTaskManager())
320 AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
321 #if defined(OS_CHROMEOS)
322 AddItemWithStringId(IDC_TAKE_SCREENSHOT, IDS_TAKE_SCREENSHOT);
323 #endif
324 encoding_menu_model_.reset(new EncodingMenuModel(browser));
325 AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
326 encoding_menu_model_.get());
327
328 AddSeparator(ui::NORMAL_SEPARATOR);
329 AddItemWithStringId(IDC_DEV_TOOLS, IDS_DEV_TOOLS);
330
331 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
332 AddSeparator(ui::NORMAL_SEPARATOR);
333 AddCheckItemWithStringId(IDC_PROFILING_ENABLED, IDS_PROFILING_ENABLED);
334 #endif
335 }
336
337 ////////////////////////////////////////////////////////////////////////////////
338 // WrenchMenuModel
339
340 WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider* provider,
341 Browser* browser)
342 : ui::SimpleMenuModel(this),
343 uma_action_recorded_(false),
344 provider_(provider),
345 browser_(browser) {
346 Build();
347 UpdateZoomControls();
348
349 browser_zoom_subscription_ =
350 ui_zoom::ZoomEventManager::GetForBrowserContext(browser->profile())
351 ->AddZoomLevelChangedCallback(base::Bind(
352 &WrenchMenuModel::OnZoomLevelChanged, base::Unretained(this)));
353
354 browser_->tab_strip_model()->AddObserver(this);
355
356 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
357 content::NotificationService::AllSources());
358 }
359
360 WrenchMenuModel::~WrenchMenuModel() {
361 if (browser_) // Null in tests.
362 browser_->tab_strip_model()->RemoveObserver(this);
363 }
364
365 bool WrenchMenuModel::DoesCommandIdDismissMenu(int command_id) const {
366 return command_id != IDC_ZOOM_MINUS && command_id != IDC_ZOOM_PLUS;
367 }
368
369 bool WrenchMenuModel::IsItemForCommandIdDynamic(int command_id) const {
370 return command_id == IDC_ZOOM_PERCENT_DISPLAY ||
371 #if defined(OS_MACOSX)
372 command_id == IDC_FULLSCREEN ||
373 #elif defined(OS_WIN)
374 command_id == IDC_PIN_TO_START_SCREEN ||
375 #endif
376 command_id == IDC_UPGRADE_DIALOG;
377 }
378
379 base::string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const {
380 switch (command_id) {
381 case IDC_ZOOM_PERCENT_DISPLAY:
382 return zoom_label_;
383 #if defined(OS_MACOSX)
384 case IDC_FULLSCREEN: {
385 int string_id = IDS_ENTER_FULLSCREEN_MAC; // Default to Enter.
386 // Note: On startup, |window()| may be NULL.
387 if (browser_->window() && browser_->window()->IsFullscreen())
388 string_id = IDS_EXIT_FULLSCREEN_MAC;
389 return l10n_util::GetStringUTF16(string_id);
390 }
391 #elif defined(OS_WIN)
392 case IDC_PIN_TO_START_SCREEN: {
393 int string_id = IDS_PIN_TO_START_SCREEN;
394 WebContents* web_contents =
395 browser_->tab_strip_model()->GetActiveWebContents();
396 MetroPinTabHelper* tab_helper =
397 web_contents ? MetroPinTabHelper::FromWebContents(web_contents)
398 : NULL;
399 if (tab_helper && tab_helper->IsPinned())
400 string_id = IDS_UNPIN_FROM_START_SCREEN;
401 return l10n_util::GetStringUTF16(string_id);
402 }
403 #endif
404 case IDC_UPGRADE_DIALOG:
405 return GetUpgradeDialogMenuItemName();
406 default:
407 NOTREACHED();
408 return base::string16();
409 }
410 }
411
412 bool WrenchMenuModel::GetIconForCommandId(int command_id,
413 gfx::Image* icon) const {
414 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
415 switch (command_id) {
416 case IDC_UPGRADE_DIALOG: {
417 if (UpgradeDetector::GetInstance()->notify_upgrade()) {
418 *icon = rb.GetNativeImageNamed(
419 UpgradeDetector::GetInstance()->GetIconResourceID());
420 return true;
421 }
422 return false;
423 }
424 default:
425 break;
426 }
427 return false;
428 }
429
430 void WrenchMenuModel::ExecuteCommand(int command_id, int event_flags) {
431 GlobalError* error = GlobalErrorServiceFactory::GetForProfile(
432 browser_->profile())->GetGlobalErrorByMenuItemCommandID(command_id);
433 if (error) {
434 error->ExecuteMenuItem(browser_);
435 return;
436 }
437
438 LogMenuMetrics(command_id);
439 chrome::ExecuteCommand(browser_, command_id);
440 }
441
442 void WrenchMenuModel::LogMenuMetrics(int command_id) {
443 base::TimeDelta delta = timer_.Elapsed();
444
445 switch (command_id) {
446 case IDC_NEW_TAB:
447 if (!uma_action_recorded_)
448 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.NewTab", delta);
449 LogMenuAction(MENU_ACTION_NEW_TAB);
450 break;
451 case IDC_NEW_WINDOW:
452 if (!uma_action_recorded_)
453 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.NewWindow", delta);
454 LogMenuAction(MENU_ACTION_NEW_WINDOW);
455 break;
456 case IDC_NEW_INCOGNITO_WINDOW:
457 if (!uma_action_recorded_) {
458 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.NewIncognitoWindow",
459 delta);
460 }
461 LogMenuAction(MENU_ACTION_NEW_INCOGNITO_WINDOW);
462 break;
463
464 // Bookmarks sub menu.
465 case IDC_SHOW_BOOKMARK_BAR:
466 if (!uma_action_recorded_) {
467 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowBookmarkBar",
468 delta);
469 }
470 LogMenuAction(MENU_ACTION_SHOW_BOOKMARK_BAR);
471 break;
472 case IDC_SHOW_BOOKMARK_MANAGER:
473 if (!uma_action_recorded_) {
474 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowBookmarkMgr",
475 delta);
476 }
477 LogMenuAction(MENU_ACTION_SHOW_BOOKMARK_MANAGER);
478 break;
479 case IDC_IMPORT_SETTINGS:
480 if (!uma_action_recorded_) {
481 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ImportSettings",
482 delta);
483 }
484 LogMenuAction(MENU_ACTION_IMPORT_SETTINGS);
485 break;
486 case IDC_BOOKMARK_PAGE:
487 if (!uma_action_recorded_) {
488 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.BookmarkPage",
489 delta);
490 }
491 LogMenuAction(MENU_ACTION_BOOKMARK_PAGE);
492 break;
493 case IDC_BOOKMARK_ALL_TABS:
494 if (!uma_action_recorded_) {
495 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.BookmarkAllTabs",
496 delta);
497 }
498 LogMenuAction(MENU_ACTION_BOOKMARK_ALL_TABS);
499 break;
500 case IDC_PIN_TO_START_SCREEN:
501 if (!uma_action_recorded_) {
502 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.PinToStartScreen",
503 delta);
504 }
505 LogMenuAction(MENU_ACTION_PIN_TO_START_SCREEN);
506 break;
507
508 // Recent tabs menu.
509 case IDC_RESTORE_TAB:
510 if (!uma_action_recorded_)
511 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.RestoreTab", delta);
512 LogMenuAction(MENU_ACTION_RESTORE_TAB);
513 break;
514
515 // Windows.
516 case IDC_WIN_DESKTOP_RESTART:
517 if (!uma_action_recorded_) {
518 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.WinDesktopRestart",
519 delta);
520 }
521 LogMenuAction(MENU_ACTION_WIN_DESKTOP_RESTART);
522 break;
523 case IDC_WIN8_METRO_RESTART:
524 if (!uma_action_recorded_) {
525 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Win8MetroRestart",
526 delta);
527 }
528 LogMenuAction(MENU_ACTION_WIN8_METRO_RESTART);
529 break;
530
531 case IDC_WIN_CHROMEOS_RESTART:
532 if (!uma_action_recorded_) {
533 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ChromeOSRestart",
534 delta);
535 }
536 LogMenuAction(MENU_ACTION_WIN_CHROMEOS_RESTART);
537 break;
538 case IDC_DISTILL_PAGE:
539 if (!uma_action_recorded_) {
540 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DistillPage",
541 delta);
542 }
543 LogMenuAction(MENU_ACTION_DISTILL_PAGE);
544 break;
545 case IDC_SAVE_PAGE:
546 if (!uma_action_recorded_)
547 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.SavePage", delta);
548 LogMenuAction(MENU_ACTION_SAVE_PAGE);
549 break;
550 case IDC_FIND:
551 if (!uma_action_recorded_)
552 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Find", delta);
553 LogMenuAction(MENU_ACTION_FIND);
554 break;
555 case IDC_PRINT:
556 if (!uma_action_recorded_)
557 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Print", delta);
558 LogMenuAction(MENU_ACTION_PRINT);
559 break;
560
561 // Edit menu.
562 case IDC_CUT:
563 if (!uma_action_recorded_)
564 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Cut", delta);
565 LogMenuAction(MENU_ACTION_CUT);
566 break;
567 case IDC_COPY:
568 if (!uma_action_recorded_)
569 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Copy", delta);
570 LogMenuAction(MENU_ACTION_COPY);
571 break;
572 case IDC_PASTE:
573 if (!uma_action_recorded_)
574 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Paste", delta);
575 LogMenuAction(MENU_ACTION_PASTE);
576 break;
577
578 // Tools menu.
579 case IDC_CREATE_HOSTED_APP:
580 if (!uma_action_recorded_) {
581 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.CreateHostedApp",
582 delta);
583 }
584 LogMenuAction(MENU_ACTION_CREATE_HOSTED_APP);
585 break;
586 case IDC_CREATE_SHORTCUTS:
587 if (!uma_action_recorded_)
588 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.CreateShortcuts",
589 delta);
590 LogMenuAction(MENU_ACTION_CREATE_SHORTCUTS);
591 break;
592 case IDC_MANAGE_EXTENSIONS:
593 if (!uma_action_recorded_) {
594 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ManageExtensions",
595 delta);
596 }
597 LogMenuAction(MENU_ACTION_MANAGE_EXTENSIONS);
598 break;
599 case IDC_TASK_MANAGER:
600 if (!uma_action_recorded_) {
601 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.TaskManager",
602 delta);
603 }
604 LogMenuAction(MENU_ACTION_TASK_MANAGER);
605 break;
606 case IDC_CLEAR_BROWSING_DATA:
607 if (!uma_action_recorded_) {
608 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ClearBrowsingData",
609 delta);
610 }
611 LogMenuAction(MENU_ACTION_CLEAR_BROWSING_DATA);
612 break;
613 case IDC_VIEW_SOURCE:
614 if (!uma_action_recorded_)
615 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ViewSource", delta);
616 LogMenuAction(MENU_ACTION_VIEW_SOURCE);
617 break;
618 case IDC_DEV_TOOLS:
619 if (!uma_action_recorded_)
620 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DevTools", delta);
621 LogMenuAction(MENU_ACTION_DEV_TOOLS);
622 break;
623 case IDC_DEV_TOOLS_CONSOLE:
624 if (!uma_action_recorded_) {
625 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DevToolsConsole",
626 delta);
627 }
628 LogMenuAction(MENU_ACTION_DEV_TOOLS_CONSOLE);
629 break;
630 case IDC_DEV_TOOLS_DEVICES:
631 if (!uma_action_recorded_) {
632 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DevToolsDevices",
633 delta);
634 }
635 LogMenuAction(MENU_ACTION_DEV_TOOLS_DEVICES);
636 break;
637 case IDC_PROFILING_ENABLED:
638 if (!uma_action_recorded_) {
639 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ProfilingEnabled",
640 delta);
641 }
642 LogMenuAction(MENU_ACTION_PROFILING_ENABLED);
643 break;
644
645 // Zoom menu
646 case IDC_ZOOM_MINUS:
647 if (!uma_action_recorded_) {
648 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ZoomMinus", delta);
649 LogMenuAction(MENU_ACTION_ZOOM_MINUS);
650 }
651 break;
652 case IDC_ZOOM_PLUS:
653 if (!uma_action_recorded_) {
654 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ZoomPlus", delta);
655 LogMenuAction(MENU_ACTION_ZOOM_PLUS);
656 }
657 break;
658 case IDC_FULLSCREEN:
659 content::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));
660
661 if (!uma_action_recorded_) {
662 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.EnterFullScreen",
663 delta);
664 }
665 LogMenuAction(MENU_ACTION_FULLSCREEN);
666 break;
667
668 case IDC_SHOW_HISTORY:
669 if (!uma_action_recorded_) {
670 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowHistory",
671 delta);
672 }
673 LogMenuAction(MENU_ACTION_SHOW_HISTORY);
674 break;
675 case IDC_SHOW_DOWNLOADS:
676 if (!uma_action_recorded_) {
677 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowDownloads",
678 delta);
679 }
680 LogMenuAction(MENU_ACTION_SHOW_DOWNLOADS);
681 break;
682 case IDC_SHOW_SYNC_SETUP:
683 if (!uma_action_recorded_) {
684 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowSyncSetup",
685 delta);
686 }
687 LogMenuAction(MENU_ACTION_SHOW_SYNC_SETUP);
688 break;
689 case IDC_OPTIONS:
690 if (!uma_action_recorded_)
691 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Settings", delta);
692 LogMenuAction(MENU_ACTION_OPTIONS);
693 break;
694 case IDC_ABOUT:
695 if (!uma_action_recorded_)
696 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.About", delta);
697 LogMenuAction(MENU_ACTION_ABOUT);
698 break;
699
700 // Help menu.
701 case IDC_HELP_PAGE_VIA_MENU:
702 content::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));
703
704 if (!uma_action_recorded_)
705 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.HelpPage", delta);
706 LogMenuAction(MENU_ACTION_HELP_PAGE_VIA_MENU);
707 break;
708 #if defined(GOOGLE_CHROME_BUILD)
709 case IDC_FEEDBACK:
710 if (!uma_action_recorded_)
711 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Feedback", delta);
712 LogMenuAction(MENU_ACTION_FEEDBACK);
713 break;
714 #endif
715
716 case IDC_TOGGLE_REQUEST_TABLET_SITE:
717 if (!uma_action_recorded_) {
718 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.RequestTabletSite",
719 delta);
720 }
721 LogMenuAction(MENU_ACTION_TOGGLE_REQUEST_TABLET_SITE);
722 break;
723 case IDC_EXIT:
724 if (!uma_action_recorded_)
725 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Exit", delta);
726 LogMenuAction(MENU_ACTION_EXIT);
727 break;
728 }
729
730 if (!uma_action_recorded_) {
731 UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction", delta);
732 uma_action_recorded_ = true;
733 }
734 }
735
736 void WrenchMenuModel::LogMenuAction(int action_id) {
737 UMA_HISTOGRAM_ENUMERATION("WrenchMenu.MenuAction", action_id,
738 LIMIT_MENU_ACTION);
739 }
740
741 bool WrenchMenuModel::IsCommandIdChecked(int command_id) const {
742 if (command_id == IDC_SHOW_BOOKMARK_BAR) {
743 return browser_->profile()->GetPrefs()->GetBoolean(
744 bookmarks::prefs::kShowBookmarkBar);
745 } else if (command_id == IDC_PROFILING_ENABLED) {
746 return Profiling::BeingProfiled();
747 } else if (command_id == IDC_TOGGLE_REQUEST_TABLET_SITE) {
748 return chrome::IsRequestingTabletSite(browser_);
749 }
750
751 return false;
752 }
753
754 bool WrenchMenuModel::IsCommandIdEnabled(int command_id) const {
755 GlobalError* error = GlobalErrorServiceFactory::GetForProfile(
756 browser_->profile())->GetGlobalErrorByMenuItemCommandID(command_id);
757 if (error)
758 return true;
759
760 return chrome::IsCommandEnabled(browser_, command_id);
761 }
762
763 bool WrenchMenuModel::IsCommandIdVisible(int command_id) const {
764 switch (command_id) {
765 #if defined(OS_MACOSX)
766 case kEmptyMenuItemCommand:
767 return false; // Always hidden (see CreateActionToolbarOverflowMenu).
768 #endif
769 #if defined(OS_WIN)
770 case IDC_VIEW_INCOMPATIBILITIES: {
771 EnumerateModulesModel* loaded_modules =
772 EnumerateModulesModel::GetInstance();
773 if (loaded_modules->confirmed_bad_modules_detected() <= 0)
774 return false;
775 // We'll leave the wrench adornment on until the user clicks the link.
776 if (loaded_modules->modules_to_notify_about() <= 0)
777 loaded_modules->AcknowledgeConflictNotification();
778 return true;
779 }
780 case IDC_PIN_TO_START_SCREEN:
781 return base::win::IsMetroProcess();
782 #else
783 case IDC_VIEW_INCOMPATIBILITIES:
784 case IDC_PIN_TO_START_SCREEN:
785 return false;
786 #endif
787 case IDC_UPGRADE_DIALOG:
788 return browser_defaults::kShowUpgradeMenuItem &&
789 UpgradeDetector::GetInstance()->notify_upgrade();
790 #if !defined(OS_LINUX) || defined(USE_AURA)
791 case IDC_BOOKMARK_PAGE:
792 return !chrome::ShouldRemoveBookmarkThisPageUI(browser_->profile());
793 case IDC_BOOKMARK_ALL_TABS:
794 return !chrome::ShouldRemoveBookmarkOpenPagesUI(browser_->profile());
795 #endif
796 default:
797 return true;
798 }
799 }
800
801 bool WrenchMenuModel::GetAcceleratorForCommandId(
802 int command_id,
803 ui::Accelerator* accelerator) {
804 return provider_->GetAcceleratorForCommandId(command_id, accelerator);
805 }
806
807 void WrenchMenuModel::ActiveTabChanged(WebContents* old_contents,
808 WebContents* new_contents,
809 int index,
810 int reason) {
811 // The user has switched between tabs and the new tab may have a different
812 // zoom setting.
813 UpdateZoomControls();
814 }
815
816 void WrenchMenuModel::TabReplacedAt(TabStripModel* tab_strip_model,
817 WebContents* old_contents,
818 WebContents* new_contents,
819 int index) {
820 UpdateZoomControls();
821 }
822
823 void WrenchMenuModel::Observe(int type,
824 const content::NotificationSource& source,
825 const content::NotificationDetails& details) {
826 DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED);
827 UpdateZoomControls();
828 }
829
830 // For testing.
831 WrenchMenuModel::WrenchMenuModel()
832 : ui::SimpleMenuModel(this),
833 uma_action_recorded_(false),
834 provider_(nullptr),
835 browser_(nullptr) {}
836
837 bool WrenchMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
838 if (browser_->profile()->IsGuestSession())
839 return false;
840
841 return IncognitoModePrefs::GetAvailability(browser_->profile()->GetPrefs()) !=
842 IncognitoModePrefs::DISABLED;
843 }
844
845 // Note: When adding new menu items please place under an appropriate section.
846 // Menu is organised as follows:
847 // - Extension toolbar overflow.
848 // - Global browser errors and warnings.
849 // - Tabs and windows.
850 // - Places previously been e.g. History, bookmarks, recent tabs.
851 // - Page actions e.g. zoom, edit, find, print.
852 // - Learn about the browser and global customisation e.g. settings, help.
853 // - Browser relaunch, quit.
854 void WrenchMenuModel::Build() {
855 if (extensions::FeatureSwitch::extension_action_redesign()->IsEnabled())
856 CreateActionToolbarOverflowMenu();
857
858 AddItem(IDC_VIEW_INCOMPATIBILITIES,
859 l10n_util::GetStringUTF16(IDS_VIEW_INCOMPATIBILITIES));
860 SetIcon(GetIndexOfCommandId(IDC_VIEW_INCOMPATIBILITIES),
861 ui::ResourceBundle::GetSharedInstance().
862 GetNativeImageNamed(IDR_INPUT_ALERT_MENU));
863 if (IsCommandIdVisible(IDC_UPGRADE_DIALOG))
864 AddItem(IDC_UPGRADE_DIALOG, GetUpgradeDialogMenuItemName());
865 if (AddGlobalErrorMenuItems() ||
866 IsCommandIdVisible(IDC_VIEW_INCOMPATIBILITIES) ||
867 IsCommandIdVisible(IDC_UPGRADE_DIALOG))
868 AddSeparator(ui::NORMAL_SEPARATOR);
869
870 AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
871 AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
872 if (ShouldShowNewIncognitoWindowMenuItem())
873 AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
874 AddSeparator(ui::NORMAL_SEPARATOR);
875
876 if (!browser_->profile()->IsOffTheRecord()) {
877 recent_tabs_sub_menu_model_.reset(new RecentTabsSubMenuModel(provider_,
878 browser_,
879 NULL));
880 AddSubMenuWithStringId(IDC_RECENT_TABS_MENU, IDS_HISTORY_MENU,
881 recent_tabs_sub_menu_model_.get());
882 }
883 AddItemWithStringId(IDC_SHOW_DOWNLOADS, IDS_SHOW_DOWNLOADS);
884 if (!browser_->profile()->IsGuestSession()) {
885 bookmark_sub_menu_model_.reset(new BookmarkSubMenuModel(this, browser_));
886 AddSubMenuWithStringId(IDC_BOOKMARKS_MENU, IDS_BOOKMARKS_MENU,
887 bookmark_sub_menu_model_.get());
888 }
889
890 CreateZoomMenu();
891 AddItemWithStringId(IDC_PRINT, IDS_PRINT);
892 if (switches::MediaRouterEnabled() && !browser()->profile()->IsOffTheRecord())
893 AddItemWithStringId(IDC_ROUTE_MEDIA, IDS_MEDIA_ROUTER_MENU_ITEM_TITLE);
894 AddItemWithStringId(IDC_FIND, IDS_FIND);
895 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
896 switches::kEnableDomDistiller))
897 AddItemWithStringId(IDC_DISTILL_PAGE, IDS_DISTILL_PAGE);
898 tools_menu_model_.reset(new ToolsMenuModel(this, browser_));
899 AddSubMenuWithStringId(
900 IDC_MORE_TOOLS_MENU, IDS_MORE_TOOLS_MENU, tools_menu_model_.get());
901 // Append the full menu including separators. The final separator only gets
902 // appended when this is a touch menu - otherwise it would get added twice.
903 CreateCutCopyPasteMenu();
904
905 AddItemWithStringId(IDC_OPTIONS, IDS_SETTINGS);
906 // The help submenu is only displayed on official Chrome builds. As the
907 // 'About' item has been moved to this submenu, it's reinstated here for
908 // Chromium builds.
909 #if defined(GOOGLE_CHROME_BUILD)
910 help_menu_model_.reset(new HelpMenuModel(this, browser_));
911 AddSubMenuWithStringId(IDC_HELP_MENU, IDS_HELP_MENU,
912 help_menu_model_.get());
913 #else
914 AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
915 #endif
916 #if defined(OS_CHROMEOS)
917 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
918 chromeos::switches::kEnableRequestTabletSite))
919 AddCheckItemWithStringId(IDC_TOGGLE_REQUEST_TABLET_SITE,
920 IDS_TOGGLE_REQUEST_TABLET_SITE);
921 #endif
922
923 #if defined(OS_WIN)
924 int command_id = IDC_WIN_DESKTOP_RESTART;
925 int string_id = IDS_WIN_DESKTOP_RESTART;
926 if (GetRestartMenuItemIfRequired(browser_->host_desktop_type(),
927 &command_id,
928 &string_id)) {
929 AddSeparator(ui::NORMAL_SEPARATOR);
930 AddItemWithStringId(command_id, string_id);
931 }
932 #endif
933 bool show_exit_menu = browser_defaults::kShowExitMenuItem;
934 #if defined(OS_WIN)
935 if (browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
936 show_exit_menu = false;
937 #endif
938 if (show_exit_menu) {
939 AddSeparator(ui::NORMAL_SEPARATOR);
940 AddItemWithStringId(IDC_EXIT, IDS_EXIT);
941 }
942 uma_action_recorded_ = false;
943 }
944
945 bool WrenchMenuModel::AddGlobalErrorMenuItems() {
946 // TODO(sail): Currently we only build the wrench menu once per browser
947 // window. This means that if a new error is added after the menu is built
948 // it won't show in the existing wrench menu. To fix this we need to some
949 // how update the menu if new errors are added.
950 const GlobalErrorService::GlobalErrorList& errors =
951 GlobalErrorServiceFactory::GetForProfile(browser_->profile())->errors();
952 bool menu_items_added = false;
953 for (GlobalErrorService::GlobalErrorList::const_iterator
954 it = errors.begin(); it != errors.end(); ++it) {
955 GlobalError* error = *it;
956 DCHECK(error);
957 if (error->HasMenuItem()) {
958 AddItem(error->MenuItemCommandID(), error->MenuItemLabel());
959 SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()),
960 error->MenuItemIcon());
961 menu_items_added = true;
962 }
963 }
964 return menu_items_added;
965 }
966
967 void WrenchMenuModel::CreateActionToolbarOverflowMenu() {
968 // We only add the extensions overflow container if there are any icons that
969 // aren't shown in the main container.
970 // browser_->window() can return null during startup.
971 if (browser_->window() &&
972 browser_->window()->GetToolbarActionsBar()->NeedsOverflow()) {
973 #if defined(OS_MACOSX)
974 // There's a bug in AppKit menus, where if a menu item with a custom view
975 // (like the extensions overflow menu) is the first menu item, it is not
976 // highlightable or keyboard-selectable.
977 // Adding any menu item before it (even one which is never visible) prevents
978 // it, so add a bogus item here that will always be hidden.
979 AddItem(kEmptyMenuItemCommand, base::string16());
980 #endif
981 AddItem(IDC_EXTENSIONS_OVERFLOW_MENU, base::string16());
982 AddSeparator(ui::UPPER_SEPARATOR);
983 }
984 }
985
986 void WrenchMenuModel::CreateCutCopyPasteMenu() {
987 AddSeparator(ui::LOWER_SEPARATOR);
988
989 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
990 // layout for this menu item in WrenchMenu.xib. It does, however, use the
991 // command_id value from AddButtonItem() to identify this special item.
992 edit_menu_item_model_.reset(new ui::ButtonMenuItemModel(IDS_EDIT, this));
993 edit_menu_item_model_->AddGroupItemWithStringId(IDC_CUT, IDS_CUT);
994 edit_menu_item_model_->AddGroupItemWithStringId(IDC_COPY, IDS_COPY);
995 edit_menu_item_model_->AddGroupItemWithStringId(IDC_PASTE, IDS_PASTE);
996 AddButtonItem(IDC_EDIT_MENU, edit_menu_item_model_.get());
997
998 AddSeparator(ui::UPPER_SEPARATOR);
999 }
1000
1001 void WrenchMenuModel::CreateZoomMenu() {
1002 // This menu needs to be enclosed by separators.
1003 AddSeparator(ui::LOWER_SEPARATOR);
1004
1005 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
1006 // layout for this menu item in WrenchMenu.xib. It does, however, use the
1007 // command_id value from AddButtonItem() to identify this special item.
1008 zoom_menu_item_model_.reset(
1009 new ui::ButtonMenuItemModel(IDS_ZOOM_MENU, this));
1010 zoom_menu_item_model_->AddGroupItemWithStringId(IDC_ZOOM_MINUS,
1011 IDS_ZOOM_MINUS2);
1012 zoom_menu_item_model_->AddGroupItemWithStringId(IDC_ZOOM_PLUS,
1013 IDS_ZOOM_PLUS2);
1014 zoom_menu_item_model_->AddItemWithImage(IDC_FULLSCREEN,
1015 IDR_FULLSCREEN_MENU_BUTTON);
1016 AddButtonItem(IDC_ZOOM_MENU, zoom_menu_item_model_.get());
1017
1018 AddSeparator(ui::UPPER_SEPARATOR);
1019 }
1020
1021 void WrenchMenuModel::UpdateZoomControls() {
1022 int zoom_percent = 100;
1023 if (browser_->tab_strip_model() &&
1024 browser_->tab_strip_model()->GetActiveWebContents()) {
1025 zoom_percent = ui_zoom::ZoomController::FromWebContents(
1026 browser_->tab_strip_model()->GetActiveWebContents())
1027 ->GetZoomPercent();
1028 }
1029 zoom_label_ = l10n_util::GetStringFUTF16(
1030 IDS_ZOOM_PERCENT, base::IntToString16(zoom_percent));
1031 }
1032
1033 void WrenchMenuModel::OnZoomLevelChanged(
1034 const content::HostZoomMap::ZoomLevelChange& change) {
1035 UpdateZoomControls();
1036 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/toolbar/wrench_menu_model.h ('k') | chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698