OLD | NEW |
| (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 } | |
OLD | NEW |