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"
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_factory.h"
22 #include "chrome/browser/signin/signin_ui_util.h"
23 #include "chrome/browser/task_manager/task_manager.h"
24 #include "chrome/browser/ui/bookmarks/bookmark_utils.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 "components/signin/core/browser/signin_manager.h"
42 #include "content/public/browser/host_zoom_map.h"
43 #include "content/public/browser/navigation_entry.h"
44 #include "content/public/browser/notification_service.h"
45 #include "content/public/browser/notification_source.h"
46 #include "content/public/browser/notification_types.h"
47 #include "content/public/browser/user_metrics.h"
48 #include "content/public/browser/web_contents.h"
49 #include "grit/chromium_strings.h"
50 #include "grit/generated_resources.h"
51 #include "grit/theme_resources.h"
52 #include "ui/base/l10n/l10n_util.h"
53 #include "ui/base/layout.h"
54 #include "ui/base/models/button_menu_item_model.h"
55 #include "ui/base/resource/resource_bundle.h"
56 #include "ui/gfx/image/image.h"
57 #include "ui/gfx/image/image_skia.h"
59 #if defined(OS_CHROMEOS)
60 #include "chromeos/chromeos_switches.h"
64 #include "base/win/metro.h"
65 #include "base/win/windows_version.h"
66 #include "chrome/browser/enumerate_modules_model_win.h"
67 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
68 #include "content/public/browser/gpu_data_manager.h"
69 #include "win8/util/win8_util.h"
73 #include "ash/shell.h"
76 using base::UserMetricsAction
;
77 using content::HostZoomMap
;
78 using content::WebContents
;
81 // Conditionally return the update app menu item title based on upgrade detector
83 base::string16
GetUpgradeDialogMenuItemName() {
84 if (UpgradeDetector::GetInstance()->is_outdated_install() ||
85 UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
86 return l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_MENU_ITEM
);
88 return l10n_util::GetStringUTF16(IDS_UPDATE_NOW
);
94 ////////////////////////////////////////////////////////////////////////////////
97 EncodingMenuModel::EncodingMenuModel(Browser
* browser
)
98 : ui::SimpleMenuModel(this),
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
);
113 EncodingMenuController::EncodingMenuItemList::iterator it
=
114 encoding_menu_items
.begin();
115 for (; it
!= encoding_menu_items
.end(); ++it
) {
117 base::string16
& label
= it
->second
;
119 AddSeparator(ui::NORMAL_SEPARATOR
);
121 if (id
== IDC_ENCODING_AUTO_DETECT
) {
122 AddCheckItem(id
, label
);
124 // Use the id of the first radio command as the id of the group.
127 AddRadioItem(id
, label
, group_id
);
133 bool EncodingMenuModel::IsCommandIdChecked(int command_id
) const {
134 WebContents
* current_tab
=
135 browser_
->tab_strip_model()->GetActiveWebContents();
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
);
154 bool EncodingMenuModel::GetAcceleratorForCommandId(
156 ui::Accelerator
* accelerator
) {
160 void EncodingMenuModel::ExecuteCommand(int command_id
, int event_flags
) {
161 chrome::ExecuteCommand(browser_
, command_id
);
164 ////////////////////////////////////////////////////////////////////////////////
167 ZoomMenuModel::ZoomMenuModel(ui::SimpleMenuModel::Delegate
* delegate
)
168 : SimpleMenuModel(delegate
) {
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 ////////////////////////////////////////////////////////////////////////////////
184 ToolsMenuModel::ToolsMenuModel(ui::SimpleMenuModel::Delegate
* delegate
,
186 : SimpleMenuModel(delegate
) {
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;
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 AddSeparator(ui::NORMAL_SEPARATOR
);
219 #if defined(GOOGLE_CHROME_BUILD)
220 #if !defined(OS_CHROMEOS)
221 // Show IDC_FEEDBACK in "Tools" menu for non-ChromeOS platforms.
222 AddItemWithStringId(IDC_FEEDBACK
, IDS_FEEDBACK
);
223 AddSeparator(ui::NORMAL_SEPARATOR
);
225 #endif // GOOGLE_CHROME_BUILD
227 encoding_menu_model_
.reset(new EncodingMenuModel(browser
));
228 AddSubMenuWithStringId(IDC_ENCODING_MENU
, IDS_ENCODING_MENU
,
229 encoding_menu_model_
.get());
230 AddItemWithStringId(IDC_VIEW_SOURCE
, IDS_VIEW_SOURCE
);
231 AddItemWithStringId(IDC_DEV_TOOLS
, IDS_DEV_TOOLS
);
232 AddItemWithStringId(IDC_DEV_TOOLS_CONSOLE
, IDS_DEV_TOOLS_CONSOLE
);
233 AddItemWithStringId(IDC_DEV_TOOLS_DEVICES
, IDS_DEV_TOOLS_DEVICES
);
235 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
236 AddSeparator(ui::NORMAL_SEPARATOR
);
237 AddCheckItemWithStringId(IDC_PROFILING_ENABLED
, IDS_PROFILING_ENABLED
);
241 ////////////////////////////////////////////////////////////////////////////////
244 WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider
* provider
,
247 : ui::SimpleMenuModel(this),
250 tab_strip_model_(browser_
->tab_strip_model()) {
252 UpdateZoomControls();
254 zoom_subscription_
= HostZoomMap::GetForBrowserContext(
255 browser
->profile())->AddZoomLevelChangedCallback(
256 base::Bind(&WrenchMenuModel::OnZoomLevelChanged
,
257 base::Unretained(this)));
259 tab_strip_model_
->AddObserver(this);
261 registrar_
.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED
,
262 content::NotificationService::AllSources());
265 WrenchMenuModel::~WrenchMenuModel() {
266 if (tab_strip_model_
)
267 tab_strip_model_
->RemoveObserver(this);
270 bool WrenchMenuModel::DoesCommandIdDismissMenu(int command_id
) const {
271 return command_id
!= IDC_ZOOM_MINUS
&& command_id
!= IDC_ZOOM_PLUS
;
274 bool WrenchMenuModel::IsItemForCommandIdDynamic(int command_id
) const {
275 return command_id
== IDC_ZOOM_PERCENT_DISPLAY
||
276 #if defined(OS_MACOSX)
277 command_id
== IDC_FULLSCREEN
||
278 #elif defined(OS_WIN)
279 command_id
== IDC_PIN_TO_START_SCREEN
||
281 command_id
== IDC_UPGRADE_DIALOG
||
282 command_id
== IDC_SHOW_SIGNIN
;
285 base::string16
WrenchMenuModel::GetLabelForCommandId(int command_id
) const {
286 switch (command_id
) {
287 case IDC_ZOOM_PERCENT_DISPLAY
:
289 #if defined(OS_MACOSX)
290 case IDC_FULLSCREEN
: {
291 int string_id
= IDS_ENTER_FULLSCREEN_MAC
; // Default to Enter.
292 // Note: On startup, |window()| may be NULL.
293 if (browser_
->window() && browser_
->window()->IsFullscreen())
294 string_id
= IDS_EXIT_FULLSCREEN_MAC
;
295 return l10n_util::GetStringUTF16(string_id
);
297 #elif defined(OS_WIN)
298 case IDC_PIN_TO_START_SCREEN
: {
299 int string_id
= IDS_PIN_TO_START_SCREEN
;
300 WebContents
* web_contents
=
301 browser_
->tab_strip_model()->GetActiveWebContents();
302 MetroPinTabHelper
* tab_helper
=
303 web_contents
? MetroPinTabHelper::FromWebContents(web_contents
)
305 if (tab_helper
&& tab_helper
->IsPinned())
306 string_id
= IDS_UNPIN_FROM_START_SCREEN
;
307 return l10n_util::GetStringUTF16(string_id
);
310 case IDC_UPGRADE_DIALOG
:
311 return GetUpgradeDialogMenuItemName();
312 case IDC_SHOW_SIGNIN
:
313 return signin_ui_util::GetSigninMenuLabel(
314 browser_
->profile()->GetOriginalProfile());
317 return base::string16();
321 bool WrenchMenuModel::GetIconForCommandId(int command_id
,
322 gfx::Image
* icon
) const {
323 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
324 switch (command_id
) {
325 case IDC_UPGRADE_DIALOG
: {
326 if (UpgradeDetector::GetInstance()->notify_upgrade()) {
327 *icon
= rb
.GetNativeImageNamed(
328 UpgradeDetector::GetInstance()->GetIconResourceID(
329 UpgradeDetector::UPGRADE_ICON_TYPE_MENU_ICON
));
334 case IDC_SHOW_SIGNIN
: {
335 GlobalError
* error
= signin_ui_util::GetSignedInServiceError(
336 browser_
->profile()->GetOriginalProfile());
338 int icon_id
= error
->MenuItemIconResourceID();
340 *icon
= rb
.GetNativeImageNamed(icon_id
);
352 void WrenchMenuModel::ExecuteCommand(int command_id
, int event_flags
) {
353 GlobalError
* error
= GlobalErrorServiceFactory::GetForProfile(
354 browser_
->profile())->GetGlobalErrorByMenuItemCommandID(command_id
);
356 error
->ExecuteMenuItem(browser_
);
360 if (command_id
== IDC_SHOW_SIGNIN
) {
361 // If a custom error message is being shown, handle it.
362 GlobalError
* error
= signin_ui_util::GetSignedInServiceError(
363 browser_
->profile()->GetOriginalProfile());
365 error
->ExecuteMenuItem(browser_
);
370 if (command_id
== IDC_HELP_PAGE_VIA_MENU
)
371 content::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));
373 if (command_id
== IDC_FULLSCREEN
) {
374 // We issue the UMA command here and not in BrowserCommandController or even
375 // FullscreenController since we want to be able to distinguish this event
376 // and a menu which is under development.
377 content::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));
380 chrome::ExecuteCommand(browser_
, command_id
);
383 bool WrenchMenuModel::IsCommandIdChecked(int command_id
) const {
384 if (command_id
== IDC_SHOW_BOOKMARK_BAR
) {
385 return browser_
->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar
);
386 } else if (command_id
== IDC_PROFILING_ENABLED
) {
387 return Profiling::BeingProfiled();
388 } else if (command_id
== IDC_TOGGLE_REQUEST_TABLET_SITE
) {
389 return chrome::IsRequestingTabletSite(browser_
);
395 bool WrenchMenuModel::IsCommandIdEnabled(int command_id
) const {
396 GlobalError
* error
= GlobalErrorServiceFactory::GetForProfile(
397 browser_
->profile())->GetGlobalErrorByMenuItemCommandID(command_id
);
401 return chrome::IsCommandEnabled(browser_
, command_id
);
404 bool WrenchMenuModel::IsCommandIdVisible(int command_id
) const {
405 switch (command_id
) {
407 case IDC_VIEW_INCOMPATIBILITIES
: {
408 EnumerateModulesModel
* loaded_modules
=
409 EnumerateModulesModel::GetInstance();
410 if (loaded_modules
->confirmed_bad_modules_detected() <= 0)
412 // We'll leave the wrench adornment on until the user clicks the link.
413 if (loaded_modules
->modules_to_notify_about() <= 0)
414 loaded_modules
->AcknowledgeConflictNotification();
417 case IDC_PIN_TO_START_SCREEN
:
418 return base::win::IsMetroProcess();
420 case IDC_VIEW_INCOMPATIBILITIES
:
421 case IDC_PIN_TO_START_SCREEN
:
424 case IDC_UPGRADE_DIALOG
:
425 return UpgradeDetector::GetInstance()->notify_upgrade();
426 #if !defined(OS_LINUX) || defined(USE_AURA)
427 case IDC_BOOKMARK_PAGE
:
428 return !chrome::ShouldRemoveBookmarkThisPageUI(browser_
->profile());
429 case IDC_BOOKMARK_ALL_TABS
:
430 return !chrome::ShouldRemoveBookmarkOpenPagesUI(browser_
->profile());
437 bool WrenchMenuModel::GetAcceleratorForCommandId(
439 ui::Accelerator
* accelerator
) {
440 return provider_
->GetAcceleratorForCommandId(command_id
, accelerator
);
443 void WrenchMenuModel::ActiveTabChanged(WebContents
* old_contents
,
444 WebContents
* new_contents
,
447 // The user has switched between tabs and the new tab may have a different
449 UpdateZoomControls();
452 void WrenchMenuModel::TabReplacedAt(TabStripModel
* tab_strip_model
,
453 WebContents
* old_contents
,
454 WebContents
* new_contents
,
456 UpdateZoomControls();
459 void WrenchMenuModel::TabStripModelDeleted() {
460 // During views shutdown, the tabstrip model/browser is deleted first, while
461 // it is the opposite in gtk land.
462 tab_strip_model_
->RemoveObserver(this);
463 tab_strip_model_
= NULL
;
466 void WrenchMenuModel::Observe(int type
,
467 const content::NotificationSource
& source
,
468 const content::NotificationDetails
& details
) {
469 DCHECK(type
== content::NOTIFICATION_NAV_ENTRY_COMMITTED
);
470 UpdateZoomControls();
474 WrenchMenuModel::WrenchMenuModel()
475 : ui::SimpleMenuModel(this),
478 tab_strip_model_(NULL
) {
481 bool WrenchMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
482 if (browser_
->profile()->IsManaged())
486 if (win8::IsSingleWindowMetroMode() &&
487 browser_
->profile()->HasOffTheRecordProfile()) {
492 return !browser_
->profile()->IsGuestSession();
495 bool WrenchMenuModel::ShouldShowNewWindowMenuItem() {
497 if (!win8::IsSingleWindowMetroMode())
500 // In Win8's single window Metro mode, we only show the New Window options
501 // if there isn't already a window of the requested type (incognito or not)
502 // that is available.
503 return browser_
->profile()->IsOffTheRecord() &&
504 !chrome::FindBrowserWithProfile(
505 browser_
->profile()->GetOriginalProfile(),
506 browser_
->host_desktop_type());
512 void WrenchMenuModel::Build(bool is_new_menu
) {
514 AddItem(IDC_VIEW_INCOMPATIBILITIES
,
515 l10n_util::GetStringUTF16(IDS_VIEW_INCOMPATIBILITIES
));
516 EnumerateModulesModel
* model
=
517 EnumerateModulesModel::GetInstance();
518 if (model
->modules_to_notify_about() > 0 ||
519 model
->confirmed_bad_modules_detected() > 0)
520 AddSeparator(ui::NORMAL_SEPARATOR
);
523 AddItemWithStringId(IDC_NEW_TAB
, IDS_NEW_TAB
);
524 if (ShouldShowNewWindowMenuItem())
525 AddItemWithStringId(IDC_NEW_WINDOW
, IDS_NEW_WINDOW
);
527 if (ShouldShowNewIncognitoWindowMenuItem())
528 AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW
, IDS_NEW_INCOGNITO_WINDOW
);
530 #if defined(OS_WIN) && !defined(NDEBUG) && defined(USE_ASH)
531 if (base::win::GetVersion() < base::win::VERSION_WIN8
&&
532 chrome::HOST_DESKTOP_TYPE_NATIVE
!= chrome::HOST_DESKTOP_TYPE_ASH
) {
533 AddItemWithStringId(IDC_TOGGLE_ASH_DESKTOP
,
534 ash::Shell::HasInstance() ? IDS_CLOSE_ASH_DESKTOP
:
535 IDS_OPEN_ASH_DESKTOP
);
539 bookmark_sub_menu_model_
.reset(new BookmarkSubMenuModel(this, browser_
));
540 AddSubMenuWithStringId(IDC_BOOKMARKS_MENU
, IDS_BOOKMARKS_MENU
,
541 bookmark_sub_menu_model_
.get());
543 if (chrome::IsInstantExtendedAPIEnabled()) {
544 recent_tabs_sub_menu_model_
.reset(new RecentTabsSubMenuModel(provider_
,
547 AddSubMenuWithStringId(IDC_RECENT_TABS_MENU
, IDS_RECENT_TABS_MENU
,
548 recent_tabs_sub_menu_model_
.get());
553 #if defined(USE_AURA)
554 if (base::win::GetVersion() >= base::win::VERSION_WIN8
&&
555 content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
556 if (browser_
->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH
) {
557 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
558 AddSeparator(ui::NORMAL_SEPARATOR
);
559 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART
, IDS_WIN8_DESKTOP_RESTART
);
561 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
562 AddSeparator(ui::NORMAL_SEPARATOR
);
563 AddItemWithStringId(IDC_WIN8_METRO_RESTART
, IDS_WIN8_METRO_RESTART
);
567 if (base::win::IsMetroProcess()) {
568 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
569 AddSeparator(ui::NORMAL_SEPARATOR
);
570 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART
, IDS_WIN8_DESKTOP_RESTART
);
572 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
573 AddSeparator(ui::NORMAL_SEPARATOR
);
574 AddItemWithStringId(IDC_WIN8_METRO_RESTART
, IDS_WIN8_METRO_RESTART
);
580 // Append the full menu including separators. The final separator only gets
581 // appended when this is a touch menu - otherwise it would get added twice.
582 CreateCutCopyPasteMenu(is_new_menu
);
585 CreateZoomMenu(is_new_menu
);
587 AddItemWithStringId(IDC_SAVE_PAGE
, IDS_SAVE_PAGE
);
588 AddItemWithStringId(IDC_FIND
, IDS_FIND
);
589 AddItemWithStringId(IDC_PRINT
, IDS_PRINT
);
591 tools_menu_model_
.reset(new ToolsMenuModel(this, browser_
));
592 // In case of touch this is the last item.
594 AddSubMenuWithStringId(IDC_ZOOM_MENU
, IDS_TOOLS_MENU
,
595 tools_menu_model_
.get());
599 CreateZoomMenu(is_new_menu
);
601 AddSeparator(ui::NORMAL_SEPARATOR
);
603 AddItemWithStringId(IDC_SHOW_HISTORY
, IDS_SHOW_HISTORY
);
604 AddItemWithStringId(IDC_SHOW_DOWNLOADS
, IDS_SHOW_DOWNLOADS
);
605 AddSeparator(ui::NORMAL_SEPARATOR
);
607 #if !defined(OS_CHROMEOS)
608 // No "Sign in to Chromium..." menu item on ChromeOS.
609 SigninManager
* signin
= SigninManagerFactory::GetForProfile(
610 browser_
->profile()->GetOriginalProfile());
611 if (signin
&& signin
->IsSigninAllowed()) {
612 const base::string16 short_product_name
=
613 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME
);
614 AddItem(IDC_SHOW_SYNC_SETUP
, l10n_util::GetStringFUTF16(
615 IDS_SYNC_MENU_PRE_SYNCED_LABEL
, short_product_name
));
616 AddSeparator(ui::NORMAL_SEPARATOR
);
620 AddItemWithStringId(IDC_OPTIONS
, IDS_SETTINGS
);
622 #if defined(OS_CHROMEOS)
623 if (CommandLine::ForCurrentProcess()->HasSwitch(
624 chromeos::switches::kEnableRequestTabletSite
))
625 AddCheckItemWithStringId(IDC_TOGGLE_REQUEST_TABLET_SITE
,
626 IDS_TOGGLE_REQUEST_TABLET_SITE
);
629 // On ChromeOS-Touch, we don't want the about menu option.
630 #if defined(OS_CHROMEOS)
634 AddItem(IDC_ABOUT
, l10n_util::GetStringUTF16(IDS_ABOUT
));
637 if (browser_defaults::kShowUpgradeMenuItem
)
638 AddItem(IDC_UPGRADE_DIALOG
, GetUpgradeDialogMenuItemName());
641 SetIcon(GetIndexOfCommandId(IDC_VIEW_INCOMPATIBILITIES
),
642 ui::ResourceBundle::GetSharedInstance().
643 GetNativeImageNamed(IDR_INPUT_ALERT_MENU
));
647 AddItemWithStringId(IDC_HELP_PAGE_VIA_MENU
, IDS_HELP_PAGE
);
649 if (browser_defaults::kShowHelpMenuItemIcon
) {
650 ui::ResourceBundle
& rb
= ResourceBundle::GetSharedInstance();
651 SetIcon(GetIndexOfCommandId(IDC_HELP_PAGE_VIA_MENU
),
652 rb
.GetNativeImageNamed(IDR_HELP_MENU
));
656 #if defined(GOOGLE_CHROME_BUILD)
657 #if defined(OS_CHROMEOS)
658 AddItemWithStringId(IDC_FEEDBACK
, IDS_FEEDBACK
);
662 AddGlobalErrorMenuItems();
665 AddSubMenuWithStringId(IDC_ZOOM_MENU
, IDS_MORE_TOOLS_MENU
,
666 tools_menu_model_
.get());
669 bool show_exit_menu
= browser_defaults::kShowExitMenuItem
;
671 if (browser_
->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH
)
672 show_exit_menu
= false;
675 if (show_exit_menu
) {
676 AddSeparator(ui::NORMAL_SEPARATOR
);
677 AddItemWithStringId(IDC_EXIT
, IDS_EXIT
);
681 void WrenchMenuModel::AddGlobalErrorMenuItems() {
682 // TODO(sail): Currently we only build the wrench menu once per browser
683 // window. This means that if a new error is added after the menu is built
684 // it won't show in the existing wrench menu. To fix this we need to some
685 // how update the menu if new errors are added.
686 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
687 // GetSignedInServiceErrors() can modify the global error list, so call it
688 // before iterating through that list below.
689 std::vector
<GlobalError
*> signin_errors
=
690 signin_ui_util::GetSignedInServiceErrors(
691 browser_
->profile()->GetOriginalProfile());
692 const GlobalErrorService::GlobalErrorList
& errors
=
693 GlobalErrorServiceFactory::GetForProfile(browser_
->profile())->errors();
694 for (GlobalErrorService::GlobalErrorList::const_iterator
695 it
= errors
.begin(); it
!= errors
.end(); ++it
) {
696 GlobalError
* error
= *it
;
698 if (error
->HasMenuItem()) {
699 #if !defined(OS_CHROMEOS)
700 // Don't add a signin error if it's already being displayed elsewhere.
701 if (std::find(signin_errors
.begin(), signin_errors
.end(), error
) !=
702 signin_errors
.end()) {
703 MenuModel
* model
= this;
705 if (MenuModel::GetModelAndIndexForCommandId(
706 IDC_SHOW_SIGNIN
, &model
, &index
)) {
712 AddItem(error
->MenuItemCommandID(), error
->MenuItemLabel());
713 int icon_id
= error
->MenuItemIconResourceID();
715 const gfx::Image
& image
= rb
.GetNativeImageNamed(icon_id
);
716 SetIcon(GetIndexOfCommandId(error
->MenuItemCommandID()),
723 void WrenchMenuModel::CreateCutCopyPasteMenu(bool new_menu
) {
724 AddSeparator(new_menu
? ui::LOWER_SEPARATOR
: ui::NORMAL_SEPARATOR
);
726 #if defined(OS_POSIX) && !defined(TOOLKIT_VIEWS)
727 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
728 // layout for this menu item in Toolbar.xib. It does, however, use the
729 // command_id value from AddButtonItem() to identify this special item.
730 edit_menu_item_model_
.reset(new ui::ButtonMenuItemModel(IDS_EDIT
, this));
731 edit_menu_item_model_
->AddGroupItemWithStringId(IDC_CUT
, IDS_CUT
);
732 edit_menu_item_model_
->AddGroupItemWithStringId(IDC_COPY
, IDS_COPY
);
733 edit_menu_item_model_
->AddGroupItemWithStringId(IDC_PASTE
, IDS_PASTE
);
734 AddButtonItem(IDC_EDIT_MENU
, edit_menu_item_model_
.get());
736 // WARNING: views/wrench_menu assumes these items are added in this order. If
737 // you change the order you'll need to update wrench_menu as well.
738 AddItemWithStringId(IDC_CUT
, IDS_CUT
);
739 AddItemWithStringId(IDC_COPY
, IDS_COPY
);
740 AddItemWithStringId(IDC_PASTE
, IDS_PASTE
);
744 AddSeparator(ui::UPPER_SEPARATOR
);
747 void WrenchMenuModel::CreateZoomMenu(bool new_menu
) {
748 // This menu needs to be enclosed by separators.
749 AddSeparator(new_menu
? ui::LOWER_SEPARATOR
: ui::NORMAL_SEPARATOR
);
751 #if defined(OS_POSIX) && !defined(TOOLKIT_VIEWS)
752 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
753 // layout for this menu item in Toolbar.xib. It does, however, use the
754 // command_id value from AddButtonItem() to identify this special item.
755 zoom_menu_item_model_
.reset(
756 new ui::ButtonMenuItemModel(IDS_ZOOM_MENU
, this));
757 zoom_menu_item_model_
->AddGroupItemWithStringId(
758 IDC_ZOOM_MINUS
, IDS_ZOOM_MINUS2
);
759 zoom_menu_item_model_
->AddButtonLabel(IDC_ZOOM_PERCENT_DISPLAY
,
761 zoom_menu_item_model_
->AddGroupItemWithStringId(
762 IDC_ZOOM_PLUS
, IDS_ZOOM_PLUS2
);
763 zoom_menu_item_model_
->AddSpace();
764 zoom_menu_item_model_
->AddItemWithImage(
765 IDC_FULLSCREEN
, IDR_FULLSCREEN_MENU_BUTTON
);
766 AddButtonItem(IDC_ZOOM_MENU
, zoom_menu_item_model_
.get());
768 // WARNING: views/wrench_menu assumes these items are added in this order. If
769 // you change the order you'll need to update wrench_menu as well.
770 AddItemWithStringId(IDC_ZOOM_MINUS
, IDS_ZOOM_MINUS
);
771 AddItemWithStringId(IDC_ZOOM_PLUS
, IDS_ZOOM_PLUS
);
772 AddItemWithStringId(IDC_FULLSCREEN
, IDS_FULLSCREEN
);
775 AddSeparator(new_menu
? ui::UPPER_SEPARATOR
: ui::NORMAL_SEPARATOR
);
778 void WrenchMenuModel::UpdateZoomControls() {
779 bool enable_increment
= false;
780 bool enable_decrement
= false;
781 int zoom_percent
= 100;
782 if (browser_
->tab_strip_model()->GetActiveWebContents()) {
784 browser_
->tab_strip_model()->GetActiveWebContents()->GetZoomPercent(
785 &enable_increment
, &enable_decrement
);
787 zoom_label_
= l10n_util::GetStringFUTF16(
788 IDS_ZOOM_PERCENT
, base::IntToString16(zoom_percent
));
791 void WrenchMenuModel::OnZoomLevelChanged(
792 const content::HostZoomMap::ZoomLevelChange
& change
) {
793 UpdateZoomControls();