1 // Copyright 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/session/session_state_delegate.h"
13 #include "ash/shelf/shelf_item_delegate.h"
14 #include "ash/shelf/shelf_widget.h"
15 #include "ash/shell.h"
16 #include "base/bind.h"
17 #include "base/prefs/pref_service.h"
18 #include "chrome/browser/extensions/context_menu_matcher.h"
19 #include "chrome/browser/extensions/extension_util.h"
20 #include "chrome/browser/fullscreen.h"
21 #include "chrome/browser/prefs/incognito_mode_prefs.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
24 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
25 #include "chrome/common/extensions/extension_constants.h"
26 #include "chrome/grit/generated_resources.h"
27 #include "content/public/common/context_menu_params.h"
28 #include "grit/ash_strings.h"
29 #include "ui/base/l10n/l10n_util.h"
33 bool MenuItemHasLauncherContext(const extensions::MenuItem
* item
) {
34 return item
->contexts().Contains(extensions::MenuItem::LAUNCHER
);
39 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController
* controller
,
40 const ash::ShelfItem
* item
,
42 : ui::SimpleMenuModel(NULL
),
43 controller_(controller
),
45 shelf_alignment_menu_(root
),
47 item_delegate_(NULL
) {
53 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController
* controller
,
54 ash::ShelfItemDelegate
* item_delegate
,
57 : ui::SimpleMenuModel(NULL
),
58 controller_(controller
),
60 shelf_alignment_menu_(root
),
62 item_delegate_(item_delegate
) {
68 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController
* controller
,
70 : ui::SimpleMenuModel(NULL
),
71 controller_(controller
),
72 item_(ash::ShelfItem()),
73 shelf_alignment_menu_(root
),
74 extension_items_(new extensions::ContextMenuMatcher(
75 controller
->profile(), this, this,
76 base::Bind(MenuItemHasLauncherContext
))),
78 item_delegate_(NULL
) {
83 void LauncherContextMenu::Init() {
84 extension_items_
.reset(new extensions::ContextMenuMatcher(
85 controller_
->profile(), this, this,
86 base::Bind(MenuItemHasLauncherContext
)));
89 if (is_valid_item()) {
90 if (item_
.type
== ash::TYPE_APP_SHORTCUT
||
91 item_
.type
== ash::TYPE_WINDOWED_APP
) {
92 // V1 apps can be started from the menu - but V2 apps should not.
93 if (!controller_
->IsPlatformApp(item_
.id
)) {
94 AddItem(MENU_OPEN_NEW
, base::string16());
95 AddSeparator(ui::NORMAL_SEPARATOR
);
99 l10n_util::GetStringUTF16(controller_
->IsPinned(item_
.id
) ?
100 IDS_LAUNCHER_CONTEXT_MENU_UNPIN
:
101 IDS_LAUNCHER_CONTEXT_MENU_PIN
));
102 if (controller_
->IsOpen(item_
.id
)) {
104 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE
));
106 if (!controller_
->IsPlatformApp(item_
.id
) &&
107 item_
.type
!= ash::TYPE_WINDOWED_APP
) {
108 AddSeparator(ui::NORMAL_SEPARATOR
);
109 if (extensions::util::IsNewBookmarkAppsEnabled()) {
110 // With bookmark apps enabled, hosted apps launch in a window by
111 // default. This menu item is re-interpreted as a single, toggle-able
112 // option to launch the hosted app as a tab.
113 AddCheckItemWithStringId(LAUNCH_TYPE_WINDOW
,
114 IDS_APP_CONTEXT_MENU_OPEN_WINDOW
);
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 !ash::Shell::GetInstance()->session_state_delegate()->IsScreenLocked()) {
181 AddSubMenuWithStringId(MENU_ALIGNMENT_MENU
,
182 IDS_ASH_SHELF_CONTEXT_MENU_POSITION
,
183 &shelf_alignment_menu_
);
185 #if defined(OS_CHROMEOS)
186 if (!controller_
->IsLoggedInAsGuest()) {
187 AddItem(MENU_CHANGE_WALLPAPER
,
188 l10n_util::GetStringUTF16(IDS_AURA_SET_DESKTOP_WALLPAPER
));
193 LauncherContextMenu::~LauncherContextMenu() {
196 bool LauncherContextMenu::IsItemForCommandIdDynamic(int command_id
) const {
197 return command_id
== MENU_OPEN_NEW
;
200 base::string16
LauncherContextMenu::GetLabelForCommandId(int command_id
) const {
201 if (command_id
== MENU_OPEN_NEW
) {
202 if (item_
.type
== ash::TYPE_PLATFORM_APP
) {
203 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW
);
205 switch (controller_
->GetLaunchType(item_
.id
)) {
206 case extensions::LAUNCH_TYPE_PINNED
:
207 case extensions::LAUNCH_TYPE_REGULAR
:
208 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_TAB
);
209 case extensions::LAUNCH_TYPE_FULLSCREEN
:
210 case extensions::LAUNCH_TYPE_WINDOW
:
211 return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW
);
214 return base::string16();
218 return base::string16();
221 bool LauncherContextMenu::IsCommandIdChecked(int command_id
) const {
222 switch (command_id
) {
223 case LAUNCH_TYPE_PINNED_TAB
:
224 return controller_
->GetLaunchType(item_
.id
) ==
225 extensions::LAUNCH_TYPE_PINNED
;
226 case LAUNCH_TYPE_REGULAR_TAB
:
227 return controller_
->GetLaunchType(item_
.id
) ==
228 extensions::LAUNCH_TYPE_REGULAR
;
229 case LAUNCH_TYPE_WINDOW
:
230 return controller_
->GetLaunchType(item_
.id
) ==
231 extensions::LAUNCH_TYPE_WINDOW
;
232 case LAUNCH_TYPE_FULLSCREEN
:
233 return controller_
->GetLaunchType(item_
.id
) ==
234 extensions::LAUNCH_TYPE_FULLSCREEN
;
236 return controller_
->GetShelfAutoHideBehavior(root_window_
) ==
237 ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS
;
239 return extension_items_
->IsCommandIdChecked(command_id
);
243 bool LauncherContextMenu::IsCommandIdEnabled(int command_id
) const {
244 switch (command_id
) {
246 return controller_
->IsPinnable(item_
.id
);
247 #if defined(OS_CHROMEOS)
248 case MENU_CHANGE_WALLPAPER
:
249 return ash::Shell::GetInstance()->user_wallpaper_delegate()->
250 CanOpenSetWallpaperPage();
252 case MENU_NEW_WINDOW
:
253 // "Normal" windows are not allowed when incognito is enforced.
254 return IncognitoModePrefs::GetAvailability(
255 controller_
->profile()->GetPrefs()) != IncognitoModePrefs::FORCED
;
257 return controller_
->CanUserModifyShelfAutoHideBehavior(root_window_
);
258 case MENU_NEW_INCOGNITO_WINDOW
:
259 // Incognito windows are not allowed when incognito is disabled.
260 return IncognitoModePrefs::GetAvailability(
261 controller_
->profile()->GetPrefs()) != IncognitoModePrefs::DISABLED
;
263 return extension_items_
->IsCommandIdEnabled(command_id
);
267 bool LauncherContextMenu::IsCommandIdVisible(int command_id
) const {
268 if (item_
.type
!= ash::TYPE_PLATFORM_APP
)
271 switch (command_id
) {
273 return !controller_
->CanInstall(item_
.id
);
275 return controller_
->CanInstall(item_
.id
);
281 bool LauncherContextMenu::GetAcceleratorForCommandId(
283 ui::Accelerator
* accelerator
) {
287 void LauncherContextMenu::ExecuteCommand(int command_id
, int event_flags
) {
288 switch (static_cast<MenuItem
>(command_id
)) {
290 controller_
->Launch(item_
.id
, ui::EF_NONE
);
293 if (item_
.type
== ash::TYPE_DIALOG
) {
294 DCHECK(item_delegate_
);
295 item_delegate_
->Close();
297 // TODO(simonhong): Use ShelfItemDelegate::Close().
298 controller_
->Close(item_
.id
);
300 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(
301 ash::UMA_CLOSE_THROUGH_CONTEXT_MENU
);
304 controller_
->TogglePinned(item_
.id
);
307 controller_
->Install(item_
.id
);
309 case LAUNCH_TYPE_PINNED_TAB
:
310 controller_
->SetLaunchType(item_
.id
, extensions::LAUNCH_TYPE_PINNED
);
312 case LAUNCH_TYPE_REGULAR_TAB
:
313 controller_
->SetLaunchType(item_
.id
, extensions::LAUNCH_TYPE_REGULAR
);
315 case LAUNCH_TYPE_WINDOW
: {
316 extensions::LaunchType launch_type
= extensions::LAUNCH_TYPE_WINDOW
;
317 // With bookmark apps enabled, hosted apps can only toggle between
318 // LAUNCH_WINDOW and LAUNCH_REGULAR.
319 if (extensions::util::IsNewBookmarkAppsEnabled()) {
320 launch_type
= controller_
->GetLaunchType(item_
.id
) ==
321 extensions::LAUNCH_TYPE_WINDOW
322 ? extensions::LAUNCH_TYPE_REGULAR
323 : extensions::LAUNCH_TYPE_WINDOW
;
325 controller_
->SetLaunchType(item_
.id
, launch_type
);
328 case LAUNCH_TYPE_FULLSCREEN
:
329 controller_
->SetLaunchType(item_
.id
, extensions::LAUNCH_TYPE_FULLSCREEN
);
332 controller_
->ToggleShelfAutoHideBehavior(root_window_
);
334 case MENU_NEW_WINDOW
:
335 controller_
->CreateNewWindow();
337 case MENU_NEW_INCOGNITO_WINDOW
:
338 controller_
->CreateNewIncognitoWindow();
340 case MENU_ALIGNMENT_MENU
:
342 #if defined(OS_CHROMEOS)
343 case MENU_CHANGE_WALLPAPER
:
344 ash::Shell::GetInstance()->user_wallpaper_delegate()->
345 OpenSetWallpaperPage();
349 extension_items_
->ExecuteCommand(command_id
, NULL
,
350 content::ContextMenuParams());