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/ash/launcher/launcher_context_menu.h"
9 #include "ash/desktop_background/user_wallpaper_delegate.h"
10 #include "ash/metrics/user_metrics_recorder.h"
11 #include "ash/root_window_controller.h"
12 #include "ash/shelf/shelf_item_delegate.h"
13 #include "ash/shelf/shelf_widget.h"
14 #include "ash/shell.h"
15 #include "base/bind.h"
16 #include "base/prefs/pref_service.h"
17 #include "chrome/browser/extensions/context_menu_matcher.h"
18 #include "chrome/browser/extensions/extension_util.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/extensions/extension_constants.h"
25 #include "chrome/grit/generated_resources.h"
26 #include "content/public/common/context_menu_params.h"
27 #include "grit/ash_strings.h"
28 #include "ui/base/l10n/l10n_util.h"
32 bool MenuItemHasLauncherContext(const extensions::MenuItem* item) {
33 return item->contexts().Contains(extensions::MenuItem::LAUNCHER);
38 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
39 const ash::ShelfItem* item,
41 : ui::SimpleMenuModel(NULL),
42 controller_(controller),
44 shelf_alignment_menu_(root),
46 item_delegate_(NULL) {
52 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
53 ash::ShelfItemDelegate* item_delegate,
56 : ui::SimpleMenuModel(NULL),
57 controller_(controller),
59 shelf_alignment_menu_(root),
61 item_delegate_(item_delegate) {
67 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
69 : ui::SimpleMenuModel(NULL),
70 controller_(controller),
71 item_(ash::ShelfItem()),
72 shelf_alignment_menu_(root),
73 extension_items_(new extensions::ContextMenuMatcher(
74 controller->profile(), this, this,
75 base::Bind(MenuItemHasLauncherContext))),
77 item_delegate_(NULL) {
82 void LauncherContextMenu::Init() {
83 extension_items_.reset(new extensions::ContextMenuMatcher(
84 controller_->profile(), this, this,
85 base::Bind(MenuItemHasLauncherContext)));
88 if (is_valid_item()) {
89 if (item_.type == ash::TYPE_APP_SHORTCUT ||
90 item_.type == ash::TYPE_WINDOWED_APP) {
91 // V1 apps can be started from the menu - but V2 apps should not.
92 if (!controller_->IsPlatformApp(item_.id)) {
93 AddItem(MENU_OPEN_NEW, base::string16());
94 AddSeparator(ui::NORMAL_SEPARATOR);
98 l10n_util::GetStringUTF16(controller_->IsPinned(item_.id) ?
99 IDS_LAUNCHER_CONTEXT_MENU_UNPIN :
100 IDS_LAUNCHER_CONTEXT_MENU_PIN));
101 if (controller_->IsOpen(item_.id)) {
103 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
105 if (!controller_->IsPlatformApp(item_.id) &&
106 item_.type != ash::TYPE_WINDOWED_APP) {
107 AddSeparator(ui::NORMAL_SEPARATOR);
108 if (extensions::util::IsStreamlinedHostedAppsEnabled()) {
109 // Streamlined hosted apps launch in a window by default. This menu
110 // item is re-interpreted as a single, toggle-able option to launch
111 // the hosted app as a tab.
112 AddCheckItemWithStringId(
113 LAUNCH_TYPE_REGULAR_TAB,
114 IDS_APP_CONTEXT_MENU_OPEN_TAB);
116 AddCheckItemWithStringId(
117 LAUNCH_TYPE_REGULAR_TAB,
118 IDS_APP_CONTEXT_MENU_OPEN_REGULAR);
119 AddCheckItemWithStringId(
120 LAUNCH_TYPE_PINNED_TAB,
121 IDS_APP_CONTEXT_MENU_OPEN_PINNED);
122 AddCheckItemWithStringId(
124 IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
125 // Even though the launch type is Full Screen it is more accurately
126 // described as Maximized in Ash.
127 AddCheckItemWithStringId(
128 LAUNCH_TYPE_FULLSCREEN,
129 IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
132 } else if (item_.type == ash::TYPE_BROWSER_SHORTCUT) {
133 AddItem(MENU_NEW_WINDOW,
134 l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_WINDOW));
135 if (!controller_->IsLoggedInAsGuest()) {
136 AddItem(MENU_NEW_INCOGNITO_WINDOW,
137 l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_INCOGNITO_WINDOW));
139 } else if (item_.type == ash::TYPE_DIALOG) {
141 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
143 if (item_.type == ash::TYPE_PLATFORM_APP) {
146 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_PIN));
147 AddItem(MENU_INSTALL, l10n_util::GetStringUTF16(IDS_APP_INSTALL_TITLE));
149 if (controller_->IsOpen(item_.id)) {
151 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
154 AddSeparator(ui::NORMAL_SEPARATOR);
155 if (item_.type == ash::TYPE_APP_SHORTCUT ||
156 item_.type == ash::TYPE_WINDOWED_APP ||
157 item_.type == ash::TYPE_PLATFORM_APP) {
158 const extensions::MenuItem::ExtensionKey app_key(
159 controller_->GetAppIDForShelfID(item_.id));
160 if (!app_key.empty()) {
162 extension_items_->AppendExtensionItems(app_key,
165 false); // is_action_menu
166 AddSeparator(ui::NORMAL_SEPARATOR);
170 // In fullscreen, the launcher is either hidden or autohidden depending on
171 // the type of fullscreen. Do not show the auto-hide menu item while in
172 // fullscreen because it is confusing when the preference appears not to
174 if (!IsFullScreenMode() &&
175 controller_->CanUserModifyShelfAutoHideBehavior(root_window_)) {
176 AddCheckItemWithStringId(MENU_AUTO_HIDE,
177 IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE);
179 if (ash::ShelfWidget::ShelfAlignmentAllowed()) {
180 AddSubMenuWithStringId(MENU_ALIGNMENT_MENU,
181 IDS_ASH_SHELF_CONTEXT_MENU_POSITION,
182 &shelf_alignment_menu_);
184 #if defined(OS_CHROMEOS)
185 AddItem(MENU_CHANGE_WALLPAPER,
186 l10n_util::GetStringUTF16(IDS_AURA_SET_DESKTOP_WALLPAPER));
190 LauncherContextMenu::~LauncherContextMenu() {
193 bool LauncherContextMenu::IsItemForCommandIdDynamic(int command_id) const {
194 return command_id == MENU_OPEN_NEW;
197 base::string16 LauncherContextMenu::GetLabelForCommandId(int command_id) const {
198 if (command_id == MENU_OPEN_NEW) {
199 if (item_.type == ash::TYPE_PLATFORM_APP) {
200 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW);
202 switch (controller_->GetLaunchType(item_.id)) {
203 case extensions::LAUNCH_TYPE_PINNED:
204 case extensions::LAUNCH_TYPE_REGULAR:
205 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_TAB);
206 case extensions::LAUNCH_TYPE_FULLSCREEN:
207 case extensions::LAUNCH_TYPE_WINDOW:
208 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW);
211 return base::string16();
215 return base::string16();
218 bool LauncherContextMenu::IsCommandIdChecked(int command_id) const {
219 switch (command_id) {
220 case LAUNCH_TYPE_PINNED_TAB:
221 return controller_->GetLaunchType(item_.id) ==
222 extensions::LAUNCH_TYPE_PINNED;
223 case LAUNCH_TYPE_REGULAR_TAB:
224 return controller_->GetLaunchType(item_.id) ==
225 extensions::LAUNCH_TYPE_REGULAR;
226 case LAUNCH_TYPE_WINDOW:
227 return controller_->GetLaunchType(item_.id) ==
228 extensions::LAUNCH_TYPE_WINDOW;
229 case LAUNCH_TYPE_FULLSCREEN:
230 return controller_->GetLaunchType(item_.id) ==
231 extensions::LAUNCH_TYPE_FULLSCREEN;
233 return controller_->GetShelfAutoHideBehavior(root_window_) ==
234 ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
236 return extension_items_->IsCommandIdChecked(command_id);
240 bool LauncherContextMenu::IsCommandIdEnabled(int command_id) const {
241 switch (command_id) {
243 return controller_->IsPinnable(item_.id);
244 #if defined(OS_CHROMEOS)
245 case MENU_CHANGE_WALLPAPER:
246 return ash::Shell::GetInstance()->user_wallpaper_delegate()->
247 CanOpenSetWallpaperPage();
249 case MENU_NEW_WINDOW:
250 // "Normal" windows are not allowed when incognito is enforced.
251 return IncognitoModePrefs::GetAvailability(
252 controller_->profile()->GetPrefs()) != IncognitoModePrefs::FORCED;
254 return controller_->CanUserModifyShelfAutoHideBehavior(root_window_);
255 case MENU_NEW_INCOGNITO_WINDOW:
256 // Incognito windows are not allowed when incognito is disabled.
257 return IncognitoModePrefs::GetAvailability(
258 controller_->profile()->GetPrefs()) != IncognitoModePrefs::DISABLED;
260 return extension_items_->IsCommandIdEnabled(command_id);
264 bool LauncherContextMenu::IsCommandIdVisible(int command_id) const {
265 if (item_.type != ash::TYPE_PLATFORM_APP)
268 switch (command_id) {
270 return !controller_->CanInstall(item_.id);
272 return controller_->CanInstall(item_.id);
278 bool LauncherContextMenu::GetAcceleratorForCommandId(
280 ui::Accelerator* accelerator) {
284 void LauncherContextMenu::ExecuteCommand(int command_id, int event_flags) {
285 switch (static_cast<MenuItem>(command_id)) {
287 controller_->Launch(item_.id, ui::EF_NONE);
290 if (item_.type == ash::TYPE_DIALOG) {
291 DCHECK(item_delegate_);
292 item_delegate_->Close();
294 // TODO(simonhong): Use ShelfItemDelegate::Close().
295 controller_->Close(item_.id);
297 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(
298 ash::UMA_CLOSE_THROUGH_CONTEXT_MENU);
301 controller_->TogglePinned(item_.id);
304 controller_->Install(item_.id);
306 case LAUNCH_TYPE_PINNED_TAB:
307 controller_->SetLaunchType(item_.id, extensions::LAUNCH_TYPE_PINNED);
309 case LAUNCH_TYPE_REGULAR_TAB: {
310 extensions::LaunchType launch_type =
311 extensions::LAUNCH_TYPE_REGULAR;
312 // Streamlined hosted apps can only toggle between LAUNCH_WINDOW and
314 if (extensions::util::IsStreamlinedHostedAppsEnabled()) {
315 launch_type = controller_->GetLaunchType(item_.id) ==
316 extensions::LAUNCH_TYPE_REGULAR
317 ? extensions::LAUNCH_TYPE_WINDOW
318 : extensions::LAUNCH_TYPE_REGULAR;
320 controller_->SetLaunchType(item_.id, launch_type);
323 case LAUNCH_TYPE_WINDOW:
324 controller_->SetLaunchType(item_.id, extensions::LAUNCH_TYPE_WINDOW);
326 case LAUNCH_TYPE_FULLSCREEN:
327 controller_->SetLaunchType(item_.id, extensions::LAUNCH_TYPE_FULLSCREEN);
330 controller_->ToggleShelfAutoHideBehavior(root_window_);
332 case MENU_NEW_WINDOW:
333 controller_->CreateNewWindow();
335 case MENU_NEW_INCOGNITO_WINDOW:
336 controller_->CreateNewIncognitoWindow();
338 case MENU_ALIGNMENT_MENU:
340 #if defined(OS_CHROMEOS)
341 case MENU_CHANGE_WALLPAPER:
342 ash::Shell::GetInstance()->user_wallpaper_delegate()->
343 OpenSetWallpaperPage();
347 extension_items_->ExecuteCommand(command_id, NULL,
348 content::ContextMenuParams());