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. 4 5 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h" 6 7 #include <string> 8 9 #include "ash/desktop_background/user_wallpaper_delegate.h" 10 #include "ash/root_window_controller.h" 11 #include "ash/shell.h" 12 #include "ash/shell_delegate.h" 13 #include "ash/wm/property_util.h" 14 #include "base/bind.h" 15 #include "base/command_line.h" 16 #include "base/prefs/pref_service.h" 17 #include "chrome/browser/extensions/context_menu_matcher.h" 18 #include "chrome/browser/extensions/extension_prefs.h" 19 #include "chrome/browser/fullscreen.h" 20 #include "chrome/browser/prefs/incognito_mode_prefs.h" 21 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/ui/ash/chrome_shell_delegate.h" 23 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" 24 #include "chrome/common/chrome_switches.h" 25 #include "content/public/common/context_menu_params.h" 26 #include "grit/ash_strings.h" 27 #include "grit/generated_resources.h" 28 #include "ui/base/l10n/l10n_util.h" 29 30 namespace { 31 32 bool MenuItemHasLauncherContext(const extensions::MenuItem* item) { 33 return item->contexts().Contains(extensions::MenuItem::LAUNCHER); 34 } 35 36 } // namespace 37 38 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller, 39 const ash::LauncherItem* item, 40 aura::RootWindow* root) 41 : ui::SimpleMenuModel(NULL), 42 controller_(controller), 43 item_(*item), 44 launcher_alignment_menu_(root), 45 root_window_(root) { 46 DCHECK(item); 47 DCHECK(root_window_); 48 Init(); 49 } 50 51 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller, 52 aura::RootWindow* root) 53 : ui::SimpleMenuModel(NULL), 54 controller_(controller), 55 item_(ash::LauncherItem()), 56 launcher_alignment_menu_(root), 57 extension_items_(new extensions::ContextMenuMatcher( 58 controller->profile(), this, this, 59 base::Bind(MenuItemHasLauncherContext))), 60 root_window_(root) { 61 DCHECK(root_window_); 62 Init(); 63 } 64 65 void LauncherContextMenu::Init() { 66 extension_items_.reset(new extensions::ContextMenuMatcher( 67 controller_->profile(), this, this, 68 base::Bind(MenuItemHasLauncherContext))); 69 set_delegate(this); 70 71 if (is_valid_item()) { 72 if (item_.type == ash::TYPE_APP_SHORTCUT || 73 item_.type == ash::TYPE_WINDOWED_APP) { 74 // V1 apps can be started from the menu - but V2 apps should not. 75 if (!controller_->IsPlatformApp(item_.id)) { 76 AddItem(MENU_OPEN_NEW, string16()); 77 AddSeparator(ui::NORMAL_SEPARATOR); 78 } 79 AddItem( 80 MENU_PIN, 81 l10n_util::GetStringUTF16(controller_->IsPinned(item_.id) ? 82 IDS_LAUNCHER_CONTEXT_MENU_UNPIN : 83 IDS_LAUNCHER_CONTEXT_MENU_PIN)); 84 if (controller_->IsOpen(item_.id)) { 85 AddItem(MENU_CLOSE, 86 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE)); 87 } 88 if (!controller_->IsPlatformApp(item_.id) && 89 item_.type != ash::TYPE_WINDOWED_APP) { 90 AddSeparator(ui::NORMAL_SEPARATOR); 91 AddCheckItemWithStringId( 92 LAUNCH_TYPE_REGULAR_TAB, 93 IDS_APP_CONTEXT_MENU_OPEN_REGULAR); 94 AddCheckItemWithStringId( 95 LAUNCH_TYPE_PINNED_TAB, 96 IDS_APP_CONTEXT_MENU_OPEN_PINNED); 97 if (!ash::Shell::IsForcedMaximizeMode()) { 98 AddCheckItemWithStringId( 99 LAUNCH_TYPE_WINDOW, 100 IDS_APP_CONTEXT_MENU_OPEN_WINDOW); 101 // Even though the launch type is Full Screen it is more accurately 102 // described as Maximized in Ash. 103 AddCheckItemWithStringId( 104 LAUNCH_TYPE_FULLSCREEN, 105 IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED); 106 } 107 } 108 } else if (item_.type == ash::TYPE_BROWSER_SHORTCUT) { 109 AddItem(MENU_NEW_WINDOW, 110 l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_WINDOW)); 111 if (!controller_->IsLoggedInAsGuest()) { 112 AddItem(MENU_NEW_INCOGNITO_WINDOW, 113 l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_INCOGNITO_WINDOW)); 114 } 115 } else { 116 if (item_.type == ash::TYPE_PLATFORM_APP) { 117 AddItem( 118 MENU_PIN, 119 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_PIN)); 120 } 121 if (controller_->IsOpen(item_.id)) { 122 AddItem(MENU_CLOSE, 123 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE)); 124 } 125 } 126 AddSeparator(ui::NORMAL_SEPARATOR); 127 if (item_.type == ash::TYPE_APP_SHORTCUT || 128 item_.type == ash::TYPE_WINDOWED_APP || 129 item_.type == ash::TYPE_PLATFORM_APP) { 130 std::string app_id = controller_->GetAppIDForLauncherID(item_.id); 131 if (!app_id.empty()) { 132 int index = 0; 133 extension_items_->AppendExtensionItems( 134 app_id, string16(), &index); 135 AddSeparator(ui::NORMAL_SEPARATOR); 136 } 137 } 138 } 139 // In fullscreen, the launcher is either hidden or autohidden depending on 140 // the type of fullscreen. Do not show the auto-hide menu item while in 141 // fullscreen because it is confusing when the preference appears not to 142 // apply. 143 if (!IsFullScreenMode()) { 144 AddCheckItemWithStringId(MENU_AUTO_HIDE, 145 IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE); 146 } 147 if (CommandLine::ForCurrentProcess()->HasSwitch( 148 switches::kShowShelfAlignmentMenu)) { 149 AddSubMenuWithStringId(MENU_ALIGNMENT_MENU, 150 IDS_ASH_SHELF_CONTEXT_MENU_POSITION, 151 &launcher_alignment_menu_); 152 } 153 #if defined(OS_CHROMEOS) 154 AddItem(MENU_CHANGE_WALLPAPER, 155 l10n_util::GetStringUTF16(IDS_AURA_SET_DESKTOP_WALLPAPER)); 156 #endif 157 } 158 159 LauncherContextMenu::~LauncherContextMenu() { 160 } 161 162 bool LauncherContextMenu::IsItemForCommandIdDynamic(int command_id) const { 163 return command_id == MENU_OPEN_NEW; 164 } 165 166 string16 LauncherContextMenu::GetLabelForCommandId(int command_id) const { 167 if (command_id == MENU_OPEN_NEW) { 168 if (item_.type == ash::TYPE_PLATFORM_APP) { 169 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW); 170 } 171 switch (controller_->GetLaunchType(item_.id)) { 172 case extensions::ExtensionPrefs::LAUNCH_PINNED: 173 case extensions::ExtensionPrefs::LAUNCH_REGULAR: 174 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_TAB); 175 case extensions::ExtensionPrefs::LAUNCH_FULLSCREEN: 176 case extensions::ExtensionPrefs::LAUNCH_WINDOW: 177 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW); 178 } 179 } 180 NOTREACHED(); 181 return string16(); 182 } 183 184 bool LauncherContextMenu::IsCommandIdChecked(int command_id) const { 185 switch (command_id) { 186 case LAUNCH_TYPE_PINNED_TAB: 187 return controller_->GetLaunchType(item_.id) == 188 extensions::ExtensionPrefs::LAUNCH_PINNED; 189 case LAUNCH_TYPE_REGULAR_TAB: 190 return controller_->GetLaunchType(item_.id) == 191 extensions::ExtensionPrefs::LAUNCH_REGULAR; 192 case LAUNCH_TYPE_WINDOW: 193 return controller_->GetLaunchType(item_.id) == 194 extensions::ExtensionPrefs::LAUNCH_WINDOW; 195 case LAUNCH_TYPE_FULLSCREEN: 196 return controller_->GetLaunchType(item_.id) == 197 extensions::ExtensionPrefs::LAUNCH_FULLSCREEN; 198 case MENU_AUTO_HIDE: 199 return controller_->GetShelfAutoHideBehavior(root_window_) == 200 ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; 201 default: 202 return extension_items_->IsCommandIdChecked(command_id); 203 } 204 } 205 206 bool LauncherContextMenu::IsCommandIdEnabled(int command_id) const { 207 switch (command_id) { 208 case MENU_PIN: 209 return item_.type == ash::TYPE_PLATFORM_APP || 210 controller_->IsPinnable(item_.id); 211 #if defined(OS_CHROMEOS) 212 case MENU_CHANGE_WALLPAPER: 213 return ash::Shell::GetInstance()->user_wallpaper_delegate()-> 214 CanOpenSetWallpaperPage(); 215 #endif 216 case MENU_NEW_WINDOW: 217 // "Normal" windows are not allowed when incognito is enforced. 218 return IncognitoModePrefs::GetAvailability( 219 controller_->profile()->GetPrefs()) != IncognitoModePrefs::FORCED; 220 case MENU_AUTO_HIDE: 221 return controller_->CanUserModifyShelfAutoHideBehavior(root_window_); 222 case MENU_NEW_INCOGNITO_WINDOW: 223 // Incognito windows are not allowed when incognito is disabled. 224 return IncognitoModePrefs::GetAvailability( 225 controller_->profile()->GetPrefs()) != IncognitoModePrefs::DISABLED; 226 default: 227 return extension_items_->IsCommandIdEnabled(command_id); 228 } 229 } 230 231 bool LauncherContextMenu::GetAcceleratorForCommandId( 232 int command_id, 233 ui::Accelerator* accelerator) { 234 return false; 235 } 236 237 void LauncherContextMenu::ExecuteCommand(int command_id, int event_flags) { 238 switch (static_cast<MenuItem>(command_id)) { 239 case MENU_OPEN_NEW: 240 controller_->Launch(item_.id, ui::EF_NONE); 241 break; 242 case MENU_CLOSE: 243 controller_->Close(item_.id); 244 ChromeShellDelegate::instance()->RecordUserMetricsAction( 245 ash::UMA_CLOSE_THROUGH_CONTEXT_MENU); 246 break; 247 case MENU_PIN: 248 controller_->TogglePinned(item_.id); 249 break; 250 case LAUNCH_TYPE_PINNED_TAB: 251 controller_->SetLaunchType(item_.id, 252 extensions::ExtensionPrefs::LAUNCH_PINNED); 253 break; 254 case LAUNCH_TYPE_REGULAR_TAB: 255 controller_->SetLaunchType(item_.id, 256 extensions::ExtensionPrefs::LAUNCH_REGULAR); 257 break; 258 case LAUNCH_TYPE_WINDOW: 259 controller_->SetLaunchType(item_.id, 260 extensions::ExtensionPrefs::LAUNCH_WINDOW); 261 break; 262 case LAUNCH_TYPE_FULLSCREEN: 263 controller_->SetLaunchType(item_.id, 264 extensions::ExtensionPrefs::LAUNCH_FULLSCREEN); 265 break; 266 case MENU_AUTO_HIDE: 267 controller_->ToggleShelfAutoHideBehavior(root_window_); 268 break; 269 case MENU_NEW_WINDOW: 270 controller_->CreateNewWindow(); 271 break; 272 case MENU_NEW_INCOGNITO_WINDOW: 273 controller_->CreateNewIncognitoWindow(); 274 break; 275 case MENU_ALIGNMENT_MENU: 276 break; 277 #if defined(OS_CHROMEOS) 278 case MENU_CHANGE_WALLPAPER: 279 ash::Shell::GetInstance()->user_wallpaper_delegate()-> 280 OpenSetWallpaperPage(); 281 break; 282 #endif 283 default: 284 extension_items_->ExecuteCommand(command_id, NULL, 285 content::ContextMenuParams()); 286 } 287 } 288