1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/views/frame/system_menu_model_builder.h" 6 7 #include "base/command_line.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/app/chrome_command_ids.h" 10 #include "chrome/browser/ui/browser_commands.h" 11 #include "chrome/browser/ui/host_desktop.h" 12 #include "chrome/browser/ui/toolbar/wrench_menu_model.h" 13 #include "chrome/common/chrome_switches.h" 14 #include "grit/generated_resources.h" 15 #include "ui/base/accelerators/accelerator.h" 16 #include "ui/base/models/simple_menu_model.h" 17 18 #if defined(OS_CHROMEOS) 19 #include "ash/session/session_state_delegate.h" 20 #include "ash/session/user_info.h" 21 #include "ash/shell.h" 22 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" 23 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" 24 #include "chrome/browser/ui/browser_window.h" 25 #include "ui/base/l10n/l10n_util.h" 26 #endif 27 28 SystemMenuModelBuilder::SystemMenuModelBuilder( 29 ui::AcceleratorProvider* provider, 30 Browser* browser) 31 : menu_delegate_(provider, browser) { 32 } 33 34 SystemMenuModelBuilder::~SystemMenuModelBuilder() { 35 } 36 37 void SystemMenuModelBuilder::Init() { 38 ui::SimpleMenuModel* model = new ui::SimpleMenuModel(&menu_delegate_); 39 menu_model_.reset(model); 40 BuildMenu(model); 41 #if defined(OS_WIN) 42 // On Windows with HOST_DESKTOP_TYPE_NATIVE we put the menu items in the 43 // system menu (not at the end). Doing this necessitates adding a trailing 44 // separator. 45 if (browser()->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE) 46 model->AddSeparator(ui::NORMAL_SEPARATOR); 47 #endif 48 } 49 50 void SystemMenuModelBuilder::BuildMenu(ui::SimpleMenuModel* model) { 51 // We add the menu items in reverse order so that insertion_index never needs 52 // to change. 53 if (browser()->is_type_tabbed()) 54 BuildSystemMenuForBrowserWindow(model); 55 else 56 BuildSystemMenuForAppOrPopupWindow(model); 57 AddFrameToggleItems(model); 58 } 59 60 void SystemMenuModelBuilder::BuildSystemMenuForBrowserWindow( 61 ui::SimpleMenuModel* model) { 62 model->AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB); 63 model->AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB); 64 if (chrome::CanOpenTaskManager()) { 65 model->AddSeparator(ui::NORMAL_SEPARATOR); 66 model->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER); 67 } 68 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 69 model->AddSeparator(ui::NORMAL_SEPARATOR); 70 model->AddCheckItemWithStringId(IDC_USE_SYSTEM_TITLE_BAR, 71 IDS_SHOW_WINDOW_DECORATIONS_MENU); 72 #endif 73 AppendTeleportMenu(model); 74 // If it's a regular browser window with tabs, we don't add any more items, 75 // since it already has menus (Page, Chrome). 76 } 77 78 void SystemMenuModelBuilder::BuildSystemMenuForAppOrPopupWindow( 79 ui::SimpleMenuModel* model) { 80 model->AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK); 81 model->AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD); 82 model->AddItemWithStringId(IDC_RELOAD, IDS_APP_MENU_RELOAD); 83 model->AddSeparator(ui::NORMAL_SEPARATOR); 84 if (browser()->is_app()) 85 model->AddItemWithStringId(IDC_NEW_TAB, IDS_APP_MENU_NEW_WEB_PAGE); 86 else 87 model->AddItemWithStringId(IDC_SHOW_AS_TAB, IDS_SHOW_AS_TAB); 88 model->AddSeparator(ui::NORMAL_SEPARATOR); 89 model->AddItemWithStringId(IDC_CUT, IDS_CUT); 90 model->AddItemWithStringId(IDC_COPY, IDS_COPY); 91 model->AddItemWithStringId(IDC_PASTE, IDS_PASTE); 92 model->AddSeparator(ui::NORMAL_SEPARATOR); 93 model->AddItemWithStringId(IDC_FIND, IDS_FIND); 94 model->AddItemWithStringId(IDC_PRINT, IDS_PRINT); 95 zoom_menu_contents_.reset(new ZoomMenuModel(&menu_delegate_)); 96 model->AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_ZOOM_MENU, 97 zoom_menu_contents_.get()); 98 encoding_menu_contents_.reset(new EncodingMenuModel(browser())); 99 model->AddSubMenuWithStringId(IDC_ENCODING_MENU, 100 IDS_ENCODING_MENU, 101 encoding_menu_contents_.get()); 102 if (browser()->is_app() && chrome::CanOpenTaskManager()) { 103 model->AddSeparator(ui::NORMAL_SEPARATOR); 104 model->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER); 105 } 106 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 107 model->AddSeparator(ui::NORMAL_SEPARATOR); 108 model->AddItemWithStringId(IDC_CLOSE_WINDOW, IDS_CLOSE); 109 #endif 110 111 AppendTeleportMenu(model); 112 } 113 114 void SystemMenuModelBuilder::AddFrameToggleItems(ui::SimpleMenuModel* model) { 115 if (CommandLine::ForCurrentProcess()->HasSwitch( 116 switches::kDebugEnableFrameToggle)) { 117 model->AddSeparator(ui::NORMAL_SEPARATOR); 118 model->AddItem(IDC_DEBUG_FRAME_TOGGLE, 119 base::ASCIIToUTF16("Toggle Frame Type")); 120 } 121 } 122 123 void SystemMenuModelBuilder::AppendTeleportMenu(ui::SimpleMenuModel* model) { 124 #if defined(OS_CHROMEOS) 125 DCHECK(browser()->window()); 126 // If there is no manager, we are not in the proper multi user mode. 127 if (chrome::MultiUserWindowManager::GetMultiProfileMode() != 128 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) 129 return; 130 131 // Don't show the menu for incognito windows. 132 if (browser()->profile()->IsOffTheRecord()) 133 return; 134 135 // To show the menu we need at least two logged in users. 136 ash::SessionStateDelegate* delegate = 137 ash::Shell::GetInstance()->session_state_delegate(); 138 int logged_in_users = delegate->NumberOfLoggedInUsers(); 139 if (logged_in_users <= 1) 140 return; 141 142 // If this does not belong to a profile or there is no window, or the window 143 // is not owned by anyone, we don't show the menu addition. 144 chrome::MultiUserWindowManager* manager = 145 chrome::MultiUserWindowManager::GetInstance(); 146 const std::string user_id = 147 multi_user_util::GetUserIDFromProfile(browser()->profile()); 148 aura::Window* window = browser()->window()->GetNativeWindow(); 149 if (user_id.empty() || !window || manager->GetWindowOwner(window).empty()) 150 return; 151 152 model->AddSeparator(ui::NORMAL_SEPARATOR); 153 DCHECK(logged_in_users <= 3); 154 for (int user_index = 1; user_index < logged_in_users; ++user_index) { 155 const ash::UserInfo* user_info = delegate->GetUserInfo(user_index); 156 model->AddItem( 157 user_index == 1 ? IDC_VISIT_DESKTOP_OF_LRU_USER_2 158 : IDC_VISIT_DESKTOP_OF_LRU_USER_3, 159 l10n_util::GetStringFUTF16(IDS_VISIT_DESKTOP_OF_LRU_USER, 160 user_info->GetDisplayName(), 161 base::ASCIIToUTF16(user_info->GetEmail()))); 162 } 163 #endif 164 } 165