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 "components/signin/core/common/profile_management_switches.h"
43 #include "content/public/browser/host_zoom_map.h"
44 #include "content/public/browser/navigation_entry.h"
45 #include "content/public/browser/notification_service.h"
46 #include "content/public/browser/notification_source.h"
47 #include "content/public/browser/notification_types.h"
48 #include "content/public/browser/user_metrics.h"
49 #include "content/public/browser/web_contents.h"
50 #include "grit/chromium_strings.h"
51 #include "grit/generated_resources.h"
52 #include "grit/theme_resources.h"
53 #include "ui/base/l10n/l10n_util.h"
54 #include "ui/base/layout.h"
55 #include "ui/base/models/button_menu_item_model.h"
56 #include "ui/base/resource/resource_bundle.h"
57 #include "ui/gfx/image/image.h"
58 #include "ui/gfx/image/image_skia.h"
60 #if defined(OS_CHROMEOS)
61 #include "chromeos/chromeos_switches.h"
65 #include "base/win/metro.h"
66 #include "base/win/windows_version.h"
67 #include "chrome/browser/enumerate_modules_model_win.h"
68 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
69 #include "content/public/browser/gpu_data_manager.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 #if defined(GOOGLE_CHROME_BUILD)
186 class WrenchMenuModel::HelpMenuModel
: public ui::SimpleMenuModel
{
188 HelpMenuModel(ui::SimpleMenuModel::Delegate
* delegate
,
190 : SimpleMenuModel(delegate
) {
193 virtual ~HelpMenuModel() {
197 void Build(Browser
* browser
) {
198 int help_string_id
= IDS_HELP_PAGE
;
199 #if defined(OS_CHROMEOS)
200 if (!CommandLine::ForCurrentProcess()->HasSwitch(
201 chromeos::switches::kDisableGeniusApp
)) {
202 help_string_id
= IDS_GENIUS_APP_NAME
;
205 AddItemWithStringId(IDC_HELP_PAGE_VIA_MENU
, help_string_id
);
206 if (browser_defaults::kShowHelpMenuItemIcon
) {
207 ui::ResourceBundle
& rb
= ResourceBundle::GetSharedInstance();
208 SetIcon(GetIndexOfCommandId(IDC_HELP_PAGE_VIA_MENU
),
209 rb
.GetNativeImageNamed(IDR_HELP_MENU
));
212 AddItemWithStringId(IDC_FEEDBACK
, IDS_FEEDBACK
);
215 DISALLOW_COPY_AND_ASSIGN(HelpMenuModel
);
218 #endif // defined(GOOGLE_CHROME_BUILD)
220 ////////////////////////////////////////////////////////////////////////////////
223 ToolsMenuModel::ToolsMenuModel(ui::SimpleMenuModel::Delegate
* delegate
,
225 : SimpleMenuModel(delegate
) {
229 ToolsMenuModel::~ToolsMenuModel() {}
231 void ToolsMenuModel::Build(Browser
* browser
) {
232 bool show_create_shortcuts
= true;
233 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
234 show_create_shortcuts
= false;
235 #elif defined(USE_ASH)
236 if (browser
->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH
)
237 show_create_shortcuts
= false;
240 if (CommandLine::ForCurrentProcess()->HasSwitch(
241 switches::kEnableStreamlinedHostedApps
)) {
242 AddItemWithStringId(IDC_CREATE_HOSTED_APP
, IDS_CREATE_HOSTED_APP
);
243 AddSeparator(ui::NORMAL_SEPARATOR
);
244 } else if (show_create_shortcuts
) {
245 AddItemWithStringId(IDC_CREATE_SHORTCUTS
, IDS_CREATE_SHORTCUTS
);
246 AddSeparator(ui::NORMAL_SEPARATOR
);
249 AddItemWithStringId(IDC_MANAGE_EXTENSIONS
, IDS_SHOW_EXTENSIONS
);
251 if (chrome::CanOpenTaskManager())
252 AddItemWithStringId(IDC_TASK_MANAGER
, IDS_TASK_MANAGER
);
254 AddItemWithStringId(IDC_CLEAR_BROWSING_DATA
, IDS_CLEAR_BROWSING_DATA
);
256 AddSeparator(ui::NORMAL_SEPARATOR
);
258 encoding_menu_model_
.reset(new EncodingMenuModel(browser
));
259 AddSubMenuWithStringId(IDC_ENCODING_MENU
, IDS_ENCODING_MENU
,
260 encoding_menu_model_
.get());
261 AddItemWithStringId(IDC_VIEW_SOURCE
, IDS_VIEW_SOURCE
);
262 AddItemWithStringId(IDC_DEV_TOOLS
, IDS_DEV_TOOLS
);
263 AddItemWithStringId(IDC_DEV_TOOLS_CONSOLE
, IDS_DEV_TOOLS_CONSOLE
);
264 AddItemWithStringId(IDC_DEV_TOOLS_DEVICES
, IDS_DEV_TOOLS_DEVICES
);
266 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
267 AddSeparator(ui::NORMAL_SEPARATOR
);
268 AddCheckItemWithStringId(IDC_PROFILING_ENABLED
, IDS_PROFILING_ENABLED
);
272 ////////////////////////////////////////////////////////////////////////////////
275 WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider
* provider
,
278 : ui::SimpleMenuModel(this),
281 tab_strip_model_(browser_
->tab_strip_model()) {
283 UpdateZoomControls();
285 zoom_subscription_
= HostZoomMap::GetForBrowserContext(
286 browser
->profile())->AddZoomLevelChangedCallback(
287 base::Bind(&WrenchMenuModel::OnZoomLevelChanged
,
288 base::Unretained(this)));
290 tab_strip_model_
->AddObserver(this);
292 registrar_
.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED
,
293 content::NotificationService::AllSources());
296 WrenchMenuModel::~WrenchMenuModel() {
297 if (tab_strip_model_
)
298 tab_strip_model_
->RemoveObserver(this);
301 bool WrenchMenuModel::DoesCommandIdDismissMenu(int command_id
) const {
302 return command_id
!= IDC_ZOOM_MINUS
&& command_id
!= IDC_ZOOM_PLUS
;
305 bool WrenchMenuModel::IsItemForCommandIdDynamic(int command_id
) const {
306 return command_id
== IDC_ZOOM_PERCENT_DISPLAY
||
307 #if defined(OS_MACOSX)
308 command_id
== IDC_FULLSCREEN
||
309 #elif defined(OS_WIN)
310 command_id
== IDC_PIN_TO_START_SCREEN
||
312 command_id
== IDC_UPGRADE_DIALOG
||
313 (!switches::IsNewProfileManagement() && command_id
== IDC_SHOW_SIGNIN
);
316 base::string16
WrenchMenuModel::GetLabelForCommandId(int command_id
) const {
317 switch (command_id
) {
318 case IDC_ZOOM_PERCENT_DISPLAY
:
320 #if defined(OS_MACOSX)
321 case IDC_FULLSCREEN
: {
322 int string_id
= IDS_ENTER_FULLSCREEN_MAC
; // Default to Enter.
323 // Note: On startup, |window()| may be NULL.
324 if (browser_
->window() && browser_
->window()->IsFullscreen())
325 string_id
= IDS_EXIT_FULLSCREEN_MAC
;
326 return l10n_util::GetStringUTF16(string_id
);
328 #elif defined(OS_WIN)
329 case IDC_PIN_TO_START_SCREEN
: {
330 int string_id
= IDS_PIN_TO_START_SCREEN
;
331 WebContents
* web_contents
=
332 browser_
->tab_strip_model()->GetActiveWebContents();
333 MetroPinTabHelper
* tab_helper
=
334 web_contents
? MetroPinTabHelper::FromWebContents(web_contents
)
336 if (tab_helper
&& tab_helper
->IsPinned())
337 string_id
= IDS_UNPIN_FROM_START_SCREEN
;
338 return l10n_util::GetStringUTF16(string_id
);
341 case IDC_UPGRADE_DIALOG
:
342 return GetUpgradeDialogMenuItemName();
343 case IDC_SHOW_SIGNIN
:
344 DCHECK(!switches::IsNewProfileManagement());
345 return signin_ui_util::GetSigninMenuLabel(
346 browser_
->profile()->GetOriginalProfile());
349 return base::string16();
353 bool WrenchMenuModel::GetIconForCommandId(int command_id
,
354 gfx::Image
* icon
) const {
355 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
356 switch (command_id
) {
357 case IDC_UPGRADE_DIALOG
: {
358 if (UpgradeDetector::GetInstance()->notify_upgrade()) {
359 *icon
= rb
.GetNativeImageNamed(
360 UpgradeDetector::GetInstance()->GetIconResourceID(
361 UpgradeDetector::UPGRADE_ICON_TYPE_MENU_ICON
));
366 case IDC_SHOW_SIGNIN
: {
367 DCHECK(!switches::IsNewProfileManagement());
368 GlobalError
* error
= signin_ui_util::GetSignedInServiceError(
369 browser_
->profile()->GetOriginalProfile());
371 int icon_id
= error
->MenuItemIconResourceID();
373 *icon
= rb
.GetNativeImageNamed(icon_id
);
385 void WrenchMenuModel::ExecuteCommand(int command_id
, int event_flags
) {
386 GlobalError
* error
= GlobalErrorServiceFactory::GetForProfile(
387 browser_
->profile())->GetGlobalErrorByMenuItemCommandID(command_id
);
389 error
->ExecuteMenuItem(browser_
);
393 if (!switches::IsNewProfileManagement() && command_id
== IDC_SHOW_SIGNIN
) {
394 // If a custom error message is being shown, handle it.
395 GlobalError
* error
= signin_ui_util::GetSignedInServiceError(
396 browser_
->profile()->GetOriginalProfile());
398 error
->ExecuteMenuItem(browser_
);
403 if (command_id
== IDC_HELP_PAGE_VIA_MENU
)
404 content::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));
406 if (command_id
== IDC_FULLSCREEN
) {
407 // We issue the UMA command here and not in BrowserCommandController or even
408 // FullscreenController since we want to be able to distinguish this event
409 // and a menu which is under development.
410 content::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));
413 chrome::ExecuteCommand(browser_
, command_id
);
416 bool WrenchMenuModel::IsCommandIdChecked(int command_id
) const {
417 if (command_id
== IDC_SHOW_BOOKMARK_BAR
) {
418 return browser_
->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar
);
419 } else if (command_id
== IDC_PROFILING_ENABLED
) {
420 return Profiling::BeingProfiled();
421 } else if (command_id
== IDC_TOGGLE_REQUEST_TABLET_SITE
) {
422 return chrome::IsRequestingTabletSite(browser_
);
428 bool WrenchMenuModel::IsCommandIdEnabled(int command_id
) const {
429 GlobalError
* error
= GlobalErrorServiceFactory::GetForProfile(
430 browser_
->profile())->GetGlobalErrorByMenuItemCommandID(command_id
);
434 return chrome::IsCommandEnabled(browser_
, command_id
);
437 bool WrenchMenuModel::IsCommandIdVisible(int command_id
) const {
438 switch (command_id
) {
440 case IDC_VIEW_INCOMPATIBILITIES
: {
441 EnumerateModulesModel
* loaded_modules
=
442 EnumerateModulesModel::GetInstance();
443 if (loaded_modules
->confirmed_bad_modules_detected() <= 0)
445 // We'll leave the wrench adornment on until the user clicks the link.
446 if (loaded_modules
->modules_to_notify_about() <= 0)
447 loaded_modules
->AcknowledgeConflictNotification();
450 case IDC_PIN_TO_START_SCREEN
:
451 return base::win::IsMetroProcess();
453 case IDC_VIEW_INCOMPATIBILITIES
:
454 case IDC_PIN_TO_START_SCREEN
:
457 case IDC_UPGRADE_DIALOG
:
458 return UpgradeDetector::GetInstance()->notify_upgrade();
459 #if !defined(OS_LINUX) || defined(USE_AURA)
460 case IDC_BOOKMARK_PAGE
:
461 return !chrome::ShouldRemoveBookmarkThisPageUI(browser_
->profile());
462 case IDC_BOOKMARK_ALL_TABS
:
463 return !chrome::ShouldRemoveBookmarkOpenPagesUI(browser_
->profile());
470 bool WrenchMenuModel::GetAcceleratorForCommandId(
472 ui::Accelerator
* accelerator
) {
473 return provider_
->GetAcceleratorForCommandId(command_id
, accelerator
);
476 void WrenchMenuModel::ActiveTabChanged(WebContents
* old_contents
,
477 WebContents
* new_contents
,
480 // The user has switched between tabs and the new tab may have a different
482 UpdateZoomControls();
485 void WrenchMenuModel::TabReplacedAt(TabStripModel
* tab_strip_model
,
486 WebContents
* old_contents
,
487 WebContents
* new_contents
,
489 UpdateZoomControls();
492 void WrenchMenuModel::TabStripModelDeleted() {
493 // During views shutdown, the tabstrip model/browser is deleted first, while
494 // it is the opposite in gtk land.
495 tab_strip_model_
->RemoveObserver(this);
496 tab_strip_model_
= NULL
;
499 void WrenchMenuModel::Observe(int type
,
500 const content::NotificationSource
& source
,
501 const content::NotificationDetails
& details
) {
502 DCHECK(type
== content::NOTIFICATION_NAV_ENTRY_COMMITTED
);
503 UpdateZoomControls();
507 WrenchMenuModel::WrenchMenuModel()
508 : ui::SimpleMenuModel(this),
511 tab_strip_model_(NULL
) {
514 bool WrenchMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
515 if (browser_
->profile()->IsManaged())
518 return !browser_
->profile()->IsGuestSession();
521 void WrenchMenuModel::Build(bool is_new_menu
) {
523 AddItem(IDC_VIEW_INCOMPATIBILITIES
,
524 l10n_util::GetStringUTF16(IDS_VIEW_INCOMPATIBILITIES
));
525 EnumerateModulesModel
* model
=
526 EnumerateModulesModel::GetInstance();
527 if (model
->modules_to_notify_about() > 0 ||
528 model
->confirmed_bad_modules_detected() > 0)
529 AddSeparator(ui::NORMAL_SEPARATOR
);
532 AddItemWithStringId(IDC_NEW_TAB
, IDS_NEW_TAB
);
533 AddItemWithStringId(IDC_NEW_WINDOW
, IDS_NEW_WINDOW
);
535 if (ShouldShowNewIncognitoWindowMenuItem())
536 AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW
, IDS_NEW_INCOGNITO_WINDOW
);
538 #if defined(OS_WIN) && !defined(NDEBUG) && defined(USE_ASH)
539 if (base::win::GetVersion() < base::win::VERSION_WIN8
&&
540 chrome::HOST_DESKTOP_TYPE_NATIVE
!= chrome::HOST_DESKTOP_TYPE_ASH
) {
541 AddItemWithStringId(IDC_TOGGLE_ASH_DESKTOP
,
542 ash::Shell::HasInstance() ? IDS_CLOSE_ASH_DESKTOP
:
543 IDS_OPEN_ASH_DESKTOP
);
547 bookmark_sub_menu_model_
.reset(new BookmarkSubMenuModel(this, browser_
));
548 AddSubMenuWithStringId(IDC_BOOKMARKS_MENU
, IDS_BOOKMARKS_MENU
,
549 bookmark_sub_menu_model_
.get());
551 if (!browser_
->profile()->IsOffTheRecord()) {
552 recent_tabs_sub_menu_model_
.reset(new RecentTabsSubMenuModel(provider_
,
555 AddSubMenuWithStringId(IDC_RECENT_TABS_MENU
, IDS_RECENT_TABS_MENU
,
556 recent_tabs_sub_menu_model_
.get());
561 #if defined(USE_AURA)
562 if (base::win::GetVersion() >= base::win::VERSION_WIN8
&&
563 content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
564 if (browser_
->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH
) {
565 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
566 AddSeparator(ui::NORMAL_SEPARATOR
);
567 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART
, IDS_WIN8_DESKTOP_RESTART
);
569 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
570 AddSeparator(ui::NORMAL_SEPARATOR
);
571 AddItemWithStringId(IDC_WIN8_METRO_RESTART
, IDS_WIN8_METRO_RESTART
);
575 if (base::win::IsMetroProcess()) {
576 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
577 AddSeparator(ui::NORMAL_SEPARATOR
);
578 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART
, IDS_WIN8_DESKTOP_RESTART
);
580 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
581 AddSeparator(ui::NORMAL_SEPARATOR
);
582 AddItemWithStringId(IDC_WIN8_METRO_RESTART
, IDS_WIN8_METRO_RESTART
);
588 // Append the full menu including separators. The final separator only gets
589 // appended when this is a touch menu - otherwise it would get added twice.
590 CreateCutCopyPasteMenu(is_new_menu
);
593 CreateZoomMenu(is_new_menu
);
595 if (CommandLine::ForCurrentProcess()->HasSwitch(
596 switches::kEnableDomDistiller
)) {
597 AddItemWithStringId(IDC_DISTILL_PAGE
, IDS_DISTILL_PAGE
);
600 AddItemWithStringId(IDC_SAVE_PAGE
, IDS_SAVE_PAGE
);
601 AddItemWithStringId(IDC_FIND
, IDS_FIND
);
602 AddItemWithStringId(IDC_PRINT
, IDS_PRINT
);
604 tools_menu_model_
.reset(new ToolsMenuModel(this, browser_
));
605 // In case of touch this is the last item.
607 AddSubMenuWithStringId(IDC_ZOOM_MENU
, IDS_TOOLS_MENU
,
608 tools_menu_model_
.get());
612 CreateZoomMenu(is_new_menu
);
614 AddSeparator(ui::NORMAL_SEPARATOR
);
616 AddItemWithStringId(IDC_SHOW_HISTORY
, IDS_SHOW_HISTORY
);
617 AddItemWithStringId(IDC_SHOW_DOWNLOADS
, IDS_SHOW_DOWNLOADS
);
618 AddSeparator(ui::NORMAL_SEPARATOR
);
620 #if !defined(OS_CHROMEOS)
621 if (!switches::IsNewProfileManagement()) {
622 // No "Sign in to Chromium..." menu item on ChromeOS.
623 SigninManager
* signin
= SigninManagerFactory::GetForProfile(
624 browser_
->profile()->GetOriginalProfile());
625 if (signin
&& signin
->IsSigninAllowed()) {
626 const base::string16 short_product_name
=
627 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME
);
628 AddItem(IDC_SHOW_SYNC_SETUP
, l10n_util::GetStringFUTF16(
629 IDS_SYNC_MENU_PRE_SYNCED_LABEL
, short_product_name
));
630 AddSeparator(ui::NORMAL_SEPARATOR
);
635 AddItemWithStringId(IDC_OPTIONS
, IDS_SETTINGS
);
637 #if defined(GOOGLE_CHROME_BUILD)
638 help_menu_model_
.reset(new HelpMenuModel(this, browser_
));
639 AddSubMenuWithStringId(IDC_HELP_MENU
, IDS_HELP_MENU
,
640 help_menu_model_
.get());
641 AddSeparator(ui::NORMAL_SEPARATOR
);
644 #if defined(OS_CHROMEOS)
645 if (CommandLine::ForCurrentProcess()->HasSwitch(
646 chromeos::switches::kEnableRequestTabletSite
))
647 AddCheckItemWithStringId(IDC_TOGGLE_REQUEST_TABLET_SITE
,
648 IDS_TOGGLE_REQUEST_TABLET_SITE
);
651 if (browser_defaults::kShowUpgradeMenuItem
)
652 AddItem(IDC_UPGRADE_DIALOG
, GetUpgradeDialogMenuItemName());
655 SetIcon(GetIndexOfCommandId(IDC_VIEW_INCOMPATIBILITIES
),
656 ui::ResourceBundle::GetSharedInstance().
657 GetNativeImageNamed(IDR_INPUT_ALERT_MENU
));
660 AddGlobalErrorMenuItems();
663 AddSubMenuWithStringId(IDC_ZOOM_MENU
, IDS_MORE_TOOLS_MENU
,
664 tools_menu_model_
.get());
667 bool show_exit_menu
= browser_defaults::kShowExitMenuItem
;
669 if (browser_
->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH
)
670 show_exit_menu
= false;
673 if (show_exit_menu
) {
674 AddSeparator(ui::NORMAL_SEPARATOR
);
675 AddItemWithStringId(IDC_EXIT
, IDS_EXIT
);
678 RemoveTrailingSeparators();
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 if (!switches::IsNewProfileManagement()) {
691 signin_errors
= signin_ui_util::GetSignedInServiceErrors(
692 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
;
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;
707 if (MenuModel::GetModelAndIndexForCommandId(
708 IDC_SHOW_SIGNIN
, &model
, &index
)) {
714 AddItem(error
->MenuItemCommandID(), error
->MenuItemLabel());
715 int icon_id
= error
->MenuItemIconResourceID();
717 const gfx::Image
& image
= rb
.GetNativeImageNamed(icon_id
);
718 SetIcon(GetIndexOfCommandId(error
->MenuItemCommandID()),
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());
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
);
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
,
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());
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
);
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()) {
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();