Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / app_list / app_context_menu.cc
blob12a4230a68fb0980184cbf15cb4dd31e79909c4a
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.
5 #include "chrome/browser/ui/app_list/app_context_menu.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "chrome/app/chrome_command_ids.h"
10 #include "chrome/browser/extensions/context_menu_matcher.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/common/chrome_switches.h"
16 #include "chrome/common/extensions/extension_constants.h"
17 #include "chrome/common/extensions/manifest_url_handler.h"
18 #include "content/public/common/context_menu_params.h"
19 #include "grit/chromium_strings.h"
20 #include "grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util.h"
23 #if defined(USE_ASH)
24 #include "ash/shell.h"
25 #endif
27 namespace app_list {
29 namespace {
31 enum CommandId {
32 LAUNCH_NEW = 100,
33 TOGGLE_PIN,
34 CREATE_SHORTCUTS,
35 OPTIONS,
36 UNINSTALL,
37 DETAILS,
38 MENU_NEW_WINDOW,
39 MENU_NEW_INCOGNITO_WINDOW,
40 // Order matters in USE_LAUNCH_TYPE_* and must match the LaunchType enum.
41 USE_LAUNCH_TYPE_COMMAND_START = 200,
42 USE_LAUNCH_TYPE_PINNED = USE_LAUNCH_TYPE_COMMAND_START,
43 USE_LAUNCH_TYPE_REGULAR,
44 USE_LAUNCH_TYPE_FULLSCREEN,
45 USE_LAUNCH_TYPE_WINDOW,
46 USE_LAUNCH_TYPE_COMMAND_END,
49 bool MenuItemHasLauncherContext(const extensions::MenuItem* item) {
50 return item->contexts().Contains(extensions::MenuItem::LAUNCHER);
53 } // namespace
55 AppContextMenu::AppContextMenu(AppContextMenuDelegate* delegate,
56 Profile* profile,
57 const std::string& app_id,
58 AppListControllerDelegate* controller,
59 bool is_platform_app,
60 bool is_search_result)
61 : delegate_(delegate),
62 profile_(profile),
63 app_id_(app_id),
64 controller_(controller),
65 is_platform_app_(is_platform_app),
66 is_search_result_(is_search_result) {
69 AppContextMenu::~AppContextMenu() {}
71 ui::MenuModel* AppContextMenu::GetMenuModel() {
72 if (!controller_->IsExtensionInstalled(profile_, app_id_))
73 return NULL;
75 if (menu_model_.get())
76 return menu_model_.get();
78 menu_model_.reset(new ui::SimpleMenuModel(this));
80 if (app_id_ == extension_misc::kChromeAppId) {
81 menu_model_->AddItemWithStringId(
82 MENU_NEW_WINDOW,
83 IDS_APP_LIST_NEW_WINDOW);
84 if (!profile_->IsOffTheRecord()) {
85 menu_model_->AddItemWithStringId(
86 MENU_NEW_INCOGNITO_WINDOW,
87 IDS_APP_LIST_NEW_INCOGNITO_WINDOW);
89 } else {
90 extension_menu_items_.reset(new extensions::ContextMenuMatcher(
91 profile_, this, menu_model_.get(),
92 base::Bind(MenuItemHasLauncherContext)));
94 if (!is_platform_app_)
95 menu_model_->AddItem(LAUNCH_NEW, base::string16());
97 int index = 0;
98 extension_menu_items_->AppendExtensionItems(app_id_, base::string16(),
99 &index);
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);
111 if (controller_->CanDoCreateShortcutsFlow()) {
112 menu_model_->AddItemWithStringId(CREATE_SHORTCUTS,
113 IDS_NEW_TAB_APP_CREATE_SHORTCUT);
116 if (!is_platform_app_) {
117 menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
118 // Streamlined hosted apps can only toggle between USE_LAUNCH_TYPE_WINDOW
119 // and USE_LAUNCH_TYPE_REGULAR.
120 if (CommandLine::ForCurrentProcess()->HasSwitch(
121 switches::kEnableStreamlinedHostedApps)) {
122 menu_model_->AddCheckItemWithStringId(
123 USE_LAUNCH_TYPE_REGULAR,
124 IDS_APP_CONTEXT_MENU_OPEN_TAB);
125 } else {
126 menu_model_->AddCheckItemWithStringId(
127 USE_LAUNCH_TYPE_REGULAR,
128 IDS_APP_CONTEXT_MENU_OPEN_REGULAR);
129 menu_model_->AddCheckItemWithStringId(
130 USE_LAUNCH_TYPE_PINNED,
131 IDS_APP_CONTEXT_MENU_OPEN_PINNED);
132 #if defined(OS_MACOSX)
133 // Mac does not support standalone web app browser windows or maximize.
134 menu_model_->AddCheckItemWithStringId(
135 USE_LAUNCH_TYPE_FULLSCREEN,
136 IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN);
137 #else
138 menu_model_->AddCheckItemWithStringId(
139 USE_LAUNCH_TYPE_WINDOW,
140 IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
141 // Even though the launch type is Full Screen it is more accurately
142 // described as Maximized in Ash.
143 menu_model_->AddCheckItemWithStringId(
144 USE_LAUNCH_TYPE_FULLSCREEN,
145 IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
146 #endif
148 menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
149 menu_model_->AddItemWithStringId(OPTIONS, IDS_NEW_TAB_APP_OPTIONS);
152 menu_model_->AddItemWithStringId(DETAILS, IDS_NEW_TAB_APP_DETAILS);
153 menu_model_->AddItemWithStringId(
154 UNINSTALL,
155 is_platform_app_ ? IDS_APP_LIST_UNINSTALL_ITEM
156 : IDS_EXTENSIONS_UNINSTALL);
159 return menu_model_.get();
162 bool AppContextMenu::IsItemForCommandIdDynamic(int command_id) const {
163 return command_id == TOGGLE_PIN || command_id == LAUNCH_NEW;
166 base::string16 AppContextMenu::GetLabelForCommandId(int command_id) const {
167 if (command_id == TOGGLE_PIN) {
168 return controller_->IsAppPinned(app_id_) ?
169 l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_UNPIN) :
170 l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_PIN);
171 } else if (command_id == LAUNCH_NEW) {
172 #if defined(OS_MACOSX)
173 // Even fullscreen windows launch in a browser tab on Mac.
174 const bool launches_in_tab = true;
175 #else
176 const bool launches_in_tab = IsCommandIdChecked(USE_LAUNCH_TYPE_PINNED) ||
177 IsCommandIdChecked(USE_LAUNCH_TYPE_REGULAR);
178 #endif
179 return launches_in_tab ?
180 l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_NEW_TAB) :
181 l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW);
182 } else {
183 NOTREACHED();
184 return base::string16();
188 bool AppContextMenu::IsCommandIdChecked(int command_id) const {
189 if (command_id >= USE_LAUNCH_TYPE_COMMAND_START &&
190 command_id < USE_LAUNCH_TYPE_COMMAND_END) {
191 return static_cast<int>(controller_->GetExtensionLaunchType(
192 profile_, app_id_)) + USE_LAUNCH_TYPE_COMMAND_START == command_id;
193 } else if (command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
194 command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
195 return extension_menu_items_->IsCommandIdChecked(command_id);
197 return false;
200 bool AppContextMenu::IsCommandIdEnabled(int command_id) const {
201 if (command_id == TOGGLE_PIN) {
202 return controller_->GetPinnable() ==
203 AppListControllerDelegate::PIN_EDITABLE;
204 } else if (command_id == OPTIONS) {
205 return controller_->HasOptionsPage(profile_, app_id_);
206 } else if (command_id == UNINSTALL) {
207 return controller_->UserMayModifySettings(profile_, app_id_);
208 } else if (command_id == DETAILS) {
209 return controller_->IsAppFromWebStore(profile_, app_id_);
210 } else if (command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
211 command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
212 return extension_menu_items_->IsCommandIdEnabled(command_id);
213 } else if (command_id == MENU_NEW_WINDOW) {
214 // "Normal" windows are not allowed when incognito is enforced.
215 return IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
216 IncognitoModePrefs::FORCED;
217 } else if (command_id == MENU_NEW_INCOGNITO_WINDOW) {
218 // Incognito windows are not allowed when incognito is disabled.
219 return IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
220 IncognitoModePrefs::DISABLED;
222 return true;
225 bool AppContextMenu::GetAcceleratorForCommandId(
226 int command_id,
227 ui::Accelerator* acclelrator) {
228 return false;
231 void AppContextMenu::ExecuteCommand(int command_id, int event_flags) {
232 if (command_id == LAUNCH_NEW) {
233 delegate_->ExecuteLaunchCommand(event_flags);
234 } else if (command_id == TOGGLE_PIN && controller_->GetPinnable() ==
235 AppListControllerDelegate::PIN_EDITABLE) {
236 if (controller_->IsAppPinned(app_id_))
237 controller_->UnpinApp(app_id_);
238 else
239 controller_->PinApp(app_id_);
240 } else if (command_id == CREATE_SHORTCUTS) {
241 controller_->DoCreateShortcutsFlow(profile_, app_id_);
242 } else if (command_id >= USE_LAUNCH_TYPE_COMMAND_START &&
243 command_id < USE_LAUNCH_TYPE_COMMAND_END) {
244 extensions::LaunchType launch_type = static_cast<extensions::LaunchType>(
245 command_id - USE_LAUNCH_TYPE_COMMAND_START);
246 // Streamlined hosted apps can only toggle between LAUNCH_TYPE_WINDOW and
247 // LAUNCH_TYPE_REGULAR.
248 if (CommandLine::ForCurrentProcess()->HasSwitch(
249 switches::kEnableStreamlinedHostedApps)) {
250 launch_type = (controller_->GetExtensionLaunchType(profile_, app_id_) ==
251 extensions::LAUNCH_TYPE_REGULAR) ?
252 extensions::LAUNCH_TYPE_WINDOW :
253 extensions::LAUNCH_TYPE_REGULAR;
255 controller_->SetExtensionLaunchType(profile_, app_id_, 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);
273 } // namespace app_list