Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / toolbar / wrench_menu_model.cc
blob99d7b96506793abcc19532a6f995acf0d3f4dd19
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.
5 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
7 #include <algorithm>
8 #include <cmath>
10 #include "base/command_line.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/defaults.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/search/search.h"
21 #include "chrome/browser/signin/signin_manager.h"
22 #include "chrome/browser/signin/signin_manager_factory.h"
23 #include "chrome/browser/signin/signin_ui_util.h"
24 #include "chrome/browser/task_manager/task_manager.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_commands.h"
27 #include "chrome/browser/ui/browser_finder.h"
28 #include "chrome/browser/ui/browser_window.h"
29 #include "chrome/browser/ui/global_error/global_error.h"
30 #include "chrome/browser/ui/global_error/global_error_service.h"
31 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
32 #include "chrome/browser/ui/tabs/tab_strip_model.h"
33 #include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h"
34 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
35 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
36 #include "chrome/browser/upgrade_detector.h"
37 #include "chrome/common/chrome_paths.h"
38 #include "chrome/common/chrome_switches.h"
39 #include "chrome/common/pref_names.h"
40 #include "chrome/common/profiling.h"
41 #include "content/public/browser/host_zoom_map.h"
42 #include "content/public/browser/navigation_entry.h"
43 #include "content/public/browser/notification_service.h"
44 #include "content/public/browser/notification_source.h"
45 #include "content/public/browser/notification_types.h"
46 #include "content/public/browser/user_metrics.h"
47 #include "content/public/browser/web_contents.h"
48 #include "grit/chromium_strings.h"
49 #include "grit/generated_resources.h"
50 #include "grit/theme_resources.h"
51 #include "ui/base/l10n/l10n_util.h"
52 #include "ui/base/layout.h"
53 #include "ui/base/models/button_menu_item_model.h"
54 #include "ui/base/resource/resource_bundle.h"
55 #include "ui/gfx/image/image.h"
56 #include "ui/gfx/image/image_skia.h"
58 #if defined(OS_CHROMEOS)
59 #include "chromeos/chromeos_switches.h"
60 #endif
62 #if defined(OS_WIN)
63 #include "base/win/metro.h"
64 #include "base/win/windows_version.h"
65 #include "chrome/browser/enumerate_modules_model_win.h"
66 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
67 #include "content/public/browser/gpu_data_manager.h"
68 #include "win8/util/win8_util.h"
69 #endif
71 #if defined(USE_ASH)
72 #include "ash/shell.h"
73 #endif
75 using base::UserMetricsAction;
76 using content::HostZoomMap;
77 using content::WebContents;
79 namespace {
80 // Conditionally return the update app menu item title based on upgrade detector
81 // state.
82 base::string16 GetUpgradeDialogMenuItemName() {
83 if (UpgradeDetector::GetInstance()->is_outdated_install()) {
84 return l10n_util::GetStringFUTF16(
85 IDS_UPGRADE_BUBBLE_MENU_ITEM,
86 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
87 } else {
88 return l10n_util::GetStringUTF16(IDS_UPDATE_NOW);
92 } // namespace
94 ////////////////////////////////////////////////////////////////////////////////
95 // EncodingMenuModel
97 EncodingMenuModel::EncodingMenuModel(Browser* browser)
98 : ui::SimpleMenuModel(this),
99 browser_(browser) {
100 Build();
103 EncodingMenuModel::~EncodingMenuModel() {
106 void EncodingMenuModel::Build() {
107 EncodingMenuController::EncodingMenuItemList encoding_menu_items;
108 EncodingMenuController encoding_menu_controller;
109 encoding_menu_controller.GetEncodingMenuItems(browser_->profile(),
110 &encoding_menu_items);
112 int group_id = 0;
113 EncodingMenuController::EncodingMenuItemList::iterator it =
114 encoding_menu_items.begin();
115 for (; it != encoding_menu_items.end(); ++it) {
116 int id = it->first;
117 base::string16& label = it->second;
118 if (id == 0) {
119 AddSeparator(ui::NORMAL_SEPARATOR);
120 } else {
121 if (id == IDC_ENCODING_AUTO_DETECT) {
122 AddCheckItem(id, label);
123 } else {
124 // Use the id of the first radio command as the id of the group.
125 if (group_id <= 0)
126 group_id = id;
127 AddRadioItem(id, label, group_id);
133 bool EncodingMenuModel::IsCommandIdChecked(int command_id) const {
134 WebContents* current_tab =
135 browser_->tab_strip_model()->GetActiveWebContents();
136 if (!current_tab)
137 return false;
138 EncodingMenuController controller;
139 return controller.IsItemChecked(browser_->profile(),
140 current_tab->GetEncoding(), command_id);
143 bool EncodingMenuModel::IsCommandIdEnabled(int command_id) const {
144 bool enabled = chrome::IsCommandEnabled(browser_, command_id);
145 // Special handling for the contents of the Encoding submenu. On Mac OS,
146 // instead of enabling/disabling the top-level menu item, the submenu's
147 // contents get disabled, per Apple's HIG.
148 #if defined(OS_MACOSX)
149 enabled &= chrome::IsCommandEnabled(browser_, IDC_ENCODING_MENU);
150 #endif
151 return enabled;
154 bool EncodingMenuModel::GetAcceleratorForCommandId(
155 int command_id,
156 ui::Accelerator* accelerator) {
157 return false;
160 void EncodingMenuModel::ExecuteCommand(int command_id, int event_flags) {
161 chrome::ExecuteCommand(browser_, command_id);
164 ////////////////////////////////////////////////////////////////////////////////
165 // ZoomMenuModel
167 ZoomMenuModel::ZoomMenuModel(ui::SimpleMenuModel::Delegate* delegate)
168 : SimpleMenuModel(delegate) {
169 Build();
172 ZoomMenuModel::~ZoomMenuModel() {
175 void ZoomMenuModel::Build() {
176 AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS);
177 AddItemWithStringId(IDC_ZOOM_NORMAL, IDS_ZOOM_NORMAL);
178 AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS);
181 ////////////////////////////////////////////////////////////////////////////////
182 // ToolsMenuModel
184 ToolsMenuModel::ToolsMenuModel(ui::SimpleMenuModel::Delegate* delegate,
185 Browser* browser)
186 : SimpleMenuModel(delegate) {
187 Build(browser);
190 ToolsMenuModel::~ToolsMenuModel() {}
192 void ToolsMenuModel::Build(Browser* browser) {
193 bool show_create_shortcuts = true;
194 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
195 show_create_shortcuts = false;
196 #elif defined(USE_ASH)
197 if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
198 show_create_shortcuts = false;
199 #endif
201 if (CommandLine::ForCurrentProcess()->HasSwitch(
202 switches::kEnableStreamlinedHostedApps)) {
203 AddItemWithStringId(IDC_CREATE_HOSTED_APP, IDS_CREATE_HOSTED_APP);
204 AddSeparator(ui::NORMAL_SEPARATOR);
205 } else if (show_create_shortcuts) {
206 AddItemWithStringId(IDC_CREATE_SHORTCUTS, IDS_CREATE_SHORTCUTS);
207 AddSeparator(ui::NORMAL_SEPARATOR);
210 AddItemWithStringId(IDC_MANAGE_EXTENSIONS, IDS_SHOW_EXTENSIONS);
212 if (chrome::CanOpenTaskManager())
213 AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
215 AddItemWithStringId(IDC_CLEAR_BROWSING_DATA, IDS_CLEAR_BROWSING_DATA);
217 #if defined(OS_CHROMEOS)
218 AddItemWithStringId(IDC_TAKE_SCREENSHOT, IDS_TAKE_SCREENSHOT);
219 #endif
221 AddSeparator(ui::NORMAL_SEPARATOR);
223 #if defined(GOOGLE_CHROME_BUILD)
224 #if !defined(OS_CHROMEOS)
225 // Show IDC_FEEDBACK in "Tools" menu for non-ChromeOS platforms.
226 AddItemWithStringId(IDC_FEEDBACK, IDS_FEEDBACK);
227 AddSeparator(ui::NORMAL_SEPARATOR);
228 #endif
229 #endif // GOOGLE_CHROME_BUILD
231 encoding_menu_model_.reset(new EncodingMenuModel(browser));
232 AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
233 encoding_menu_model_.get());
234 AddItemWithStringId(IDC_VIEW_SOURCE, IDS_VIEW_SOURCE);
235 AddItemWithStringId(IDC_DEV_TOOLS, IDS_DEV_TOOLS);
236 AddItemWithStringId(IDC_DEV_TOOLS_CONSOLE, IDS_DEV_TOOLS_CONSOLE);
237 AddItemWithStringId(IDC_DEV_TOOLS_DEVICES, IDS_DEV_TOOLS_DEVICES);
239 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
240 AddSeparator(ui::NORMAL_SEPARATOR);
241 AddCheckItemWithStringId(IDC_PROFILING_ENABLED, IDS_PROFILING_ENABLED);
242 #endif
245 ////////////////////////////////////////////////////////////////////////////////
246 // WrenchMenuModel
248 WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider* provider,
249 Browser* browser,
250 bool is_new_menu)
251 : ui::SimpleMenuModel(this),
252 provider_(provider),
253 browser_(browser),
254 tab_strip_model_(browser_->tab_strip_model()) {
255 Build(is_new_menu);
256 UpdateZoomControls();
258 zoom_subscription_ = HostZoomMap::GetForBrowserContext(
259 browser->profile())->AddZoomLevelChangedCallback(
260 base::Bind(&WrenchMenuModel::OnZoomLevelChanged,
261 base::Unretained(this)));
263 tab_strip_model_->AddObserver(this);
265 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
266 content::NotificationService::AllSources());
269 WrenchMenuModel::~WrenchMenuModel() {
270 if (tab_strip_model_)
271 tab_strip_model_->RemoveObserver(this);
274 bool WrenchMenuModel::DoesCommandIdDismissMenu(int command_id) const {
275 return command_id != IDC_ZOOM_MINUS && command_id != IDC_ZOOM_PLUS;
278 bool WrenchMenuModel::IsItemForCommandIdDynamic(int command_id) const {
279 return command_id == IDC_ZOOM_PERCENT_DISPLAY ||
280 #if defined(OS_MACOSX)
281 command_id == IDC_FULLSCREEN ||
282 #elif defined(OS_WIN)
283 command_id == IDC_PIN_TO_START_SCREEN ||
284 #endif
285 command_id == IDC_UPGRADE_DIALOG ||
286 command_id == IDC_SHOW_SIGNIN;
289 base::string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const {
290 switch (command_id) {
291 case IDC_ZOOM_PERCENT_DISPLAY:
292 return zoom_label_;
293 #if defined(OS_MACOSX)
294 case IDC_FULLSCREEN: {
295 int string_id = IDS_ENTER_FULLSCREEN_MAC; // Default to Enter.
296 // Note: On startup, |window()| may be NULL.
297 if (browser_->window() && browser_->window()->IsFullscreen())
298 string_id = IDS_EXIT_FULLSCREEN_MAC;
299 return l10n_util::GetStringUTF16(string_id);
301 #elif defined(OS_WIN)
302 case IDC_PIN_TO_START_SCREEN: {
303 int string_id = IDS_PIN_TO_START_SCREEN;
304 WebContents* web_contents =
305 browser_->tab_strip_model()->GetActiveWebContents();
306 MetroPinTabHelper* tab_helper =
307 web_contents ? MetroPinTabHelper::FromWebContents(web_contents)
308 : NULL;
309 if (tab_helper && tab_helper->IsPinned())
310 string_id = IDS_UNPIN_FROM_START_SCREEN;
311 return l10n_util::GetStringUTF16(string_id);
313 #endif
314 case IDC_UPGRADE_DIALOG:
315 return GetUpgradeDialogMenuItemName();
316 case IDC_SHOW_SIGNIN:
317 return signin_ui_util::GetSigninMenuLabel(
318 browser_->profile()->GetOriginalProfile());
319 default:
320 NOTREACHED();
321 return base::string16();
325 bool WrenchMenuModel::GetIconForCommandId(int command_id,
326 gfx::Image* icon) const {
327 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
328 switch (command_id) {
329 case IDC_UPGRADE_DIALOG: {
330 if (UpgradeDetector::GetInstance()->notify_upgrade()) {
331 *icon = rb.GetNativeImageNamed(
332 UpgradeDetector::GetInstance()->GetIconResourceID(
333 UpgradeDetector::UPGRADE_ICON_TYPE_MENU_ICON));
334 return true;
336 return false;
338 case IDC_SHOW_SIGNIN: {
339 GlobalError* error = signin_ui_util::GetSignedInServiceError(
340 browser_->profile()->GetOriginalProfile());
341 if (error) {
342 int icon_id = error->MenuItemIconResourceID();
343 if (icon_id) {
344 *icon = rb.GetNativeImageNamed(icon_id);
345 return true;
348 return false;
350 default:
351 break;
353 return false;
356 void WrenchMenuModel::ExecuteCommand(int command_id, int event_flags) {
357 GlobalError* error = GlobalErrorServiceFactory::GetForProfile(
358 browser_->profile())->GetGlobalErrorByMenuItemCommandID(command_id);
359 if (error) {
360 error->ExecuteMenuItem(browser_);
361 return;
364 if (command_id == IDC_SHOW_SIGNIN) {
365 // If a custom error message is being shown, handle it.
366 GlobalError* error = signin_ui_util::GetSignedInServiceError(
367 browser_->profile()->GetOriginalProfile());
368 if (error) {
369 error->ExecuteMenuItem(browser_);
370 return;
374 if (command_id == IDC_HELP_PAGE_VIA_MENU)
375 content::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));
377 if (command_id == IDC_FULLSCREEN) {
378 // We issue the UMA command here and not in BrowserCommandController or even
379 // FullscreenController since we want to be able to distinguish this event
380 // and a menu which is under development.
381 content::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));
384 chrome::ExecuteCommand(browser_, command_id);
387 bool WrenchMenuModel::IsCommandIdChecked(int command_id) const {
388 if (command_id == IDC_SHOW_BOOKMARK_BAR) {
389 return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
390 } else if (command_id == IDC_PROFILING_ENABLED) {
391 return Profiling::BeingProfiled();
392 } else if (command_id == IDC_TOGGLE_REQUEST_TABLET_SITE) {
393 return chrome::IsRequestingTabletSite(browser_);
396 return false;
399 bool WrenchMenuModel::IsCommandIdEnabled(int command_id) const {
400 GlobalError* error = GlobalErrorServiceFactory::GetForProfile(
401 browser_->profile())->GetGlobalErrorByMenuItemCommandID(command_id);
402 if (error)
403 return true;
405 return chrome::IsCommandEnabled(browser_, command_id);
408 bool WrenchMenuModel::IsCommandIdVisible(int command_id) const {
409 #if defined(OS_WIN)
410 if (command_id == IDC_VIEW_INCOMPATIBILITIES) {
411 EnumerateModulesModel* loaded_modules =
412 EnumerateModulesModel::GetInstance();
413 if (loaded_modules->confirmed_bad_modules_detected() <= 0)
414 return false;
415 // We'll leave the wrench adornment on until the user clicks the link.
416 if (loaded_modules->modules_to_notify_about() <= 0)
417 loaded_modules->AcknowledgeConflictNotification();
418 return true;
419 } else if (command_id == IDC_PIN_TO_START_SCREEN) {
420 return base::win::IsMetroProcess();
421 #else
422 if (command_id == IDC_VIEW_INCOMPATIBILITIES ||
423 command_id == IDC_PIN_TO_START_SCREEN) {
424 return false;
425 #endif
426 } else if (command_id == IDC_UPGRADE_DIALOG) {
427 return UpgradeDetector::GetInstance()->notify_upgrade();
429 return true;
432 bool WrenchMenuModel::GetAcceleratorForCommandId(
433 int command_id,
434 ui::Accelerator* accelerator) {
435 return provider_->GetAcceleratorForCommandId(command_id, accelerator);
438 void WrenchMenuModel::ActiveTabChanged(WebContents* old_contents,
439 WebContents* new_contents,
440 int index,
441 int reason) {
442 // The user has switched between tabs and the new tab may have a different
443 // zoom setting.
444 UpdateZoomControls();
447 void WrenchMenuModel::TabReplacedAt(TabStripModel* tab_strip_model,
448 WebContents* old_contents,
449 WebContents* new_contents,
450 int index) {
451 UpdateZoomControls();
454 void WrenchMenuModel::TabStripModelDeleted() {
455 // During views shutdown, the tabstrip model/browser is deleted first, while
456 // it is the opposite in gtk land.
457 tab_strip_model_->RemoveObserver(this);
458 tab_strip_model_ = NULL;
461 void WrenchMenuModel::Observe(int type,
462 const content::NotificationSource& source,
463 const content::NotificationDetails& details) {
464 DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED);
465 UpdateZoomControls();
468 // For testing.
469 WrenchMenuModel::WrenchMenuModel()
470 : ui::SimpleMenuModel(this),
471 provider_(NULL),
472 browser_(NULL),
473 tab_strip_model_(NULL) {
476 bool WrenchMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
477 if (browser_->profile()->IsManaged())
478 return false;
480 #if defined(OS_WIN)
481 if (win8::IsSingleWindowMetroMode() &&
482 browser_->profile()->HasOffTheRecordProfile()) {
483 return false;
485 #endif
487 #if defined(OS_CHROMEOS)
488 if (CommandLine::ForCurrentProcess()->HasSwitch(
489 chromeos::switches::kGuestSession)) {
490 return false;
492 #endif
494 return true;
497 bool WrenchMenuModel::ShouldShowNewWindowMenuItem() {
498 #if defined(OS_WIN)
499 if (!win8::IsSingleWindowMetroMode())
500 return true;
502 // In Win8's single window Metro mode, we only show the New Window options
503 // if there isn't already a window of the requested type (incognito or not)
504 // that is available.
505 return browser_->profile()->IsOffTheRecord() &&
506 !chrome::FindBrowserWithProfile(
507 browser_->profile()->GetOriginalProfile(),
508 browser_->host_desktop_type());
509 #else
510 return true;
511 #endif
514 void WrenchMenuModel::Build(bool is_new_menu) {
515 #if defined(OS_WIN)
516 AddItem(IDC_VIEW_INCOMPATIBILITIES,
517 l10n_util::GetStringUTF16(IDS_VIEW_INCOMPATIBILITIES));
518 EnumerateModulesModel* model =
519 EnumerateModulesModel::GetInstance();
520 if (model->modules_to_notify_about() > 0 ||
521 model->confirmed_bad_modules_detected() > 0)
522 AddSeparator(ui::NORMAL_SEPARATOR);
523 #endif
525 AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
526 if (ShouldShowNewWindowMenuItem())
527 AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
529 if (ShouldShowNewIncognitoWindowMenuItem())
530 AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
532 #if defined(OS_WIN) && !defined(NDEBUG) && defined(USE_ASH)
533 if (base::win::GetVersion() < base::win::VERSION_WIN8 &&
534 chrome::HOST_DESKTOP_TYPE_NATIVE != chrome::HOST_DESKTOP_TYPE_ASH) {
535 AddItemWithStringId(IDC_TOGGLE_ASH_DESKTOP,
536 ash::Shell::HasInstance() ? IDS_CLOSE_ASH_DESKTOP :
537 IDS_OPEN_ASH_DESKTOP);
539 #endif
541 bookmark_sub_menu_model_.reset(new BookmarkSubMenuModel(this, browser_));
542 AddSubMenuWithStringId(IDC_BOOKMARKS_MENU, IDS_BOOKMARKS_MENU,
543 bookmark_sub_menu_model_.get());
545 if (chrome::IsInstantExtendedAPIEnabled()) {
546 recent_tabs_sub_menu_model_.reset(new RecentTabsSubMenuModel(provider_,
547 browser_,
548 NULL));
549 AddSubMenuWithStringId(IDC_RECENT_TABS_MENU, IDS_RECENT_TABS_MENU,
550 recent_tabs_sub_menu_model_.get());
553 #if defined(OS_WIN)
555 #if defined(USE_AURA)
556 if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
557 content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
558 if (browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH) {
559 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
560 AddSeparator(ui::NORMAL_SEPARATOR);
561 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART, IDS_WIN8_DESKTOP_RESTART);
562 } else {
563 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
564 AddSeparator(ui::NORMAL_SEPARATOR);
565 AddItemWithStringId(IDC_WIN8_METRO_RESTART, IDS_WIN8_METRO_RESTART);
568 #else
569 if (base::win::IsMetroProcess()) {
570 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
571 AddSeparator(ui::NORMAL_SEPARATOR);
572 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART, IDS_WIN8_DESKTOP_RESTART);
573 } else {
574 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
575 AddSeparator(ui::NORMAL_SEPARATOR);
576 AddItemWithStringId(IDC_WIN8_METRO_RESTART, IDS_WIN8_METRO_RESTART);
578 #endif
580 #endif
582 // Append the full menu including separators. The final separator only gets
583 // appended when this is a touch menu - otherwise it would get added twice.
584 CreateCutCopyPasteMenu(is_new_menu);
586 if (!is_new_menu)
587 CreateZoomMenu(is_new_menu);
589 AddItemWithStringId(IDC_SAVE_PAGE, IDS_SAVE_PAGE);
590 AddItemWithStringId(IDC_FIND, IDS_FIND);
591 AddItemWithStringId(IDC_PRINT, IDS_PRINT);
593 tools_menu_model_.reset(new ToolsMenuModel(this, browser_));
594 // In case of touch this is the last item.
595 if (!is_new_menu) {
596 AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_TOOLS_MENU,
597 tools_menu_model_.get());
600 if (is_new_menu)
601 CreateZoomMenu(is_new_menu);
602 else
603 AddSeparator(ui::NORMAL_SEPARATOR);
605 AddItemWithStringId(IDC_SHOW_HISTORY, IDS_SHOW_HISTORY);
606 AddItemWithStringId(IDC_SHOW_DOWNLOADS, IDS_SHOW_DOWNLOADS);
607 AddSeparator(ui::NORMAL_SEPARATOR);
609 #if !defined(OS_CHROMEOS)
610 // No "Sign in to Chromium..." menu item on ChromeOS.
611 SigninManager* signin = SigninManagerFactory::GetForProfile(
612 browser_->profile()->GetOriginalProfile());
613 if (signin && signin->IsSigninAllowed()) {
614 const base::string16 short_product_name =
615 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
616 AddItem(IDC_SHOW_SYNC_SETUP, l10n_util::GetStringFUTF16(
617 IDS_SYNC_MENU_PRE_SYNCED_LABEL, short_product_name));
618 AddSeparator(ui::NORMAL_SEPARATOR);
620 #endif
622 AddItemWithStringId(IDC_OPTIONS, IDS_SETTINGS);
624 #if defined(OS_CHROMEOS)
625 if (CommandLine::ForCurrentProcess()->HasSwitch(
626 chromeos::switches::kEnableRequestTabletSite))
627 AddCheckItemWithStringId(IDC_TOGGLE_REQUEST_TABLET_SITE,
628 IDS_TOGGLE_REQUEST_TABLET_SITE);
629 #endif
631 // On ChromeOS-Touch, we don't want the about menu option.
632 #if defined(OS_CHROMEOS)
633 if (!is_new_menu)
634 #endif
636 AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
639 if (browser_defaults::kShowUpgradeMenuItem)
640 AddItem(IDC_UPGRADE_DIALOG, GetUpgradeDialogMenuItemName());
642 #if defined(OS_WIN)
643 SetIcon(GetIndexOfCommandId(IDC_VIEW_INCOMPATIBILITIES),
644 ui::ResourceBundle::GetSharedInstance().
645 GetNativeImageNamed(IDR_INPUT_ALERT_MENU));
646 #endif
648 if (!is_new_menu) {
649 AddItemWithStringId(IDC_HELP_PAGE_VIA_MENU, IDS_HELP_PAGE);
651 if (browser_defaults::kShowHelpMenuItemIcon) {
652 ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
653 SetIcon(GetIndexOfCommandId(IDC_HELP_PAGE_VIA_MENU),
654 rb.GetNativeImageNamed(IDR_HELP_MENU));
658 #if defined(GOOGLE_CHROME_BUILD)
659 #if defined(OS_CHROMEOS)
660 AddItemWithStringId(IDC_FEEDBACK, IDS_FEEDBACK);
661 #endif
662 #endif
664 AddGlobalErrorMenuItems();
666 if (is_new_menu) {
667 AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_MORE_TOOLS_MENU,
668 tools_menu_model_.get());
671 bool show_exit_menu = browser_defaults::kShowExitMenuItem;
672 #if defined(OS_WIN) && defined(USE_AURA)
673 if (browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
674 show_exit_menu = false;
675 #endif
677 if (show_exit_menu) {
678 AddSeparator(ui::NORMAL_SEPARATOR);
679 AddItemWithStringId(IDC_EXIT, IDS_EXIT);
683 void WrenchMenuModel::AddGlobalErrorMenuItems() {
684 // TODO(sail): Currently we only build the wrench menu once per browser
685 // window. This means that if a new error is added after the menu is built
686 // it won't show in the existing wrench menu. To fix this we need to some
687 // how update the menu if new errors are added.
688 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
689 // GetSignedInServiceErrors() can modify the global error list, so call it
690 // before iterating through that list below.
691 std::vector<GlobalError*> signin_errors =
692 signin_ui_util::GetSignedInServiceErrors(
693 browser_->profile()->GetOriginalProfile());
694 const GlobalErrorService::GlobalErrorList& errors =
695 GlobalErrorServiceFactory::GetForProfile(browser_->profile())->errors();
696 for (GlobalErrorService::GlobalErrorList::const_iterator
697 it = errors.begin(); it != errors.end(); ++it) {
698 GlobalError* error = *it;
699 DCHECK(error);
700 if (error->HasMenuItem()) {
701 #if !defined(OS_CHROMEOS)
702 // Don't add a signin error if it's already being displayed elsewhere.
703 if (std::find(signin_errors.begin(), signin_errors.end(), error) !=
704 signin_errors.end()) {
705 MenuModel* model = this;
706 int index = 0;
707 if (MenuModel::GetModelAndIndexForCommandId(
708 IDC_SHOW_SIGNIN, &model, &index)) {
709 continue;
712 #endif
714 AddItem(error->MenuItemCommandID(), error->MenuItemLabel());
715 int icon_id = error->MenuItemIconResourceID();
716 if (icon_id) {
717 const gfx::Image& image = rb.GetNativeImageNamed(icon_id);
718 SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()),
719 image);
725 void WrenchMenuModel::CreateCutCopyPasteMenu(bool new_menu) {
726 AddSeparator(new_menu ? ui::LOWER_SEPARATOR : ui::NORMAL_SEPARATOR);
728 #if defined(OS_POSIX) && !defined(TOOLKIT_VIEWS)
729 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
730 // layout for this menu item in Toolbar.xib. It does, however, use the
731 // command_id value from AddButtonItem() to identify this special item.
732 edit_menu_item_model_.reset(new ui::ButtonMenuItemModel(IDS_EDIT, this));
733 edit_menu_item_model_->AddGroupItemWithStringId(IDC_CUT, IDS_CUT);
734 edit_menu_item_model_->AddGroupItemWithStringId(IDC_COPY, IDS_COPY);
735 edit_menu_item_model_->AddGroupItemWithStringId(IDC_PASTE, IDS_PASTE);
736 AddButtonItem(IDC_EDIT_MENU, edit_menu_item_model_.get());
737 #else
738 // WARNING: views/wrench_menu assumes these items are added in this order. If
739 // you change the order you'll need to update wrench_menu as well.
740 AddItemWithStringId(IDC_CUT, IDS_CUT);
741 AddItemWithStringId(IDC_COPY, IDS_COPY);
742 AddItemWithStringId(IDC_PASTE, IDS_PASTE);
743 #endif
745 if (new_menu)
746 AddSeparator(ui::UPPER_SEPARATOR);
749 void WrenchMenuModel::CreateZoomMenu(bool new_menu) {
750 // This menu needs to be enclosed by separators.
751 AddSeparator(new_menu ? ui::LOWER_SEPARATOR : ui::NORMAL_SEPARATOR);
753 #if defined(OS_POSIX) && !defined(TOOLKIT_VIEWS)
754 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
755 // layout for this menu item in Toolbar.xib. It does, however, use the
756 // command_id value from AddButtonItem() to identify this special item.
757 zoom_menu_item_model_.reset(
758 new ui::ButtonMenuItemModel(IDS_ZOOM_MENU, this));
759 zoom_menu_item_model_->AddGroupItemWithStringId(
760 IDC_ZOOM_MINUS, IDS_ZOOM_MINUS2);
761 zoom_menu_item_model_->AddButtonLabel(IDC_ZOOM_PERCENT_DISPLAY,
762 IDS_ZOOM_PLUS2);
763 zoom_menu_item_model_->AddGroupItemWithStringId(
764 IDC_ZOOM_PLUS, IDS_ZOOM_PLUS2);
765 zoom_menu_item_model_->AddSpace();
766 zoom_menu_item_model_->AddItemWithImage(
767 IDC_FULLSCREEN, IDR_FULLSCREEN_MENU_BUTTON);
768 AddButtonItem(IDC_ZOOM_MENU, zoom_menu_item_model_.get());
769 #else
770 // WARNING: views/wrench_menu assumes these items are added in this order. If
771 // you change the order you'll need to update wrench_menu as well.
772 AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS);
773 AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS);
774 AddItemWithStringId(IDC_FULLSCREEN, IDS_FULLSCREEN);
775 #endif
777 AddSeparator(new_menu ? ui::UPPER_SEPARATOR : ui::NORMAL_SEPARATOR);
780 void WrenchMenuModel::UpdateZoomControls() {
781 bool enable_increment = false;
782 bool enable_decrement = false;
783 int zoom_percent = 100;
784 if (browser_->tab_strip_model()->GetActiveWebContents()) {
785 zoom_percent =
786 browser_->tab_strip_model()->GetActiveWebContents()->GetZoomPercent(
787 &enable_increment, &enable_decrement);
789 zoom_label_ = l10n_util::GetStringFUTF16(
790 IDS_ZOOM_PERCENT, base::IntToString16(zoom_percent));
793 void WrenchMenuModel::OnZoomLevelChanged(
794 const content::HostZoomMap::ZoomLevelChange& change) {
795 UpdateZoomControls();