Refactor views app list services to allow more code sharing
[chromium-blink-merge.git] / chrome / browser / ui / toolbar / wrench_menu_model.cc
blob13dc11019fd981742575c1952363a01a20b0e834
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_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"
61 #endif
63 #if defined(OS_WIN)
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 #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 UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
85 return l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_MENU_ITEM);
86 } else {
87 return l10n_util::GetStringUTF16(IDS_UPDATE_NOW);
91 } // namespace
93 ////////////////////////////////////////////////////////////////////////////////
94 // EncodingMenuModel
96 EncodingMenuModel::EncodingMenuModel(Browser* browser)
97 : ui::SimpleMenuModel(this),
98 browser_(browser) {
99 Build();
102 EncodingMenuModel::~EncodingMenuModel() {
105 void EncodingMenuModel::Build() {
106 EncodingMenuController::EncodingMenuItemList encoding_menu_items;
107 EncodingMenuController encoding_menu_controller;
108 encoding_menu_controller.GetEncodingMenuItems(browser_->profile(),
109 &encoding_menu_items);
111 int group_id = 0;
112 EncodingMenuController::EncodingMenuItemList::iterator it =
113 encoding_menu_items.begin();
114 for (; it != encoding_menu_items.end(); ++it) {
115 int id = it->first;
116 base::string16& label = it->second;
117 if (id == 0) {
118 AddSeparator(ui::NORMAL_SEPARATOR);
119 } else {
120 if (id == IDC_ENCODING_AUTO_DETECT) {
121 AddCheckItem(id, label);
122 } else {
123 // Use the id of the first radio command as the id of the group.
124 if (group_id <= 0)
125 group_id = id;
126 AddRadioItem(id, label, group_id);
132 bool EncodingMenuModel::IsCommandIdChecked(int command_id) const {
133 WebContents* current_tab =
134 browser_->tab_strip_model()->GetActiveWebContents();
135 if (!current_tab)
136 return false;
137 EncodingMenuController controller;
138 return controller.IsItemChecked(browser_->profile(),
139 current_tab->GetEncoding(), command_id);
142 bool EncodingMenuModel::IsCommandIdEnabled(int command_id) const {
143 bool enabled = chrome::IsCommandEnabled(browser_, command_id);
144 // Special handling for the contents of the Encoding submenu. On Mac OS,
145 // instead of enabling/disabling the top-level menu item, the submenu's
146 // contents get disabled, per Apple's HIG.
147 #if defined(OS_MACOSX)
148 enabled &= chrome::IsCommandEnabled(browser_, IDC_ENCODING_MENU);
149 #endif
150 return enabled;
153 bool EncodingMenuModel::GetAcceleratorForCommandId(
154 int command_id,
155 ui::Accelerator* accelerator) {
156 return false;
159 void EncodingMenuModel::ExecuteCommand(int command_id, int event_flags) {
160 chrome::ExecuteCommand(browser_, command_id);
163 ////////////////////////////////////////////////////////////////////////////////
164 // ZoomMenuModel
166 ZoomMenuModel::ZoomMenuModel(ui::SimpleMenuModel::Delegate* delegate)
167 : SimpleMenuModel(delegate) {
168 Build();
171 ZoomMenuModel::~ZoomMenuModel() {
174 void ZoomMenuModel::Build() {
175 AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS);
176 AddItemWithStringId(IDC_ZOOM_NORMAL, IDS_ZOOM_NORMAL);
177 AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS);
180 ////////////////////////////////////////////////////////////////////////////////
181 // ToolsMenuModel
183 ToolsMenuModel::ToolsMenuModel(ui::SimpleMenuModel::Delegate* delegate,
184 Browser* browser)
185 : SimpleMenuModel(delegate) {
186 Build(browser);
189 ToolsMenuModel::~ToolsMenuModel() {}
191 void ToolsMenuModel::Build(Browser* browser) {
192 bool show_create_shortcuts = true;
193 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
194 show_create_shortcuts = false;
195 #elif defined(USE_ASH)
196 if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
197 show_create_shortcuts = false;
198 #endif
200 if (CommandLine::ForCurrentProcess()->HasSwitch(
201 switches::kEnableStreamlinedHostedApps)) {
202 AddItemWithStringId(IDC_CREATE_HOSTED_APP, IDS_CREATE_HOSTED_APP);
203 AddSeparator(ui::NORMAL_SEPARATOR);
204 } else if (show_create_shortcuts) {
205 AddItemWithStringId(IDC_CREATE_SHORTCUTS, IDS_CREATE_SHORTCUTS);
206 AddSeparator(ui::NORMAL_SEPARATOR);
209 AddItemWithStringId(IDC_MANAGE_EXTENSIONS, IDS_SHOW_EXTENSIONS);
211 if (chrome::CanOpenTaskManager())
212 AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
214 AddItemWithStringId(IDC_CLEAR_BROWSING_DATA, IDS_CLEAR_BROWSING_DATA);
216 AddSeparator(ui::NORMAL_SEPARATOR);
218 #if defined(GOOGLE_CHROME_BUILD)
219 #if !defined(OS_CHROMEOS)
220 // Show IDC_FEEDBACK in "Tools" menu for non-ChromeOS platforms.
221 AddItemWithStringId(IDC_FEEDBACK, IDS_FEEDBACK);
222 AddSeparator(ui::NORMAL_SEPARATOR);
223 #endif
224 #endif // GOOGLE_CHROME_BUILD
226 encoding_menu_model_.reset(new EncodingMenuModel(browser));
227 AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
228 encoding_menu_model_.get());
229 AddItemWithStringId(IDC_VIEW_SOURCE, IDS_VIEW_SOURCE);
230 AddItemWithStringId(IDC_DEV_TOOLS, IDS_DEV_TOOLS);
231 AddItemWithStringId(IDC_DEV_TOOLS_CONSOLE, IDS_DEV_TOOLS_CONSOLE);
232 AddItemWithStringId(IDC_DEV_TOOLS_DEVICES, IDS_DEV_TOOLS_DEVICES);
234 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
235 AddSeparator(ui::NORMAL_SEPARATOR);
236 AddCheckItemWithStringId(IDC_PROFILING_ENABLED, IDS_PROFILING_ENABLED);
237 #endif
240 ////////////////////////////////////////////////////////////////////////////////
241 // WrenchMenuModel
243 WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider* provider,
244 Browser* browser,
245 bool is_new_menu)
246 : ui::SimpleMenuModel(this),
247 provider_(provider),
248 browser_(browser),
249 tab_strip_model_(browser_->tab_strip_model()) {
250 Build(is_new_menu);
251 UpdateZoomControls();
253 zoom_subscription_ = HostZoomMap::GetForBrowserContext(
254 browser->profile())->AddZoomLevelChangedCallback(
255 base::Bind(&WrenchMenuModel::OnZoomLevelChanged,
256 base::Unretained(this)));
258 tab_strip_model_->AddObserver(this);
260 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
261 content::NotificationService::AllSources());
264 WrenchMenuModel::~WrenchMenuModel() {
265 if (tab_strip_model_)
266 tab_strip_model_->RemoveObserver(this);
269 bool WrenchMenuModel::DoesCommandIdDismissMenu(int command_id) const {
270 return command_id != IDC_ZOOM_MINUS && command_id != IDC_ZOOM_PLUS;
273 bool WrenchMenuModel::IsItemForCommandIdDynamic(int command_id) const {
274 return command_id == IDC_ZOOM_PERCENT_DISPLAY ||
275 #if defined(OS_MACOSX)
276 command_id == IDC_FULLSCREEN ||
277 #elif defined(OS_WIN)
278 command_id == IDC_PIN_TO_START_SCREEN ||
279 #endif
280 command_id == IDC_UPGRADE_DIALOG ||
281 command_id == IDC_SHOW_SIGNIN;
284 base::string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const {
285 switch (command_id) {
286 case IDC_ZOOM_PERCENT_DISPLAY:
287 return zoom_label_;
288 #if defined(OS_MACOSX)
289 case IDC_FULLSCREEN: {
290 int string_id = IDS_ENTER_FULLSCREEN_MAC; // Default to Enter.
291 // Note: On startup, |window()| may be NULL.
292 if (browser_->window() && browser_->window()->IsFullscreen())
293 string_id = IDS_EXIT_FULLSCREEN_MAC;
294 return l10n_util::GetStringUTF16(string_id);
296 #elif defined(OS_WIN)
297 case IDC_PIN_TO_START_SCREEN: {
298 int string_id = IDS_PIN_TO_START_SCREEN;
299 WebContents* web_contents =
300 browser_->tab_strip_model()->GetActiveWebContents();
301 MetroPinTabHelper* tab_helper =
302 web_contents ? MetroPinTabHelper::FromWebContents(web_contents)
303 : NULL;
304 if (tab_helper && tab_helper->IsPinned())
305 string_id = IDS_UNPIN_FROM_START_SCREEN;
306 return l10n_util::GetStringUTF16(string_id);
308 #endif
309 case IDC_UPGRADE_DIALOG:
310 return GetUpgradeDialogMenuItemName();
311 case IDC_SHOW_SIGNIN:
312 return signin_ui_util::GetSigninMenuLabel(
313 browser_->profile()->GetOriginalProfile());
314 default:
315 NOTREACHED();
316 return base::string16();
320 bool WrenchMenuModel::GetIconForCommandId(int command_id,
321 gfx::Image* icon) const {
322 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
323 switch (command_id) {
324 case IDC_UPGRADE_DIALOG: {
325 if (UpgradeDetector::GetInstance()->notify_upgrade()) {
326 *icon = rb.GetNativeImageNamed(
327 UpgradeDetector::GetInstance()->GetIconResourceID(
328 UpgradeDetector::UPGRADE_ICON_TYPE_MENU_ICON));
329 return true;
331 return false;
333 case IDC_SHOW_SIGNIN: {
334 GlobalError* error = signin_ui_util::GetSignedInServiceError(
335 browser_->profile()->GetOriginalProfile());
336 if (error) {
337 int icon_id = error->MenuItemIconResourceID();
338 if (icon_id) {
339 *icon = rb.GetNativeImageNamed(icon_id);
340 return true;
343 return false;
345 default:
346 break;
348 return false;
351 void WrenchMenuModel::ExecuteCommand(int command_id, int event_flags) {
352 GlobalError* error = GlobalErrorServiceFactory::GetForProfile(
353 browser_->profile())->GetGlobalErrorByMenuItemCommandID(command_id);
354 if (error) {
355 error->ExecuteMenuItem(browser_);
356 return;
359 if (command_id == IDC_SHOW_SIGNIN) {
360 // If a custom error message is being shown, handle it.
361 GlobalError* error = signin_ui_util::GetSignedInServiceError(
362 browser_->profile()->GetOriginalProfile());
363 if (error) {
364 error->ExecuteMenuItem(browser_);
365 return;
369 if (command_id == IDC_HELP_PAGE_VIA_MENU)
370 content::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));
372 if (command_id == IDC_FULLSCREEN) {
373 // We issue the UMA command here and not in BrowserCommandController or even
374 // FullscreenController since we want to be able to distinguish this event
375 // and a menu which is under development.
376 content::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));
379 chrome::ExecuteCommand(browser_, command_id);
382 bool WrenchMenuModel::IsCommandIdChecked(int command_id) const {
383 if (command_id == IDC_SHOW_BOOKMARK_BAR) {
384 return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
385 } else if (command_id == IDC_PROFILING_ENABLED) {
386 return Profiling::BeingProfiled();
387 } else if (command_id == IDC_TOGGLE_REQUEST_TABLET_SITE) {
388 return chrome::IsRequestingTabletSite(browser_);
391 return false;
394 bool WrenchMenuModel::IsCommandIdEnabled(int command_id) const {
395 GlobalError* error = GlobalErrorServiceFactory::GetForProfile(
396 browser_->profile())->GetGlobalErrorByMenuItemCommandID(command_id);
397 if (error)
398 return true;
400 return chrome::IsCommandEnabled(browser_, command_id);
403 bool WrenchMenuModel::IsCommandIdVisible(int command_id) const {
404 switch (command_id) {
405 #if defined(OS_WIN)
406 case IDC_VIEW_INCOMPATIBILITIES: {
407 EnumerateModulesModel* loaded_modules =
408 EnumerateModulesModel::GetInstance();
409 if (loaded_modules->confirmed_bad_modules_detected() <= 0)
410 return false;
411 // We'll leave the wrench adornment on until the user clicks the link.
412 if (loaded_modules->modules_to_notify_about() <= 0)
413 loaded_modules->AcknowledgeConflictNotification();
414 return true;
416 case IDC_PIN_TO_START_SCREEN:
417 return base::win::IsMetroProcess();
418 #else
419 case IDC_VIEW_INCOMPATIBILITIES:
420 case IDC_PIN_TO_START_SCREEN:
421 return false;
422 #endif
423 case IDC_UPGRADE_DIALOG:
424 return UpgradeDetector::GetInstance()->notify_upgrade();
425 #if !defined(OS_LINUX) || defined(USE_AURA)
426 case IDC_BOOKMARK_PAGE:
427 return !chrome::ShouldRemoveBookmarkThisPageUI(browser_->profile());
428 case IDC_BOOKMARK_ALL_TABS:
429 return !chrome::ShouldRemoveBookmarkOpenPagesUI(browser_->profile());
430 #endif
431 default:
432 return true;
436 bool WrenchMenuModel::GetAcceleratorForCommandId(
437 int command_id,
438 ui::Accelerator* accelerator) {
439 return provider_->GetAcceleratorForCommandId(command_id, accelerator);
442 void WrenchMenuModel::ActiveTabChanged(WebContents* old_contents,
443 WebContents* new_contents,
444 int index,
445 int reason) {
446 // The user has switched between tabs and the new tab may have a different
447 // zoom setting.
448 UpdateZoomControls();
451 void WrenchMenuModel::TabReplacedAt(TabStripModel* tab_strip_model,
452 WebContents* old_contents,
453 WebContents* new_contents,
454 int index) {
455 UpdateZoomControls();
458 void WrenchMenuModel::TabStripModelDeleted() {
459 // During views shutdown, the tabstrip model/browser is deleted first, while
460 // it is the opposite in gtk land.
461 tab_strip_model_->RemoveObserver(this);
462 tab_strip_model_ = NULL;
465 void WrenchMenuModel::Observe(int type,
466 const content::NotificationSource& source,
467 const content::NotificationDetails& details) {
468 DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED);
469 UpdateZoomControls();
472 // For testing.
473 WrenchMenuModel::WrenchMenuModel()
474 : ui::SimpleMenuModel(this),
475 provider_(NULL),
476 browser_(NULL),
477 tab_strip_model_(NULL) {
480 bool WrenchMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
481 if (browser_->profile()->IsManaged())
482 return false;
484 return !browser_->profile()->IsGuestSession();
487 void WrenchMenuModel::Build(bool is_new_menu) {
488 #if defined(OS_WIN)
489 AddItem(IDC_VIEW_INCOMPATIBILITIES,
490 l10n_util::GetStringUTF16(IDS_VIEW_INCOMPATIBILITIES));
491 EnumerateModulesModel* model =
492 EnumerateModulesModel::GetInstance();
493 if (model->modules_to_notify_about() > 0 ||
494 model->confirmed_bad_modules_detected() > 0)
495 AddSeparator(ui::NORMAL_SEPARATOR);
496 #endif
498 AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
499 AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
501 if (ShouldShowNewIncognitoWindowMenuItem())
502 AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
504 #if defined(OS_WIN) && !defined(NDEBUG) && defined(USE_ASH)
505 if (base::win::GetVersion() < base::win::VERSION_WIN8 &&
506 chrome::HOST_DESKTOP_TYPE_NATIVE != chrome::HOST_DESKTOP_TYPE_ASH) {
507 AddItemWithStringId(IDC_TOGGLE_ASH_DESKTOP,
508 ash::Shell::HasInstance() ? IDS_CLOSE_ASH_DESKTOP :
509 IDS_OPEN_ASH_DESKTOP);
511 #endif
513 bookmark_sub_menu_model_.reset(new BookmarkSubMenuModel(this, browser_));
514 AddSubMenuWithStringId(IDC_BOOKMARKS_MENU, IDS_BOOKMARKS_MENU,
515 bookmark_sub_menu_model_.get());
517 if (chrome::IsInstantExtendedAPIEnabled()) {
518 recent_tabs_sub_menu_model_.reset(new RecentTabsSubMenuModel(provider_,
519 browser_,
520 NULL));
521 AddSubMenuWithStringId(IDC_RECENT_TABS_MENU, IDS_RECENT_TABS_MENU,
522 recent_tabs_sub_menu_model_.get());
525 #if defined(OS_WIN)
527 #if defined(USE_AURA)
528 if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
529 content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
530 if (browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH) {
531 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
532 AddSeparator(ui::NORMAL_SEPARATOR);
533 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART, IDS_WIN8_DESKTOP_RESTART);
534 } else {
535 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
536 AddSeparator(ui::NORMAL_SEPARATOR);
537 AddItemWithStringId(IDC_WIN8_METRO_RESTART, IDS_WIN8_METRO_RESTART);
540 #else
541 if (base::win::IsMetroProcess()) {
542 // Metro mode, add the 'Relaunch Chrome in desktop mode'.
543 AddSeparator(ui::NORMAL_SEPARATOR);
544 AddItemWithStringId(IDC_WIN8_DESKTOP_RESTART, IDS_WIN8_DESKTOP_RESTART);
545 } else {
546 // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'.
547 AddSeparator(ui::NORMAL_SEPARATOR);
548 AddItemWithStringId(IDC_WIN8_METRO_RESTART, IDS_WIN8_METRO_RESTART);
550 #endif
552 #endif
554 // Append the full menu including separators. The final separator only gets
555 // appended when this is a touch menu - otherwise it would get added twice.
556 CreateCutCopyPasteMenu(is_new_menu);
558 if (!is_new_menu)
559 CreateZoomMenu(is_new_menu);
561 AddItemWithStringId(IDC_SAVE_PAGE, IDS_SAVE_PAGE);
562 AddItemWithStringId(IDC_FIND, IDS_FIND);
563 AddItemWithStringId(IDC_PRINT, IDS_PRINT);
565 tools_menu_model_.reset(new ToolsMenuModel(this, browser_));
566 // In case of touch this is the last item.
567 if (!is_new_menu) {
568 AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_TOOLS_MENU,
569 tools_menu_model_.get());
572 if (is_new_menu)
573 CreateZoomMenu(is_new_menu);
574 else
575 AddSeparator(ui::NORMAL_SEPARATOR);
577 AddItemWithStringId(IDC_SHOW_HISTORY, IDS_SHOW_HISTORY);
578 AddItemWithStringId(IDC_SHOW_DOWNLOADS, IDS_SHOW_DOWNLOADS);
579 AddSeparator(ui::NORMAL_SEPARATOR);
581 #if !defined(OS_CHROMEOS)
582 // No "Sign in to Chromium..." menu item on ChromeOS.
583 SigninManager* signin = SigninManagerFactory::GetForProfile(
584 browser_->profile()->GetOriginalProfile());
585 if (signin && signin->IsSigninAllowed()) {
586 const base::string16 short_product_name =
587 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
588 AddItem(IDC_SHOW_SYNC_SETUP, l10n_util::GetStringFUTF16(
589 IDS_SYNC_MENU_PRE_SYNCED_LABEL, short_product_name));
590 AddSeparator(ui::NORMAL_SEPARATOR);
592 #endif
594 AddItemWithStringId(IDC_OPTIONS, IDS_SETTINGS);
596 #if defined(OS_CHROMEOS)
597 if (CommandLine::ForCurrentProcess()->HasSwitch(
598 chromeos::switches::kEnableRequestTabletSite))
599 AddCheckItemWithStringId(IDC_TOGGLE_REQUEST_TABLET_SITE,
600 IDS_TOGGLE_REQUEST_TABLET_SITE);
601 #endif
603 // On ChromeOS-Touch, we don't want the about menu option.
604 #if defined(OS_CHROMEOS)
605 if (!is_new_menu)
606 #endif
608 AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
611 if (browser_defaults::kShowUpgradeMenuItem)
612 AddItem(IDC_UPGRADE_DIALOG, GetUpgradeDialogMenuItemName());
614 #if defined(OS_WIN)
615 SetIcon(GetIndexOfCommandId(IDC_VIEW_INCOMPATIBILITIES),
616 ui::ResourceBundle::GetSharedInstance().
617 GetNativeImageNamed(IDR_INPUT_ALERT_MENU));
618 #endif
620 if (!is_new_menu) {
621 AddItemWithStringId(IDC_HELP_PAGE_VIA_MENU, IDS_HELP_PAGE);
623 if (browser_defaults::kShowHelpMenuItemIcon) {
624 ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
625 SetIcon(GetIndexOfCommandId(IDC_HELP_PAGE_VIA_MENU),
626 rb.GetNativeImageNamed(IDR_HELP_MENU));
630 #if defined(GOOGLE_CHROME_BUILD)
631 #if defined(OS_CHROMEOS)
632 AddItemWithStringId(IDC_FEEDBACK, IDS_FEEDBACK);
633 #endif
634 #endif
636 AddGlobalErrorMenuItems();
638 if (is_new_menu) {
639 AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_MORE_TOOLS_MENU,
640 tools_menu_model_.get());
643 bool show_exit_menu = browser_defaults::kShowExitMenuItem;
644 #if defined(OS_WIN)
645 if (browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
646 show_exit_menu = false;
647 #endif
649 if (show_exit_menu) {
650 AddSeparator(ui::NORMAL_SEPARATOR);
651 AddItemWithStringId(IDC_EXIT, IDS_EXIT);
655 void WrenchMenuModel::AddGlobalErrorMenuItems() {
656 // TODO(sail): Currently we only build the wrench menu once per browser
657 // window. This means that if a new error is added after the menu is built
658 // it won't show in the existing wrench menu. To fix this we need to some
659 // how update the menu if new errors are added.
660 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
661 // GetSignedInServiceErrors() can modify the global error list, so call it
662 // before iterating through that list below.
663 std::vector<GlobalError*> signin_errors =
664 signin_ui_util::GetSignedInServiceErrors(
665 browser_->profile()->GetOriginalProfile());
666 const GlobalErrorService::GlobalErrorList& errors =
667 GlobalErrorServiceFactory::GetForProfile(browser_->profile())->errors();
668 for (GlobalErrorService::GlobalErrorList::const_iterator
669 it = errors.begin(); it != errors.end(); ++it) {
670 GlobalError* error = *it;
671 DCHECK(error);
672 if (error->HasMenuItem()) {
673 #if !defined(OS_CHROMEOS)
674 // Don't add a signin error if it's already being displayed elsewhere.
675 if (std::find(signin_errors.begin(), signin_errors.end(), error) !=
676 signin_errors.end()) {
677 MenuModel* model = this;
678 int index = 0;
679 if (MenuModel::GetModelAndIndexForCommandId(
680 IDC_SHOW_SIGNIN, &model, &index)) {
681 continue;
684 #endif
686 AddItem(error->MenuItemCommandID(), error->MenuItemLabel());
687 int icon_id = error->MenuItemIconResourceID();
688 if (icon_id) {
689 const gfx::Image& image = rb.GetNativeImageNamed(icon_id);
690 SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()),
691 image);
697 void WrenchMenuModel::CreateCutCopyPasteMenu(bool new_menu) {
698 AddSeparator(new_menu ? ui::LOWER_SEPARATOR : ui::NORMAL_SEPARATOR);
700 #if defined(OS_POSIX) && !defined(TOOLKIT_VIEWS)
701 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
702 // layout for this menu item in Toolbar.xib. It does, however, use the
703 // command_id value from AddButtonItem() to identify this special item.
704 edit_menu_item_model_.reset(new ui::ButtonMenuItemModel(IDS_EDIT, this));
705 edit_menu_item_model_->AddGroupItemWithStringId(IDC_CUT, IDS_CUT);
706 edit_menu_item_model_->AddGroupItemWithStringId(IDC_COPY, IDS_COPY);
707 edit_menu_item_model_->AddGroupItemWithStringId(IDC_PASTE, IDS_PASTE);
708 AddButtonItem(IDC_EDIT_MENU, edit_menu_item_model_.get());
709 #else
710 // WARNING: views/wrench_menu assumes these items are added in this order. If
711 // you change the order you'll need to update wrench_menu as well.
712 AddItemWithStringId(IDC_CUT, IDS_CUT);
713 AddItemWithStringId(IDC_COPY, IDS_COPY);
714 AddItemWithStringId(IDC_PASTE, IDS_PASTE);
715 #endif
717 if (new_menu)
718 AddSeparator(ui::UPPER_SEPARATOR);
721 void WrenchMenuModel::CreateZoomMenu(bool new_menu) {
722 // This menu needs to be enclosed by separators.
723 AddSeparator(new_menu ? ui::LOWER_SEPARATOR : ui::NORMAL_SEPARATOR);
725 #if defined(OS_POSIX) && !defined(TOOLKIT_VIEWS)
726 // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
727 // layout for this menu item in Toolbar.xib. It does, however, use the
728 // command_id value from AddButtonItem() to identify this special item.
729 zoom_menu_item_model_.reset(
730 new ui::ButtonMenuItemModel(IDS_ZOOM_MENU, this));
731 zoom_menu_item_model_->AddGroupItemWithStringId(
732 IDC_ZOOM_MINUS, IDS_ZOOM_MINUS2);
733 zoom_menu_item_model_->AddButtonLabel(IDC_ZOOM_PERCENT_DISPLAY,
734 IDS_ZOOM_PLUS2);
735 zoom_menu_item_model_->AddGroupItemWithStringId(
736 IDC_ZOOM_PLUS, IDS_ZOOM_PLUS2);
737 zoom_menu_item_model_->AddSpace();
738 zoom_menu_item_model_->AddItemWithImage(
739 IDC_FULLSCREEN, IDR_FULLSCREEN_MENU_BUTTON);
740 AddButtonItem(IDC_ZOOM_MENU, zoom_menu_item_model_.get());
741 #else
742 // WARNING: views/wrench_menu assumes these items are added in this order. If
743 // you change the order you'll need to update wrench_menu as well.
744 AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS);
745 AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS);
746 AddItemWithStringId(IDC_FULLSCREEN, IDS_FULLSCREEN);
747 #endif
749 AddSeparator(new_menu ? ui::UPPER_SEPARATOR : ui::NORMAL_SEPARATOR);
752 void WrenchMenuModel::UpdateZoomControls() {
753 bool enable_increment = false;
754 bool enable_decrement = false;
755 int zoom_percent = 100;
756 if (browser_->tab_strip_model()->GetActiveWebContents()) {
757 zoom_percent =
758 browser_->tab_strip_model()->GetActiveWebContents()->GetZoomPercent(
759 &enable_increment, &enable_decrement);
761 zoom_label_ = l10n_util::GetStringFUTF16(
762 IDS_ZOOM_PERCENT, base::IntToString16(zoom_percent));
765 void WrenchMenuModel::OnZoomLevelChanged(
766 const content::HostZoomMap::ZoomLevelChange& change) {
767 UpdateZoomControls();