- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / app_context_menu.cc
1 // Copyright 2013 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/app_list/app_context_menu.h"
6
7 #include "base/command_line.h"
8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/extensions/context_menu_matcher.h"
10 #include "chrome/browser/prefs/incognito_mode_prefs.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/app_list/app_context_menu_delegate.h"
13 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/extensions/manifest_url_handler.h"
16 #include "content/public/common/context_menu_params.h"
17 #include "grit/chromium_strings.h"
18 #include "grit/generated_resources.h"
19 #include "ui/base/l10n/l10n_util.h"
20
21 #if defined(USE_ASH)
22 #include "ash/shell.h"
23 #endif
24
25 namespace app_list {
26
27 namespace {
28
29 enum CommandId {
30   LAUNCH_NEW = 100,
31   TOGGLE_PIN,
32   CREATE_SHORTCUTS,
33   OPTIONS,
34   UNINSTALL,
35   DETAILS,
36   MENU_NEW_WINDOW,
37   MENU_NEW_INCOGNITO_WINDOW,
38   // Order matters in LAUNCHER_TYPE_xxxx and must match LaunchType.
39   LAUNCH_TYPE_START = 200,
40   LAUNCH_TYPE_PINNED_TAB = LAUNCH_TYPE_START,
41   LAUNCH_TYPE_REGULAR_TAB,
42   LAUNCH_TYPE_FULLSCREEN,
43   LAUNCH_TYPE_WINDOW,
44   LAUNCH_TYPE_LAST,
45 };
46
47 bool MenuItemHasLauncherContext(const extensions::MenuItem* item) {
48   return item->contexts().Contains(extensions::MenuItem::LAUNCHER);
49 }
50
51 }  // namespace
52
53 AppContextMenu::AppContextMenu(AppContextMenuDelegate* delegate,
54                                Profile* profile,
55                                const std::string& app_id,
56                                AppListControllerDelegate* controller,
57                                bool is_platform_app,
58                                bool is_search_result)
59     : delegate_(delegate),
60       profile_(profile),
61       app_id_(app_id),
62       controller_(controller),
63       is_platform_app_(is_platform_app),
64       is_search_result_(is_search_result) {
65 }
66
67 AppContextMenu::~AppContextMenu() {}
68
69 ui::MenuModel* AppContextMenu::GetMenuModel() {
70   if (!controller_->IsExtensionInstalled(profile_, app_id_))
71     return NULL;
72
73   if (menu_model_.get())
74     return menu_model_.get();
75
76   menu_model_.reset(new ui::SimpleMenuModel(this));
77
78   if (app_id_ == extension_misc::kChromeAppId) {
79     menu_model_->AddItemWithStringId(
80         MENU_NEW_WINDOW,
81         IDS_APP_LIST_NEW_WINDOW);
82     if (!profile_->IsOffTheRecord()) {
83       menu_model_->AddItemWithStringId(
84           MENU_NEW_INCOGNITO_WINDOW,
85           IDS_APP_LIST_NEW_INCOGNITO_WINDOW);
86     }
87   } else {
88     extension_menu_items_.reset(new extensions::ContextMenuMatcher(
89         profile_, this, menu_model_.get(),
90         base::Bind(MenuItemHasLauncherContext)));
91
92     if (!is_platform_app_)
93       menu_model_->AddItem(LAUNCH_NEW, string16());
94
95     int index = 0;
96     extension_menu_items_->AppendExtensionItems(app_id_, string16(),
97                                                 &index);
98
99     // Show Pin/Unpin option if shelf is available.
100     if (controller_->GetPinnable() != AppListControllerDelegate::NO_PIN) {
101       menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
102       menu_model_->AddItemWithStringId(
103           TOGGLE_PIN,
104           controller_->IsAppPinned(app_id_) ?
105               IDS_APP_LIST_CONTEXT_MENU_UNPIN :
106               IDS_APP_LIST_CONTEXT_MENU_PIN);
107     }
108
109     if (controller_->CanDoCreateShortcutsFlow()) {
110       menu_model_->AddItemWithStringId(CREATE_SHORTCUTS,
111                                        IDS_NEW_TAB_APP_CREATE_SHORTCUT);
112     }
113
114     if (!is_platform_app_) {
115       menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
116       // Streamlined hosted apps can only toggle between LAUNCH_WINDOW and
117       // LAUNCH_REGULAR.
118       if (CommandLine::ForCurrentProcess()->HasSwitch(
119           switches::kEnableStreamlinedHostedApps)) {
120         menu_model_->AddCheckItemWithStringId(
121             LAUNCH_TYPE_REGULAR_TAB,
122             IDS_APP_CONTEXT_MENU_OPEN_TAB);
123       } else {
124         menu_model_->AddCheckItemWithStringId(
125             LAUNCH_TYPE_REGULAR_TAB,
126             IDS_APP_CONTEXT_MENU_OPEN_REGULAR);
127         menu_model_->AddCheckItemWithStringId(
128             LAUNCH_TYPE_PINNED_TAB,
129             IDS_APP_CONTEXT_MENU_OPEN_PINNED);
130 #if defined(OS_MACOSX)
131         // Mac does not support standalone web app browser windows or maximize.
132         menu_model_->AddCheckItemWithStringId(
133             LAUNCH_TYPE_FULLSCREEN,
134             IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN);
135 #else
136         menu_model_->AddCheckItemWithStringId(
137             LAUNCH_TYPE_WINDOW,
138             IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
139         // Even though the launch type is Full Screen it is more accurately
140         // described as Maximized in Ash.
141         menu_model_->AddCheckItemWithStringId(
142             LAUNCH_TYPE_FULLSCREEN,
143             IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
144 #endif
145       }
146       menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
147       menu_model_->AddItemWithStringId(OPTIONS, IDS_NEW_TAB_APP_OPTIONS);
148     }
149
150     menu_model_->AddItemWithStringId(DETAILS, IDS_NEW_TAB_APP_DETAILS);
151     menu_model_->AddItemWithStringId(
152         UNINSTALL,
153         is_platform_app_ ? IDS_APP_LIST_UNINSTALL_ITEM
154                          : IDS_EXTENSIONS_UNINSTALL);
155   }
156
157   return menu_model_.get();
158 }
159
160 bool AppContextMenu::IsItemForCommandIdDynamic(int command_id) const {
161   return command_id == TOGGLE_PIN || command_id == LAUNCH_NEW;
162 }
163
164 string16 AppContextMenu::GetLabelForCommandId(int command_id) const {
165   if (command_id == TOGGLE_PIN) {
166     return controller_->IsAppPinned(app_id_) ?
167         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_UNPIN) :
168         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_PIN);
169   } else if (command_id == LAUNCH_NEW) {
170 #if defined(OS_MACOSX)
171     // Even fullscreen windows launch in a browser tab on Mac.
172     const bool launches_in_tab = true;
173 #else
174     const bool launches_in_tab = IsCommandIdChecked(LAUNCH_TYPE_PINNED_TAB) ||
175         IsCommandIdChecked(LAUNCH_TYPE_REGULAR_TAB);
176 #endif
177     return launches_in_tab ?
178         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_NEW_TAB) :
179         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW);
180   } else {
181     NOTREACHED();
182     return string16();
183   }
184 }
185
186 bool AppContextMenu::IsCommandIdChecked(int command_id) const {
187   if (command_id >= LAUNCH_TYPE_START && command_id < LAUNCH_TYPE_LAST) {
188     return static_cast<int>(controller_->GetExtensionLaunchType(
189         profile_, app_id_)) + LAUNCH_TYPE_START == command_id;
190   } else if (command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
191              command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
192     return extension_menu_items_->IsCommandIdChecked(command_id);
193   }
194   return false;
195 }
196
197 bool AppContextMenu::IsCommandIdEnabled(int command_id) const {
198   if (command_id == TOGGLE_PIN) {
199     return controller_->GetPinnable() ==
200         AppListControllerDelegate::PIN_EDITABLE;
201   } else if (command_id == OPTIONS) {
202     return controller_->HasOptionsPage(profile_, app_id_);
203   } else if (command_id == UNINSTALL) {
204     return controller_->UserMayModifySettings(profile_, app_id_);
205   } else if (command_id == DETAILS) {
206     return controller_->IsAppFromWebStore(profile_, app_id_);
207   } else if (command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
208              command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
209     return extension_menu_items_->IsCommandIdEnabled(command_id);
210   } else if (command_id == MENU_NEW_WINDOW) {
211     // "Normal" windows are not allowed when incognito is enforced.
212     return IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
213         IncognitoModePrefs::FORCED;
214   } else if (command_id == MENU_NEW_INCOGNITO_WINDOW) {
215     // Incognito windows are not allowed when incognito is disabled.
216     return IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
217         IncognitoModePrefs::DISABLED;
218   }
219   return true;
220 }
221
222 bool AppContextMenu::GetAcceleratorForCommandId(
223     int command_id,
224     ui::Accelerator* acclelrator) {
225   return false;
226 }
227
228 void AppContextMenu::ExecuteCommand(int command_id, int event_flags) {
229   if (command_id == LAUNCH_NEW) {
230     delegate_->ExecuteLaunchCommand(event_flags);
231   } else if (command_id == TOGGLE_PIN && controller_->GetPinnable() ==
232       AppListControllerDelegate::PIN_EDITABLE) {
233     if (controller_->IsAppPinned(app_id_))
234       controller_->UnpinApp(app_id_);
235     else
236       controller_->PinApp(app_id_);
237   } else if (command_id == CREATE_SHORTCUTS) {
238     controller_->DoCreateShortcutsFlow(profile_, app_id_);
239   } else if (command_id >= LAUNCH_TYPE_START &&
240              command_id < LAUNCH_TYPE_LAST) {
241     extensions::ExtensionPrefs::LaunchType launch_type =
242         static_cast<extensions::ExtensionPrefs::LaunchType>(
243             command_id - LAUNCH_TYPE_START);
244     // Streamlined hosted apps can only toggle between LAUNCH_WINDOW and
245     // LAUNCH_REGULAR.
246     if (CommandLine::ForCurrentProcess()->HasSwitch(
247         switches::kEnableStreamlinedHostedApps)) {
248       launch_type = controller_->GetExtensionLaunchType(profile_, app_id_) ==
249                             extensions::ExtensionPrefs::LAUNCH_REGULAR
250                         ? extensions::ExtensionPrefs::LAUNCH_WINDOW
251                         : extensions::ExtensionPrefs::LAUNCH_REGULAR;
252     }
253     controller_->SetExtensionLaunchType(profile_,
254                                         app_id_,
255                                         launch_type);
256   } else if (command_id == OPTIONS) {
257     controller_->ShowOptionsPage(profile_, app_id_);
258   } else if (command_id == UNINSTALL) {
259     controller_->UninstallApp(profile_, app_id_);
260   } else if (command_id == DETAILS) {
261     controller_->ShowAppInWebStore(profile_, app_id_, is_search_result_);
262   } else if (command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
263              command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
264     extension_menu_items_->ExecuteCommand(command_id, NULL,
265                                           content::ContextMenuParams());
266   } else if (command_id == MENU_NEW_WINDOW) {
267     controller_->CreateNewWindow(profile_, false);
268   } else if (command_id == MENU_NEW_INCOGNITO_WINDOW) {
269     controller_->CreateNewWindow(profile_, true);
270   }
271 }
272
273 }  // namespace app_list