Update To 11.40.268.0
[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/bind.h"
8 #include "chrome/browser/extensions/context_menu_matcher.h"
9 #include "chrome/browser/extensions/extension_util.h"
10 #include "chrome/browser/extensions/menu_manager.h"
11 #include "chrome/browser/prefs/incognito_mode_prefs.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/app_list/app_context_menu_delegate.h"
14 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
15 #include "chrome/grit/chromium_strings.h"
16 #include "chrome/grit/generated_resources.h"
17 #include "content/public/common/context_menu_params.h"
18 #include "extensions/common/manifest_url_handlers.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   SHOW_APP_INFO,
34   OPTIONS,
35   UNINSTALL,
36   REMOVE_FROM_FOLDER,
37   MENU_NEW_WINDOW,
38   MENU_NEW_INCOGNITO_WINDOW,
39   // Order matters in USE_LAUNCH_TYPE_* and must match the LaunchType enum.
40   USE_LAUNCH_TYPE_COMMAND_START = 200,
41   USE_LAUNCH_TYPE_PINNED = USE_LAUNCH_TYPE_COMMAND_START,
42   USE_LAUNCH_TYPE_REGULAR,
43   USE_LAUNCH_TYPE_FULLSCREEN,
44   USE_LAUNCH_TYPE_WINDOW,
45   USE_LAUNCH_TYPE_COMMAND_END,
46 };
47
48 bool MenuItemHasLauncherContext(const extensions::MenuItem* item) {
49   return item->contexts().Contains(extensions::MenuItem::LAUNCHER);
50 }
51
52 }  // namespace
53
54 AppContextMenu::AppContextMenu(AppContextMenuDelegate* delegate,
55                                Profile* profile,
56                                const std::string& app_id,
57                                AppListControllerDelegate* controller)
58     : delegate_(delegate),
59       profile_(profile),
60       app_id_(app_id),
61       controller_(controller),
62       is_platform_app_(false),
63       is_search_result_(false),
64       is_in_folder_(false) {
65 }
66
67 AppContextMenu::~AppContextMenu() {
68 }
69
70 ui::MenuModel* AppContextMenu::GetMenuModel() {
71   if (!controller_->IsExtensionInstalled(profile_, app_id_))
72     return NULL;
73
74   if (menu_model_.get())
75     return menu_model_.get();
76
77   menu_model_.reset(new ui::SimpleMenuModel(this));
78
79   if (app_id_ == extension_misc::kChromeAppId) {
80     menu_model_->AddItemWithStringId(
81         MENU_NEW_WINDOW,
82         IDS_APP_LIST_NEW_WINDOW);
83     if (!profile_->IsOffTheRecord()) {
84       menu_model_->AddItemWithStringId(
85           MENU_NEW_INCOGNITO_WINDOW,
86           IDS_APP_LIST_NEW_INCOGNITO_WINDOW);
87     }
88     if (controller_->CanDoShowAppInfoFlow()) {
89       menu_model_->AddItemWithStringId(SHOW_APP_INFO,
90                                        IDS_APP_CONTEXT_MENU_SHOW_INFO);
91     }
92   } else {
93     extension_menu_items_.reset(new extensions::ContextMenuMatcher(
94         profile_, this, menu_model_.get(),
95         base::Bind(MenuItemHasLauncherContext)));
96
97     // First, add the primary actions.
98     if (!is_platform_app_)
99       menu_model_->AddItem(LAUNCH_NEW, base::string16());
100
101     // Show Pin/Unpin option if shelf is available.
102     if (controller_->GetPinnable() != AppListControllerDelegate::NO_PIN) {
103       menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
104       menu_model_->AddItemWithStringId(
105           TOGGLE_PIN,
106           controller_->IsAppPinned(app_id_) ?
107               IDS_APP_LIST_CONTEXT_MENU_UNPIN :
108               IDS_APP_LIST_CONTEXT_MENU_PIN);
109     }
110
111     if (controller_->CanDoCreateShortcutsFlow()) {
112       menu_model_->AddItemWithStringId(CREATE_SHORTCUTS,
113                                        IDS_NEW_TAB_APP_CREATE_SHORTCUT);
114     }
115     menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
116
117     if (!is_platform_app_) {
118       // Streamlined hosted apps can only toggle between USE_LAUNCH_TYPE_WINDOW
119       // and USE_LAUNCH_TYPE_REGULAR.
120       if (extensions::util::IsStreamlinedHostedAppsEnabled()) {
121         menu_model_->AddCheckItemWithStringId(
122             USE_LAUNCH_TYPE_REGULAR,
123             IDS_APP_CONTEXT_MENU_OPEN_TAB);
124       } else {
125         menu_model_->AddCheckItemWithStringId(
126             USE_LAUNCH_TYPE_REGULAR,
127             IDS_APP_CONTEXT_MENU_OPEN_REGULAR);
128         menu_model_->AddCheckItemWithStringId(
129             USE_LAUNCH_TYPE_PINNED,
130             IDS_APP_CONTEXT_MENU_OPEN_PINNED);
131 #if defined(OS_MACOSX)
132         // Mac does not support standalone web app browser windows or maximize.
133         menu_model_->AddCheckItemWithStringId(
134             USE_LAUNCH_TYPE_FULLSCREEN,
135             IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN);
136 #else
137         menu_model_->AddCheckItemWithStringId(
138             USE_LAUNCH_TYPE_WINDOW,
139             IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
140         // Even though the launch type is Full Screen it is more accurately
141         // described as Maximized in Ash.
142         menu_model_->AddCheckItemWithStringId(
143             USE_LAUNCH_TYPE_FULLSCREEN,
144             IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
145 #endif
146       }
147       menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
148     }
149
150     // Assign unique IDs to commands added by the app itself.
151     int index = USE_LAUNCH_TYPE_COMMAND_END;
152     extension_menu_items_->AppendExtensionItems(
153         extensions::MenuItem::ExtensionKey(app_id_),
154         base::string16(),
155         &index,
156         false);  // is_action_menu
157
158     // If at least 1 item was added, add another separator after the list.
159     if (index > USE_LAUNCH_TYPE_COMMAND_END)
160       menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
161
162     if (!is_platform_app_)
163       menu_model_->AddItemWithStringId(OPTIONS, IDS_NEW_TAB_APP_OPTIONS);
164
165     menu_model_->AddItemWithStringId(UNINSTALL,
166                                      is_platform_app_
167                                          ? IDS_APP_LIST_UNINSTALL_ITEM
168                                          : IDS_APP_LIST_EXTENSIONS_UNINSTALL);
169
170     if (controller_->CanDoShowAppInfoFlow()) {
171       menu_model_->AddItemWithStringId(SHOW_APP_INFO,
172                                        IDS_APP_CONTEXT_MENU_SHOW_INFO);
173     }
174   }
175
176   return menu_model_.get();
177 }
178
179 bool AppContextMenu::IsItemForCommandIdDynamic(int command_id) const {
180   return command_id == TOGGLE_PIN || command_id == LAUNCH_NEW;
181 }
182
183 base::string16 AppContextMenu::GetLabelForCommandId(int command_id) const {
184   if (command_id == TOGGLE_PIN) {
185     return controller_->IsAppPinned(app_id_) ?
186         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_UNPIN) :
187         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_PIN);
188   } else if (command_id == LAUNCH_NEW) {
189 #if defined(OS_MACOSX)
190     // Even fullscreen windows launch in a browser tab on Mac.
191     const bool launches_in_tab = true;
192 #else
193     const bool launches_in_tab = IsCommandIdChecked(USE_LAUNCH_TYPE_PINNED) ||
194         IsCommandIdChecked(USE_LAUNCH_TYPE_REGULAR);
195 #endif
196     return launches_in_tab ?
197         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_NEW_TAB) :
198         l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW);
199   } else {
200     NOTREACHED();
201     return base::string16();
202   }
203 }
204
205 bool AppContextMenu::IsCommandIdChecked(int command_id) const {
206   if (command_id >= USE_LAUNCH_TYPE_COMMAND_START &&
207       command_id < USE_LAUNCH_TYPE_COMMAND_END) {
208     return static_cast<int>(controller_->GetExtensionLaunchType(
209         profile_, app_id_)) + USE_LAUNCH_TYPE_COMMAND_START == command_id;
210   } else if (extensions::ContextMenuMatcher::IsExtensionsCustomCommandId(
211                  command_id)) {
212     return extension_menu_items_->IsCommandIdChecked(command_id);
213   }
214   return false;
215 }
216
217 bool AppContextMenu::IsCommandIdEnabled(int command_id) const {
218   if (command_id == TOGGLE_PIN) {
219     return controller_->GetPinnable() ==
220         AppListControllerDelegate::PIN_EDITABLE;
221   } else if (command_id == OPTIONS) {
222     return controller_->HasOptionsPage(profile_, app_id_);
223   } else if (command_id == UNINSTALL) {
224     return controller_->UserMayModifySettings(profile_, app_id_);
225   } else if (extensions::ContextMenuMatcher::IsExtensionsCustomCommandId(
226                  command_id)) {
227     return extension_menu_items_->IsCommandIdEnabled(command_id);
228   } else if (command_id == MENU_NEW_WINDOW) {
229     // "Normal" windows are not allowed when incognito is enforced.
230     return IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
231         IncognitoModePrefs::FORCED;
232   } else if (command_id == MENU_NEW_INCOGNITO_WINDOW) {
233     // Incognito windows are not allowed when incognito is disabled.
234     return IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
235         IncognitoModePrefs::DISABLED;
236   }
237   return true;
238 }
239
240 bool AppContextMenu::GetAcceleratorForCommandId(
241     int command_id,
242     ui::Accelerator* acclelrator) {
243   return false;
244 }
245
246 void AppContextMenu::ExecuteCommand(int command_id, int event_flags) {
247   if (command_id == LAUNCH_NEW) {
248     delegate_->ExecuteLaunchCommand(event_flags);
249   } else if (command_id == TOGGLE_PIN && controller_->GetPinnable() ==
250       AppListControllerDelegate::PIN_EDITABLE) {
251     if (controller_->IsAppPinned(app_id_))
252       controller_->UnpinApp(app_id_);
253     else
254       controller_->PinApp(app_id_);
255   } else if (command_id == CREATE_SHORTCUTS) {
256     controller_->DoCreateShortcutsFlow(profile_, app_id_);
257   } else if (command_id == SHOW_APP_INFO) {
258     controller_->DoShowAppInfoFlow(profile_, app_id_);
259   } else if (command_id >= USE_LAUNCH_TYPE_COMMAND_START &&
260              command_id < USE_LAUNCH_TYPE_COMMAND_END) {
261     extensions::LaunchType launch_type = static_cast<extensions::LaunchType>(
262         command_id - USE_LAUNCH_TYPE_COMMAND_START);
263     // Streamlined hosted apps can only toggle between LAUNCH_TYPE_WINDOW and
264     // LAUNCH_TYPE_REGULAR.
265     if (extensions::util::IsStreamlinedHostedAppsEnabled()) {
266       launch_type = (controller_->GetExtensionLaunchType(profile_, app_id_) ==
267                      extensions::LAUNCH_TYPE_REGULAR) ?
268                     extensions::LAUNCH_TYPE_WINDOW :
269                     extensions::LAUNCH_TYPE_REGULAR;
270     }
271     controller_->SetExtensionLaunchType(profile_, app_id_, launch_type);
272   } else if (command_id == OPTIONS) {
273     controller_->ShowOptionsPage(profile_, app_id_);
274   } else if (command_id == UNINSTALL) {
275     controller_->UninstallApp(profile_, app_id_);
276   } else if (extensions::ContextMenuMatcher::IsExtensionsCustomCommandId(
277                  command_id)) {
278     extension_menu_items_->ExecuteCommand(command_id, NULL,
279                                           content::ContextMenuParams());
280   } else if (command_id == MENU_NEW_WINDOW) {
281     controller_->CreateNewWindow(profile_, false);
282   } else if (command_id == MENU_NEW_INCOGNITO_WINDOW) {
283     controller_->CreateNewWindow(profile_, true);
284   }
285 }
286
287 }  // namespace app_list