Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / ash / launcher / launcher_context_menu.cc
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/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"
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::ShelfItem* item,
40                                          aura::Window* root)
41     : ui::SimpleMenuModel(NULL),
42       controller_(controller),
43       item_(*item),
44       shelf_alignment_menu_(root),
45       root_window_(root),
46       item_delegate_(NULL) {
47   DCHECK(item);
48   DCHECK(root_window_);
49   Init();
50 }
51
52 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
53                                          ash::ShelfItemDelegate* item_delegate,
54                                          ash::ShelfItem* item,
55                                          aura::Window* root)
56     : ui::SimpleMenuModel(NULL),
57       controller_(controller),
58       item_(*item),
59       shelf_alignment_menu_(root),
60       root_window_(root),
61       item_delegate_(item_delegate) {
62   DCHECK(item);
63   DCHECK(root_window_);
64   Init();
65 }
66
67 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
68                                          aura::Window* root)
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))),
76       root_window_(root),
77       item_delegate_(NULL) {
78   DCHECK(root_window_);
79   Init();
80 }
81
82 void LauncherContextMenu::Init() {
83   extension_items_.reset(new extensions::ContextMenuMatcher(
84       controller_->profile(), this, this,
85       base::Bind(MenuItemHasLauncherContext)));
86   set_delegate(this);
87
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);
95       }
96       AddItem(
97           MENU_PIN,
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)) {
102         AddItem(MENU_CLOSE,
103                 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
104       }
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);
115         } else {
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(
123               LAUNCH_TYPE_WINDOW,
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);
130         }
131       }
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));
138       }
139     } else if (item_.type == ash::TYPE_DIALOG) {
140       AddItem(MENU_CLOSE,
141               l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
142     } else {
143       if (item_.type == ash::TYPE_PLATFORM_APP) {
144         AddItem(
145             MENU_PIN,
146             l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_PIN));
147         AddItem(MENU_INSTALL, l10n_util::GetStringUTF16(IDS_APP_INSTALL_TITLE));
148       }
149       if (controller_->IsOpen(item_.id)) {
150         AddItem(MENU_CLOSE,
151                 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
152       }
153     }
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()) {
161         int index = 0;
162         extension_items_->AppendExtensionItems(app_key,
163                                                base::string16(),
164                                                &index,
165                                                false);  // is_action_menu
166         AddSeparator(ui::NORMAL_SEPARATOR);
167       }
168     }
169   }
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
173   // apply.
174   if (!IsFullScreenMode() &&
175       controller_->CanUserModifyShelfAutoHideBehavior(root_window_)) {
176     AddCheckItemWithStringId(MENU_AUTO_HIDE,
177                              IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE);
178   }
179   if (ash::ShelfWidget::ShelfAlignmentAllowed()) {
180     AddSubMenuWithStringId(MENU_ALIGNMENT_MENU,
181                            IDS_ASH_SHELF_CONTEXT_MENU_POSITION,
182                            &shelf_alignment_menu_);
183   }
184 #if defined(OS_CHROMEOS)
185   AddItem(MENU_CHANGE_WALLPAPER,
186        l10n_util::GetStringUTF16(IDS_AURA_SET_DESKTOP_WALLPAPER));
187 #endif
188 }
189
190 LauncherContextMenu::~LauncherContextMenu() {
191 }
192
193 bool LauncherContextMenu::IsItemForCommandIdDynamic(int command_id) const {
194   return command_id == MENU_OPEN_NEW;
195 }
196
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);
201     }
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);
209       default:
210         NOTREACHED();
211         return base::string16();
212     }
213   }
214   NOTREACHED();
215   return base::string16();
216 }
217
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;
232     case MENU_AUTO_HIDE:
233       return controller_->GetShelfAutoHideBehavior(root_window_) ==
234           ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
235     default:
236       return extension_items_->IsCommandIdChecked(command_id);
237   }
238 }
239
240 bool LauncherContextMenu::IsCommandIdEnabled(int command_id) const {
241   switch (command_id) {
242     case MENU_PIN:
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();
248 #endif
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;
253     case MENU_AUTO_HIDE:
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;
259     default:
260       return extension_items_->IsCommandIdEnabled(command_id);
261   }
262 }
263
264 bool LauncherContextMenu::IsCommandIdVisible(int command_id) const {
265   if (item_.type != ash::TYPE_PLATFORM_APP)
266     return true;
267
268   switch (command_id) {
269     case MENU_PIN:
270       return !controller_->CanInstall(item_.id);
271     case MENU_INSTALL:
272       return controller_->CanInstall(item_.id);
273     default:
274       return true;
275   }
276 }
277
278 bool LauncherContextMenu::GetAcceleratorForCommandId(
279       int command_id,
280       ui::Accelerator* accelerator) {
281   return false;
282 }
283
284 void LauncherContextMenu::ExecuteCommand(int command_id, int event_flags) {
285   switch (static_cast<MenuItem>(command_id)) {
286     case MENU_OPEN_NEW:
287       controller_->Launch(item_.id, ui::EF_NONE);
288       break;
289     case MENU_CLOSE:
290       if (item_.type == ash::TYPE_DIALOG) {
291         DCHECK(item_delegate_);
292         item_delegate_->Close();
293       } else {
294         // TODO(simonhong): Use ShelfItemDelegate::Close().
295         controller_->Close(item_.id);
296       }
297       ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(
298           ash::UMA_CLOSE_THROUGH_CONTEXT_MENU);
299       break;
300     case MENU_PIN:
301       controller_->TogglePinned(item_.id);
302       break;
303     case MENU_INSTALL:
304       controller_->Install(item_.id);
305       break;
306     case LAUNCH_TYPE_PINNED_TAB:
307       controller_->SetLaunchType(item_.id, extensions::LAUNCH_TYPE_PINNED);
308       break;
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
313       // LAUNCH_REGULAR.
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;
319       }
320       controller_->SetLaunchType(item_.id, launch_type);
321       break;
322     }
323     case LAUNCH_TYPE_WINDOW:
324       controller_->SetLaunchType(item_.id, extensions::LAUNCH_TYPE_WINDOW);
325       break;
326     case LAUNCH_TYPE_FULLSCREEN:
327       controller_->SetLaunchType(item_.id, extensions::LAUNCH_TYPE_FULLSCREEN);
328       break;
329     case MENU_AUTO_HIDE:
330       controller_->ToggleShelfAutoHideBehavior(root_window_);
331       break;
332     case MENU_NEW_WINDOW:
333       controller_->CreateNewWindow();
334       break;
335     case MENU_NEW_INCOGNITO_WINDOW:
336       controller_->CreateNewIncognitoWindow();
337       break;
338     case MENU_ALIGNMENT_MENU:
339       break;
340 #if defined(OS_CHROMEOS)
341     case MENU_CHANGE_WALLPAPER:
342       ash::Shell::GetInstance()->user_wallpaper_delegate()->
343           OpenSetWallpaperPage();
344       break;
345 #endif
346     default:
347       extension_items_->ExecuteCommand(command_id, NULL,
348                                        content::ContextMenuParams());
349   }
350 }