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