Android Chromoting: Remove exit-fullscreen button.
[chromium-blink-merge.git] / chrome / browser / renderer_context_menu / render_view_context_menu.cc
blobb6d877e985121b5aa612b8f57750201a8a128bee
1 // Copyright 2014 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/renderer_context_menu/render_view_context_menu.h"
7 #include <algorithm>
8 #include <set>
9 #include <utility>
11 #include "apps/app_load_service.h"
12 #include "base/command_line.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/prefs/pref_member.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/stl_util.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "chrome/app/chrome_command_ids.h"
22 #include "chrome/browser/app_mode/app_mode_utils.h"
23 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
24 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
25 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/chrome_notification_types.h"
27 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
28 #include "chrome/browser/devtools/devtools_window.h"
29 #include "chrome/browser/download/download_service.h"
30 #include "chrome/browser/download/download_service_factory.h"
31 #include "chrome/browser/download/download_stats.h"
32 #include "chrome/browser/extensions/devtools_util.h"
33 #include "chrome/browser/extensions/extension_service.h"
34 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
35 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
36 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
37 #include "chrome/browser/prefs/incognito_mode_prefs.h"
38 #include "chrome/browser/profiles/profile.h"
39 #include "chrome/browser/profiles/profile_io_data.h"
40 #include "chrome/browser/renderer_context_menu/context_menu_content_type_factory.h"
41 #include "chrome/browser/renderer_context_menu/spellchecker_submenu_observer.h"
42 #include "chrome/browser/renderer_context_menu/spelling_menu_observer.h"
43 #include "chrome/browser/search/search.h"
44 #include "chrome/browser/search_engines/template_url_service_factory.h"
45 #include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
46 #include "chrome/browser/spellchecker/spellcheck_service.h"
47 #include "chrome/browser/tab_contents/retargeting_details.h"
48 #include "chrome/browser/translate/chrome_translate_client.h"
49 #include "chrome/browser/translate/translate_service.h"
50 #include "chrome/browser/ui/browser.h"
51 #include "chrome/browser/ui/browser_commands.h"
52 #include "chrome/browser/ui/browser_finder.h"
53 #include "chrome/browser/ui/chrome_pages.h"
54 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
55 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
56 #include "chrome/common/chrome_constants.h"
57 #include "chrome/common/chrome_switches.h"
58 #include "chrome/common/content_restriction.h"
59 #include "chrome/common/net/url_util.h"
60 #include "chrome/common/pref_names.h"
61 #include "chrome/common/render_messages.h"
62 #include "chrome/common/spellcheck_messages.h"
63 #include "chrome/common/url_constants.h"
64 #include "chrome/grit/generated_resources.h"
65 #include "components/google/core/browser/google_util.h"
66 #include "components/metrics/proto/omnibox_input_type.pb.h"
67 #include "components/omnibox/autocomplete_match.h"
68 #include "components/search_engines/template_url.h"
69 #include "components/search_engines/template_url_service.h"
70 #include "components/translate/core/browser/translate_download_manager.h"
71 #include "components/translate/core/browser/translate_manager.h"
72 #include "components/translate/core/browser/translate_prefs.h"
73 #include "components/user_prefs/user_prefs.h"
74 #include "content/public/browser/child_process_security_policy.h"
75 #include "content/public/browser/download_manager.h"
76 #include "content/public/browser/download_save_info.h"
77 #include "content/public/browser/download_url_parameters.h"
78 #include "content/public/browser/navigation_details.h"
79 #include "content/public/browser/navigation_entry.h"
80 #include "content/public/browser/notification_service.h"
81 #include "content/public/browser/render_frame_host.h"
82 #include "content/public/browser/render_process_host.h"
83 #include "content/public/browser/render_view_host.h"
84 #include "content/public/browser/render_widget_host_view.h"
85 #include "content/public/browser/user_metrics.h"
86 #include "content/public/browser/web_contents.h"
87 #include "content/public/common/menu_item.h"
88 #include "content/public/common/ssl_status.h"
89 #include "content/public/common/url_utils.h"
90 #include "extensions/browser/extension_host.h"
91 #include "extensions/browser/extension_system.h"
92 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
93 #include "extensions/browser/view_type_utils.h"
94 #include "extensions/common/extension.h"
95 #include "net/base/escape.h"
96 #include "third_party/WebKit/public/web/WebContextMenuData.h"
97 #include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
98 #include "third_party/WebKit/public/web/WebPluginAction.h"
99 #include "ui/base/clipboard/clipboard.h"
100 #include "ui/base/l10n/l10n_util.h"
101 #include "ui/gfx/favicon_size.h"
102 #include "ui/gfx/geometry/point.h"
103 #include "ui/gfx/geometry/size.h"
104 #include "ui/gfx/text_elider.h"
106 #if defined(ENABLE_PRINTING)
107 #include "chrome/browser/printing/print_view_manager_common.h"
108 #include "components/printing/common/print_messages.h"
110 #if defined(ENABLE_PRINT_PREVIEW)
111 #include "chrome/browser/printing/print_preview_context_menu_observer.h"
112 #include "chrome/browser/printing/print_preview_dialog_controller.h"
113 #endif // defined(ENABLE_PRINT_PREVIEW)
114 #endif // defined(ENABLE_PRINTING)
116 using base::UserMetricsAction;
117 using blink::WebContextMenuData;
118 using blink::WebMediaPlayerAction;
119 using blink::WebPluginAction;
120 using blink::WebString;
121 using blink::WebURL;
122 using content::BrowserContext;
123 using content::ChildProcessSecurityPolicy;
124 using content::DownloadManager;
125 using content::DownloadUrlParameters;
126 using content::NavigationController;
127 using content::NavigationEntry;
128 using content::OpenURLParams;
129 using content::RenderFrameHost;
130 using content::RenderViewHost;
131 using content::SSLStatus;
132 using content::WebContents;
133 using extensions::ContextMenuMatcher;
134 using extensions::Extension;
135 using extensions::MenuItem;
136 using extensions::MenuManager;
138 namespace {
140 const int kImageSearchThumbnailMinSize = 300 * 300;
141 const int kImageSearchThumbnailMaxWidth = 600;
142 const int kImageSearchThumbnailMaxHeight = 600;
144 // Maps UMA enumeration to IDC. IDC could be changed so we can't use
145 // just them and |UMA_HISTOGRAM_CUSTOM_ENUMERATION|.
146 // Never change mapping or reuse |enum_id|. Always push back new items.
147 // Items that is not used any more by |RenderViewContextMenu.ExecuteCommand|
148 // could be deleted, but don't change the rest of |kUmaEnumToControlId|.
149 const struct UmaEnumCommandIdPair {
150 int enum_id;
151 int control_id;
152 } kUmaEnumToControlId[] = {
154 enum id for 0, 1 are detected using
155 RenderViewContextMenu::IsContentCustomCommandId and
156 ContextMenuMatcher::IsExtensionsCustomCommandId
158 {2, IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST},
159 {3, IDC_CONTENT_CONTEXT_OPENLINKNEWTAB},
160 {4, IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW},
161 {5, IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD},
162 {6, IDC_CONTENT_CONTEXT_SAVELINKAS},
163 {7, IDC_CONTENT_CONTEXT_SAVEAVAS},
164 {8, IDC_CONTENT_CONTEXT_SAVEIMAGEAS},
165 {9, IDC_CONTENT_CONTEXT_COPYLINKLOCATION},
166 {10, IDC_CONTENT_CONTEXT_COPYIMAGELOCATION},
167 {11, IDC_CONTENT_CONTEXT_COPYAVLOCATION},
168 {12, IDC_CONTENT_CONTEXT_COPYIMAGE},
169 {13, IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB},
170 {14, IDC_CONTENT_CONTEXT_OPENAVNEWTAB},
171 {15, IDC_CONTENT_CONTEXT_PLAYPAUSE},
172 {16, IDC_CONTENT_CONTEXT_MUTE},
173 {17, IDC_CONTENT_CONTEXT_LOOP},
174 {18, IDC_CONTENT_CONTEXT_CONTROLS},
175 {19, IDC_CONTENT_CONTEXT_ROTATECW},
176 {20, IDC_CONTENT_CONTEXT_ROTATECCW},
177 {21, IDC_BACK},
178 {22, IDC_FORWARD},
179 {23, IDC_SAVE_PAGE},
180 {24, IDC_RELOAD},
181 {25, IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP},
182 {26, IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP},
183 {27, IDC_PRINT},
184 {28, IDC_VIEW_SOURCE},
185 {29, IDC_CONTENT_CONTEXT_INSPECTELEMENT},
186 {30, IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE},
187 {31, IDC_CONTENT_CONTEXT_VIEWPAGEINFO},
188 {32, IDC_CONTENT_CONTEXT_TRANSLATE},
189 {33, IDC_CONTENT_CONTEXT_RELOADFRAME},
190 {34, IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE},
191 {35, IDC_CONTENT_CONTEXT_VIEWFRAMEINFO},
192 {36, IDC_CONTENT_CONTEXT_UNDO},
193 {37, IDC_CONTENT_CONTEXT_REDO},
194 {38, IDC_CONTENT_CONTEXT_CUT},
195 {39, IDC_CONTENT_CONTEXT_COPY},
196 {40, IDC_CONTENT_CONTEXT_PASTE},
197 {41, IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE},
198 {42, IDC_CONTENT_CONTEXT_DELETE},
199 {43, IDC_CONTENT_CONTEXT_SELECTALL},
200 {44, IDC_CONTENT_CONTEXT_SEARCHWEBFOR},
201 {45, IDC_CONTENT_CONTEXT_GOTOURL},
202 {46, IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS},
203 {47, IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS},
204 {48, IDC_CONTENT_CONTEXT_ADDSEARCHENGINE},
205 {52, IDC_CONTENT_CONTEXT_OPENLINKWITH},
206 {53, IDC_CHECK_SPELLING_WHILE_TYPING},
207 {54, IDC_SPELLCHECK_MENU},
208 {55, IDC_CONTENT_CONTEXT_SPELLING_TOGGLE},
209 {56, IDC_SPELLCHECK_LANGUAGES_FIRST},
210 {57, IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE},
211 {58, IDC_SPELLCHECK_SUGGESTION_0},
212 {59, IDC_SPELLCHECK_ADD_TO_DICTIONARY},
213 {60, IDC_SPELLPANEL_TOGGLE},
214 {61, IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB},
215 {62, IDC_WRITING_DIRECTION_MENU},
216 {63, IDC_WRITING_DIRECTION_DEFAULT},
217 {64, IDC_WRITING_DIRECTION_LTR},
218 {65, IDC_WRITING_DIRECTION_RTL},
219 // Add new items here and use |enum_id| from the next line.
220 {66, 0}, // Must be the last. Increment |enum_id| when new IDC was added.
223 // Collapses large ranges of ids before looking for UMA enum.
224 int CollapseCommandsForUMA(int id) {
225 DCHECK(!RenderViewContextMenu::IsContentCustomCommandId(id));
226 DCHECK(!ContextMenuMatcher::IsExtensionsCustomCommandId(id));
228 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST &&
229 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) {
230 return IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST;
233 if (id >= IDC_SPELLCHECK_LANGUAGES_FIRST &&
234 id <= IDC_SPELLCHECK_LANGUAGES_LAST) {
235 return IDC_SPELLCHECK_LANGUAGES_FIRST;
238 if (id >= IDC_SPELLCHECK_SUGGESTION_0 &&
239 id <= IDC_SPELLCHECK_SUGGESTION_LAST) {
240 return IDC_SPELLCHECK_SUGGESTION_0;
243 return id;
246 // Returns UMA enum value for command specified by |id| or -1 if not found.
247 int FindUMAEnumValueForCommand(int id) {
248 if (RenderViewContextMenu::IsContentCustomCommandId(id))
249 return 0;
251 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
252 return 1;
254 id = CollapseCommandsForUMA(id);
255 const size_t kMappingSize = arraysize(kUmaEnumToControlId);
256 for (size_t i = 0; i < kMappingSize; ++i) {
257 if (kUmaEnumToControlId[i].control_id == id) {
258 return kUmaEnumToControlId[i].enum_id;
261 return -1;
264 // Usually a new tab is expected where this function is used,
265 // however users should be able to open a tab in background
266 // or in a new window.
267 WindowOpenDisposition ForceNewTabDispositionFromEventFlags(
268 int event_flags) {
269 WindowOpenDisposition disposition =
270 ui::DispositionFromEventFlags(event_flags);
271 return disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition;
274 // Helper function to escape "&" as "&&".
275 void EscapeAmpersands(base::string16* text) {
276 base::ReplaceChars(*text, base::ASCIIToUTF16("&"), base::ASCIIToUTF16("&&"),
277 text);
280 // Returns the preference of the profile represented by the |context|.
281 PrefService* GetPrefs(content::BrowserContext* context) {
282 return user_prefs::UserPrefs::Get(context);
285 bool ExtensionPatternMatch(const extensions::URLPatternSet& patterns,
286 const GURL& url) {
287 // No patterns means no restriction, so that implicitly matches.
288 if (patterns.is_empty())
289 return true;
290 return patterns.MatchesURL(url);
293 const GURL& GetDocumentURL(const content::ContextMenuParams& params) {
294 return params.frame_url.is_empty() ? params.page_url : params.frame_url;
297 content::Referrer CreateSaveAsReferrer(
298 const GURL& url,
299 const content::ContextMenuParams& params) {
300 const GURL& referring_url = GetDocumentURL(params);
301 return content::Referrer::SanitizeForRequest(
302 url,
303 content::Referrer(referring_url.GetAsReferrer(), params.referrer_policy));
306 bool g_custom_id_ranges_initialized = false;
308 const int kSpellcheckRadioGroup = 1;
310 } // namespace
312 // static
313 bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) {
314 return url.SchemeIs(content::kChromeDevToolsScheme);
317 // static
318 bool RenderViewContextMenu::IsInternalResourcesURL(const GURL& url) {
319 if (!url.SchemeIs(content::kChromeUIScheme))
320 return false;
321 return url.host() == chrome::kChromeUISyncResourcesHost;
324 RenderViewContextMenu::RenderViewContextMenu(
325 content::RenderFrameHost* render_frame_host,
326 const content::ContextMenuParams& params)
327 : RenderViewContextMenuBase(render_frame_host, params),
328 extension_items_(browser_context_,
329 this,
330 &menu_model_,
331 base::Bind(MenuItemMatchesParams, params_)),
332 protocol_handler_submenu_model_(this),
333 protocol_handler_registry_(
334 ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())) {
335 if (!g_custom_id_ranges_initialized) {
336 g_custom_id_ranges_initialized = true;
337 SetContentCustomCommandIdRange(IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
338 IDC_CONTENT_CONTEXT_CUSTOM_LAST);
340 set_content_type(ContextMenuContentTypeFactory::Create(
341 source_web_contents_, params));
344 RenderViewContextMenu::~RenderViewContextMenu() {
347 // Menu construction functions -------------------------------------------------
349 #if defined(ENABLE_EXTENSIONS)
350 // static
351 bool RenderViewContextMenu::ExtensionContextAndPatternMatch(
352 const content::ContextMenuParams& params,
353 const MenuItem::ContextList& contexts,
354 const extensions::URLPatternSet& target_url_patterns) {
355 const bool has_link = !params.link_url.is_empty();
356 const bool has_selection = !params.selection_text.empty();
357 const bool in_frame = !params.frame_url.is_empty();
359 if (contexts.Contains(MenuItem::ALL) ||
360 (has_selection && contexts.Contains(MenuItem::SELECTION)) ||
361 (params.is_editable && contexts.Contains(MenuItem::EDITABLE)) ||
362 (in_frame && contexts.Contains(MenuItem::FRAME)))
363 return true;
365 if (has_link && contexts.Contains(MenuItem::LINK) &&
366 ExtensionPatternMatch(target_url_patterns, params.link_url))
367 return true;
369 switch (params.media_type) {
370 case WebContextMenuData::MediaTypeImage:
371 if (contexts.Contains(MenuItem::IMAGE) &&
372 ExtensionPatternMatch(target_url_patterns, params.src_url))
373 return true;
374 break;
376 case WebContextMenuData::MediaTypeVideo:
377 if (contexts.Contains(MenuItem::VIDEO) &&
378 ExtensionPatternMatch(target_url_patterns, params.src_url))
379 return true;
380 break;
382 case WebContextMenuData::MediaTypeAudio:
383 if (contexts.Contains(MenuItem::AUDIO) &&
384 ExtensionPatternMatch(target_url_patterns, params.src_url))
385 return true;
386 break;
388 default:
389 break;
392 // PAGE is the least specific context, so we only examine that if none of the
393 // other contexts apply (except for FRAME, which is included in PAGE for
394 // backwards compatibility).
395 if (!has_link && !has_selection && !params.is_editable &&
396 params.media_type == WebContextMenuData::MediaTypeNone &&
397 contexts.Contains(MenuItem::PAGE))
398 return true;
400 return false;
403 // static
404 bool RenderViewContextMenu::MenuItemMatchesParams(
405 const content::ContextMenuParams& params,
406 const extensions::MenuItem* item) {
407 bool match = ExtensionContextAndPatternMatch(params, item->contexts(),
408 item->target_url_patterns());
409 if (!match)
410 return false;
412 const GURL& document_url = GetDocumentURL(params);
413 return ExtensionPatternMatch(item->document_url_patterns(), document_url);
416 void RenderViewContextMenu::AppendAllExtensionItems() {
417 extension_items_.Clear();
418 ExtensionService* service =
419 extensions::ExtensionSystem::Get(browser_context_)->extension_service();
420 if (!service)
421 return; // In unit-tests, we may not have an ExtensionService.
423 MenuManager* menu_manager = MenuManager::Get(browser_context_);
424 if (!menu_manager)
425 return;
427 base::string16 printable_selection_text = PrintableSelectionText();
428 EscapeAmpersands(&printable_selection_text);
430 // Get a list of extension id's that have context menu items, and sort by the
431 // top level context menu title of the extension.
432 std::set<MenuItem::ExtensionKey> ids = menu_manager->ExtensionIds();
433 std::vector<base::string16> sorted_menu_titles;
434 std::map<base::string16, std::string> map_ids;
435 for (std::set<MenuItem::ExtensionKey>::iterator iter = ids.begin();
436 iter != ids.end();
437 ++iter) {
438 const Extension* extension =
439 service->GetExtensionById(iter->extension_id, false);
440 // Platform apps have their context menus created directly in
441 // AppendPlatformAppItems.
442 if (extension && !extension->is_platform_app()) {
443 base::string16 menu_title = extension_items_.GetTopLevelContextMenuTitle(
444 *iter, printable_selection_text);
445 map_ids[menu_title] = iter->extension_id;
446 sorted_menu_titles.push_back(menu_title);
449 if (sorted_menu_titles.empty())
450 return;
452 const std::string app_locale = g_browser_process->GetApplicationLocale();
453 l10n_util::SortStrings16(app_locale, &sorted_menu_titles);
455 int index = 0;
456 for (size_t i = 0; i < sorted_menu_titles.size(); ++i) {
457 const std::string& id = map_ids[sorted_menu_titles[i]];
458 const MenuItem::ExtensionKey extension_key(id);
459 extension_items_.AppendExtensionItems(extension_key,
460 printable_selection_text,
461 &index,
462 false); // is_action_menu
466 void RenderViewContextMenu::AppendCurrentExtensionItems() {
467 // Avoid appending extension related items when |extension| is null.
468 // For Panel, this happens when the panel is navigated to a url outside of the
469 // extension's package.
470 const Extension* extension = GetExtension();
471 if (extension) {
472 // Only add extension items from this extension.
473 int index = 0;
474 const MenuItem::ExtensionKey key(
475 extension->id(),
476 extensions::WebViewGuest::GetViewInstanceId(source_web_contents_));
477 extension_items_.AppendExtensionItems(key,
478 PrintableSelectionText(),
479 &index,
480 false); // is_action_menu
483 #endif // defined(ENABLE_EXTENSIONS)
485 void RenderViewContextMenu::InitMenu() {
486 RenderViewContextMenuBase::InitMenu();
488 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE))
489 AppendPageItems();
491 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_FRAME)) {
492 // Merge in frame items with page items if we clicked within a frame that
493 // needs them.
494 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
495 AppendFrameItems();
498 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_LINK)) {
499 AppendLinkItems();
500 if (params_.media_type != WebContextMenuData::MediaTypeNone)
501 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
504 if (content_type_->SupportsGroup(
505 ContextMenuContentType::ITEM_GROUP_MEDIA_IMAGE)) {
506 AppendImageItems();
509 if (content_type_->SupportsGroup(
510 ContextMenuContentType::ITEM_GROUP_SEARCHWEBFORIMAGE)) {
511 AppendSearchWebForImageItems();
514 if (content_type_->SupportsGroup(
515 ContextMenuContentType::ITEM_GROUP_MEDIA_VIDEO)) {
516 AppendVideoItems();
519 if (content_type_->SupportsGroup(
520 ContextMenuContentType::ITEM_GROUP_MEDIA_AUDIO)) {
521 AppendAudioItems();
524 if (content_type_->SupportsGroup(
525 ContextMenuContentType::ITEM_GROUP_MEDIA_CANVAS)) {
526 AppendCanvasItems();
529 if (content_type_->SupportsGroup(
530 ContextMenuContentType::ITEM_GROUP_MEDIA_PLUGIN)) {
531 AppendPluginItems();
534 // ITEM_GROUP_MEDIA_FILE has no specific items.
536 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_EDITABLE))
537 AppendEditableItems();
539 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_COPY)) {
540 DCHECK(!content_type_->SupportsGroup(
541 ContextMenuContentType::ITEM_GROUP_EDITABLE));
542 AppendCopyItem();
545 if (content_type_->SupportsGroup(
546 ContextMenuContentType::ITEM_GROUP_SEARCH_PROVIDER)) {
547 AppendSearchProvider();
550 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT))
551 AppendPrintItem();
553 if (content_type_->SupportsGroup(
554 ContextMenuContentType::ITEM_GROUP_MEDIA_PLUGIN)) {
555 AppendRotationItems();
558 if (content_type_->SupportsGroup(
559 ContextMenuContentType::ITEM_GROUP_ALL_EXTENSION)) {
560 DCHECK(!content_type_->SupportsGroup(
561 ContextMenuContentType::ITEM_GROUP_CURRENT_EXTENSION));
562 AppendAllExtensionItems();
565 if (content_type_->SupportsGroup(
566 ContextMenuContentType::ITEM_GROUP_CURRENT_EXTENSION)) {
567 DCHECK(!content_type_->SupportsGroup(
568 ContextMenuContentType::ITEM_GROUP_ALL_EXTENSION));
569 AppendCurrentExtensionItems();
572 if (content_type_->SupportsGroup(
573 ContextMenuContentType::ITEM_GROUP_DEVELOPER)) {
574 AppendDeveloperItems();
577 if (content_type_->SupportsGroup(
578 ContextMenuContentType::ITEM_GROUP_DEVTOOLS_UNPACKED_EXT)) {
579 AppendDevtoolsForUnpackedExtensions();
582 if (content_type_->SupportsGroup(
583 ContextMenuContentType::ITEM_GROUP_PRINT_PREVIEW)) {
584 AppendPrintPreviewItems();
588 Profile* RenderViewContextMenu::GetProfile() {
589 return Profile::FromBrowserContext(browser_context_);
592 void RenderViewContextMenu::RecordUsedItem(int id) {
593 int enum_id = FindUMAEnumValueForCommand(id);
594 if (enum_id != -1) {
595 const size_t kMappingSize = arraysize(kUmaEnumToControlId);
596 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Used", enum_id,
597 kUmaEnumToControlId[kMappingSize - 1].enum_id);
598 } else {
599 NOTREACHED() << "Update kUmaEnumToControlId. Unhanded IDC: " << id;
603 void RenderViewContextMenu::RecordShownItem(int id) {
604 int enum_id = FindUMAEnumValueForCommand(id);
605 if (enum_id != -1) {
606 const size_t kMappingSize = arraysize(kUmaEnumToControlId);
607 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Shown", enum_id,
608 kUmaEnumToControlId[kMappingSize - 1].enum_id);
609 } else {
610 // Just warning here. It's harder to maintain list of all possibly
611 // visible items than executable items.
612 DLOG(ERROR) << "Update kUmaEnumToControlId. Unhanded IDC: " << id;
616 #if defined(ENABLE_PLUGINS)
617 void RenderViewContextMenu::HandleAuthorizeAllPlugins() {
618 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
619 source_web_contents_, false, std::string());
621 #endif
623 void RenderViewContextMenu::AppendPrintPreviewItems() {
624 #if defined(ENABLE_PRINT_PREVIEW)
625 if (!print_preview_menu_observer_.get()) {
626 print_preview_menu_observer_.reset(
627 new PrintPreviewContextMenuObserver(source_web_contents_));
630 observers_.AddObserver(print_preview_menu_observer_.get());
631 #endif
634 const Extension* RenderViewContextMenu::GetExtension() const {
635 return extensions::ProcessManager::Get(browser_context_)
636 ->GetExtensionForRenderViewHost(
637 source_web_contents_->GetRenderViewHost());
640 void RenderViewContextMenu::AppendDeveloperItems() {
641 // Show Inspect Element in DevTools itself only in case of the debug
642 // devtools build.
643 bool show_developer_items = !IsDevToolsURL(params_.page_url);
645 #if defined(DEBUG_DEVTOOLS)
646 show_developer_items = true;
647 #endif
649 if (!show_developer_items)
650 return;
652 // In the DevTools popup menu, "developer items" is normally the only
653 // section, so omit the separator there.
654 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
655 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_INSPECTELEMENT,
656 IDS_CONTENT_CONTEXT_INSPECTELEMENT);
659 void RenderViewContextMenu::AppendDevtoolsForUnpackedExtensions() {
660 // Add a separator if there are any items already in the menu.
661 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
663 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP,
664 IDS_CONTENT_CONTEXT_RELOAD_PACKAGED_APP);
665 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP,
666 IDS_CONTENT_CONTEXT_RESTART_APP);
667 AppendDeveloperItems();
668 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE,
669 IDS_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE);
672 void RenderViewContextMenu::AppendLinkItems() {
673 if (!params_.link_url.is_empty()) {
674 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB,
675 IDS_CONTENT_CONTEXT_OPENLINKNEWTAB);
676 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW,
677 IDS_CONTENT_CONTEXT_OPENLINKNEWWINDOW);
678 if (params_.link_url.is_valid()) {
679 AppendProtocolHandlerSubMenu();
682 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD,
683 IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD);
684 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVELINKAS,
685 IDS_CONTENT_CONTEXT_SAVELINKAS);
688 menu_model_.AddItemWithStringId(
689 IDC_CONTENT_CONTEXT_COPYLINKLOCATION,
690 params_.link_url.SchemeIs(url::kMailToScheme) ?
691 IDS_CONTENT_CONTEXT_COPYEMAILADDRESS :
692 IDS_CONTENT_CONTEXT_COPYLINKLOCATION);
695 void RenderViewContextMenu::AppendImageItems() {
696 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEIMAGEAS,
697 IDS_CONTENT_CONTEXT_SAVEIMAGEAS);
698 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGELOCATION,
699 IDS_CONTENT_CONTEXT_COPYIMAGELOCATION);
700 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGE,
701 IDS_CONTENT_CONTEXT_COPYIMAGE);
702 DataReductionProxyChromeSettings* settings =
703 DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
704 browser_context_);
705 if (settings && settings->CanUseDataReductionProxy(params_.src_url)) {
706 menu_model_.AddItemWithStringId(
707 IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB,
708 IDS_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB);
709 } else {
710 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB,
711 IDS_CONTENT_CONTEXT_OPENIMAGENEWTAB);
715 void RenderViewContextMenu::AppendSearchWebForImageItems() {
716 TemplateURLService* service =
717 TemplateURLServiceFactory::GetForProfile(GetProfile());
718 const TemplateURL* const default_provider =
719 service->GetDefaultSearchProvider();
720 if (params_.has_image_contents && default_provider &&
721 !default_provider->image_url().empty() &&
722 default_provider->image_url_ref().IsValid(service->search_terms_data())) {
723 menu_model_.AddItem(
724 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE,
725 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFORIMAGE,
726 default_provider->short_name()));
730 void RenderViewContextMenu::AppendAudioItems() {
731 AppendMediaItems();
732 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
733 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS,
734 IDS_CONTENT_CONTEXT_SAVEAUDIOAS);
735 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION,
736 IDS_CONTENT_CONTEXT_COPYAUDIOLOCATION);
737 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENAVNEWTAB,
738 IDS_CONTENT_CONTEXT_OPENAUDIONEWTAB);
741 void RenderViewContextMenu::AppendCanvasItems() {
742 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEIMAGEAS,
743 IDS_CONTENT_CONTEXT_SAVEIMAGEAS);
744 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGE,
745 IDS_CONTENT_CONTEXT_COPYIMAGE);
748 void RenderViewContextMenu::AppendVideoItems() {
749 AppendMediaItems();
750 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
751 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS,
752 IDS_CONTENT_CONTEXT_SAVEVIDEOAS);
753 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION,
754 IDS_CONTENT_CONTEXT_COPYVIDEOLOCATION);
755 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENAVNEWTAB,
756 IDS_CONTENT_CONTEXT_OPENVIDEONEWTAB);
759 void RenderViewContextMenu::AppendMediaItems() {
760 int media_flags = params_.media_flags;
762 menu_model_.AddItemWithStringId(
763 IDC_CONTENT_CONTEXT_PLAYPAUSE,
764 media_flags & WebContextMenuData::MediaPaused ?
765 IDS_CONTENT_CONTEXT_PLAY :
766 IDS_CONTENT_CONTEXT_PAUSE);
768 menu_model_.AddItemWithStringId(
769 IDC_CONTENT_CONTEXT_MUTE,
770 media_flags & WebContextMenuData::MediaMuted ?
771 IDS_CONTENT_CONTEXT_UNMUTE :
772 IDS_CONTENT_CONTEXT_MUTE);
774 menu_model_.AddCheckItemWithStringId(IDC_CONTENT_CONTEXT_LOOP,
775 IDS_CONTENT_CONTEXT_LOOP);
776 menu_model_.AddCheckItemWithStringId(IDC_CONTENT_CONTEXT_CONTROLS,
777 IDS_CONTENT_CONTEXT_CONTROLS);
780 void RenderViewContextMenu::AppendPluginItems() {
781 if (params_.page_url == params_.src_url ||
782 extensions::GuestViewBase::IsGuest(source_web_contents_)) {
783 // Full page plugin, so show page menu items.
784 if (params_.link_url.is_empty() && params_.selection_text.empty())
785 AppendPageItems();
786 } else {
787 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS,
788 IDS_CONTENT_CONTEXT_SAVEPAGEAS);
789 // The "Print" menu item should always be included for plugins. If
790 // content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT)
791 // is true the item will be added inside AppendPrintItem(). Otherwise we
792 // add "Print" here.
793 if (!content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT))
794 menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT);
798 void RenderViewContextMenu::AppendPageItems() {
799 menu_model_.AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
800 menu_model_.AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
801 menu_model_.AddItemWithStringId(IDC_RELOAD, IDS_CONTENT_CONTEXT_RELOAD);
802 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
803 menu_model_.AddItemWithStringId(IDC_SAVE_PAGE,
804 IDS_CONTENT_CONTEXT_SAVEPAGEAS);
805 menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT);
807 if (TranslateService::IsTranslatableURL(params_.page_url)) {
808 std::string locale = g_browser_process->GetApplicationLocale();
809 locale = translate::TranslateDownloadManager::GetLanguageCode(locale);
810 base::string16 language =
811 l10n_util::GetDisplayNameForLocale(locale, locale, true);
812 menu_model_.AddItem(
813 IDC_CONTENT_CONTEXT_TRANSLATE,
814 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_TRANSLATE, language));
817 menu_model_.AddItemWithStringId(IDC_VIEW_SOURCE,
818 IDS_CONTENT_CONTEXT_VIEWPAGESOURCE);
819 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_VIEWPAGEINFO,
820 IDS_CONTENT_CONTEXT_VIEWPAGEINFO);
823 void RenderViewContextMenu::AppendFrameItems() {
824 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_RELOADFRAME,
825 IDS_CONTENT_CONTEXT_RELOADFRAME);
826 // These two menu items have yet to be implemented.
827 // http://code.google.com/p/chromium/issues/detail?id=11827
828 // IDS_CONTENT_CONTEXT_SAVEFRAMEAS
829 // IDS_CONTENT_CONTEXT_PRINTFRAME
830 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE,
831 IDS_CONTENT_CONTEXT_VIEWFRAMESOURCE);
832 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_VIEWFRAMEINFO,
833 IDS_CONTENT_CONTEXT_VIEWFRAMEINFO);
836 void RenderViewContextMenu::AppendCopyItem() {
837 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPY,
838 IDS_CONTENT_CONTEXT_COPY);
841 void RenderViewContextMenu::AppendPrintItem() {
842 if (GetPrefs(browser_context_)->GetBoolean(prefs::kPrintingEnabled) &&
843 (params_.media_type == WebContextMenuData::MediaTypeNone ||
844 params_.media_flags & WebContextMenuData::MediaCanPrint)) {
845 menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT);
849 void RenderViewContextMenu::AppendRotationItems() {
850 if (params_.media_flags & WebContextMenuData::MediaCanRotate) {
851 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
852 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_ROTATECW,
853 IDS_CONTENT_CONTEXT_ROTATECW);
854 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_ROTATECCW,
855 IDS_CONTENT_CONTEXT_ROTATECCW);
859 void RenderViewContextMenu::AppendSearchProvider() {
860 DCHECK(browser_context_);
862 base::TrimWhitespace(params_.selection_text, base::TRIM_ALL,
863 &params_.selection_text);
864 if (params_.selection_text.empty())
865 return;
867 base::ReplaceChars(params_.selection_text, AutocompleteMatch::kInvalidChars,
868 base::ASCIIToUTF16(" "), &params_.selection_text);
870 AutocompleteMatch match;
871 AutocompleteClassifierFactory::GetForProfile(GetProfile())->Classify(
872 params_.selection_text,
873 false,
874 false,
875 metrics::OmniboxEventProto::INVALID_SPEC,
876 &match,
877 NULL);
878 selection_navigation_url_ = match.destination_url;
879 if (!selection_navigation_url_.is_valid())
880 return;
882 base::string16 printable_selection_text = PrintableSelectionText();
883 EscapeAmpersands(&printable_selection_text);
885 if (AutocompleteMatch::IsSearchType(match.type)) {
886 const TemplateURL* const default_provider =
887 TemplateURLServiceFactory::GetForProfile(GetProfile())
888 ->GetDefaultSearchProvider();
889 if (!default_provider)
890 return;
891 menu_model_.AddItem(
892 IDC_CONTENT_CONTEXT_SEARCHWEBFOR,
893 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFOR,
894 default_provider->short_name(),
895 printable_selection_text));
896 } else {
897 if ((selection_navigation_url_ != params_.link_url) &&
898 ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
899 selection_navigation_url_.scheme())) {
900 menu_model_.AddItem(
901 IDC_CONTENT_CONTEXT_GOTOURL,
902 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_GOTOURL,
903 printable_selection_text));
908 void RenderViewContextMenu::AppendEditableItems() {
909 const bool use_spellcheck_and_search = !chrome::IsRunningInForcedAppMode();
911 if (use_spellcheck_and_search)
912 AppendSpellingSuggestionsSubMenu();
914 if (!IsDevToolsURL(params_.page_url)) {
915 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_UNDO,
916 IDS_CONTENT_CONTEXT_UNDO);
917 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_REDO,
918 IDS_CONTENT_CONTEXT_REDO);
919 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
922 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_CUT,
923 IDS_CONTENT_CONTEXT_CUT);
924 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPY,
925 IDS_CONTENT_CONTEXT_COPY);
926 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_PASTE,
927 IDS_CONTENT_CONTEXT_PASTE);
928 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE,
929 IDS_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE);
930 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_DELETE,
931 IDS_CONTENT_CONTEXT_DELETE);
932 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
934 if (use_spellcheck_and_search && !params_.keyword_url.is_empty()) {
935 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_ADDSEARCHENGINE,
936 IDS_CONTENT_CONTEXT_ADDSEARCHENGINE);
937 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
940 if (use_spellcheck_and_search)
941 AppendSpellcheckOptionsSubMenu();
942 AppendPlatformEditableItems();
944 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
945 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SELECTALL,
946 IDS_CONTENT_CONTEXT_SELECTALL);
949 void RenderViewContextMenu::AppendSpellingSuggestionsSubMenu() {
950 if (!spelling_menu_observer_.get())
951 spelling_menu_observer_.reset(new SpellingMenuObserver(this));
952 observers_.AddObserver(spelling_menu_observer_.get());
953 spelling_menu_observer_->InitMenu(params_);
956 void RenderViewContextMenu::AppendSpellcheckOptionsSubMenu() {
957 if (!spellchecker_submenu_observer_.get()) {
958 spellchecker_submenu_observer_.reset(new SpellCheckerSubMenuObserver(
959 this, this, kSpellcheckRadioGroup));
961 spellchecker_submenu_observer_->InitMenu(params_);
962 observers_.AddObserver(spellchecker_submenu_observer_.get());
965 void RenderViewContextMenu::AppendProtocolHandlerSubMenu() {
966 const ProtocolHandlerRegistry::ProtocolHandlerList handlers =
967 GetHandlersForLinkUrl();
968 if (handlers.empty())
969 return;
970 size_t max = IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST -
971 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST;
972 for (size_t i = 0; i < handlers.size() && i <= max; i++) {
973 protocol_handler_submenu_model_.AddItem(
974 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST + i,
975 base::UTF8ToUTF16(handlers[i].url().host()));
977 protocol_handler_submenu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
978 protocol_handler_submenu_model_.AddItem(
979 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS,
980 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH_CONFIGURE));
982 menu_model_.AddSubMenu(
983 IDC_CONTENT_CONTEXT_OPENLINKWITH,
984 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH),
985 &protocol_handler_submenu_model_);
988 // Menu delegate functions -----------------------------------------------------
990 bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
992 bool enabled = false;
993 if (RenderViewContextMenuBase::IsCommandIdKnown(id, &enabled))
994 return enabled;
997 CoreTabHelper* core_tab_helper =
998 CoreTabHelper::FromWebContents(source_web_contents_);
999 int content_restrictions = 0;
1000 if (core_tab_helper)
1001 content_restrictions = core_tab_helper->content_restrictions();
1002 if (id == IDC_PRINT && (content_restrictions & CONTENT_RESTRICTION_PRINT))
1003 return false;
1005 if (id == IDC_SAVE_PAGE &&
1006 (content_restrictions & CONTENT_RESTRICTION_SAVE)) {
1007 return false;
1010 PrefService* prefs = GetPrefs(browser_context_);
1012 // Allow Spell Check language items on sub menu for text area context menu.
1013 if ((id >= IDC_SPELLCHECK_LANGUAGES_FIRST) &&
1014 (id < IDC_SPELLCHECK_LANGUAGES_LAST)) {
1015 return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck);
1018 // Extension items.
1019 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
1020 return extension_items_.IsCommandIdEnabled(id);
1022 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST &&
1023 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) {
1024 return true;
1027 IncognitoModePrefs::Availability incognito_avail =
1028 IncognitoModePrefs::GetAvailability(prefs);
1029 switch (id) {
1030 case IDC_BACK:
1031 return embedder_web_contents_->GetController().CanGoBack();
1033 case IDC_FORWARD:
1034 return embedder_web_contents_->GetController().CanGoForward();
1036 case IDC_RELOAD: {
1037 CoreTabHelper* core_tab_helper =
1038 CoreTabHelper::FromWebContents(embedder_web_contents_);
1039 if (!core_tab_helper)
1040 return false;
1042 CoreTabHelperDelegate* core_delegate = core_tab_helper->delegate();
1043 return !core_delegate ||
1044 core_delegate->CanReloadContents(embedder_web_contents_);
1047 case IDC_VIEW_SOURCE:
1048 case IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE:
1049 return embedder_web_contents_->GetController().CanViewSource();
1051 case IDC_CONTENT_CONTEXT_INSPECTELEMENT:
1052 case IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE:
1053 case IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP:
1054 case IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP:
1055 return IsDevCommandEnabled(id);
1057 case IDC_CONTENT_CONTEXT_VIEWPAGEINFO:
1058 if (embedder_web_contents_->GetController().GetVisibleEntry() == NULL)
1059 return false;
1060 // Disabled if no browser is associated (e.g. desktop notifications).
1061 if (chrome::FindBrowserWithWebContents(embedder_web_contents_) == NULL)
1062 return false;
1063 return true;
1065 case IDC_CONTENT_CONTEXT_TRANSLATE: {
1066 ChromeTranslateClient* chrome_translate_client =
1067 ChromeTranslateClient::FromWebContents(embedder_web_contents_);
1068 if (!chrome_translate_client)
1069 return false;
1070 std::string original_lang =
1071 chrome_translate_client->GetLanguageState().original_language();
1072 std::string target_lang = g_browser_process->GetApplicationLocale();
1073 target_lang =
1074 translate::TranslateDownloadManager::GetLanguageCode(target_lang);
1075 // Note that we intentionally enable the menu even if the original and
1076 // target languages are identical. This is to give a way to user to
1077 // translate a page that might contains text fragments in a different
1078 // language.
1079 return ((params_.edit_flags & WebContextMenuData::CanTranslate) != 0) &&
1080 !original_lang.empty() && // Did we receive the page language yet?
1081 !chrome_translate_client->GetLanguageState().IsPageTranslated() &&
1082 !embedder_web_contents_->GetInterstitialPage() &&
1083 // There are some application locales which can't be used as a
1084 // target language for translation.
1085 translate::TranslateDownloadManager::IsSupportedLanguage(
1086 target_lang) &&
1087 // Disable on the Instant Extended NTP.
1088 !chrome::IsInstantNTP(embedder_web_contents_);
1091 case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB:
1092 case IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW:
1093 return params_.link_url.is_valid();
1095 case IDC_CONTENT_CONTEXT_COPYLINKLOCATION:
1096 return params_.unfiltered_link_url.is_valid();
1098 case IDC_CONTENT_CONTEXT_SAVELINKAS: {
1099 PrefService* local_state = g_browser_process->local_state();
1100 DCHECK(local_state);
1101 // Test if file-selection dialogs are forbidden by policy.
1102 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs))
1103 return false;
1105 return params_.link_url.is_valid() &&
1106 ProfileIOData::IsHandledProtocol(params_.link_url.scheme());
1109 case IDC_CONTENT_CONTEXT_SAVEIMAGEAS: {
1110 PrefService* local_state = g_browser_process->local_state();
1111 DCHECK(local_state);
1112 // Test if file-selection dialogs are forbidden by policy.
1113 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs))
1114 return false;
1116 return params_.has_image_contents;
1119 // The images shown in the most visited thumbnails can't be opened or
1120 // searched for conventionally.
1121 case IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB:
1122 case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB:
1123 case IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE:
1124 return params_.src_url.is_valid() &&
1125 (params_.src_url.scheme() != content::kChromeUIScheme);
1127 case IDC_CONTENT_CONTEXT_COPYIMAGE:
1128 return params_.has_image_contents;
1130 // Media control commands should all be disabled if the player is in an
1131 // error state.
1132 case IDC_CONTENT_CONTEXT_PLAYPAUSE:
1133 case IDC_CONTENT_CONTEXT_LOOP:
1134 return (params_.media_flags &
1135 WebContextMenuData::MediaInError) == 0;
1137 // Mute and unmute should also be disabled if the player has no audio.
1138 case IDC_CONTENT_CONTEXT_MUTE:
1139 return (params_.media_flags &
1140 WebContextMenuData::MediaHasAudio) != 0 &&
1141 (params_.media_flags &
1142 WebContextMenuData::MediaInError) == 0;
1144 case IDC_CONTENT_CONTEXT_CONTROLS:
1145 return (params_.media_flags &
1146 WebContextMenuData::MediaCanToggleControls) != 0;
1148 case IDC_CONTENT_CONTEXT_ROTATECW:
1149 case IDC_CONTENT_CONTEXT_ROTATECCW:
1150 return
1151 (params_.media_flags & WebContextMenuData::MediaCanRotate) != 0;
1153 case IDC_CONTENT_CONTEXT_COPYAVLOCATION:
1154 case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION:
1155 return params_.src_url.is_valid();
1157 case IDC_CONTENT_CONTEXT_SAVEAVAS: {
1158 PrefService* local_state = g_browser_process->local_state();
1159 DCHECK(local_state);
1160 // Test if file-selection dialogs are forbidden by policy.
1161 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs))
1162 return false;
1164 const GURL& url = params_.src_url;
1165 bool can_save =
1166 (params_.media_flags & WebContextMenuData::MediaCanSave) &&
1167 url.is_valid() && ProfileIOData::IsHandledProtocol(url.scheme());
1168 #if defined(ENABLE_PRINT_PREVIEW)
1169 // Do not save the preview PDF on the print preview page.
1170 can_save = can_save &&
1171 !(printing::PrintPreviewDialogController::IsPrintPreviewURL(url));
1172 #endif
1173 return can_save;
1176 case IDC_CONTENT_CONTEXT_OPENAVNEWTAB:
1177 // Currently, a media element can be opened in a new tab iff it can
1178 // be saved. So rather than duplicating the MediaCanSave flag, we rely
1179 // on that here.
1180 return !!(params_.media_flags & WebContextMenuData::MediaCanSave);
1182 case IDC_SAVE_PAGE: {
1183 CoreTabHelper* core_tab_helper =
1184 CoreTabHelper::FromWebContents(embedder_web_contents_);
1185 if (!core_tab_helper)
1186 return false;
1188 CoreTabHelperDelegate* core_delegate = core_tab_helper->delegate();
1189 if (core_delegate &&
1190 !core_delegate->CanSaveContents(embedder_web_contents_))
1191 return false;
1193 PrefService* local_state = g_browser_process->local_state();
1194 DCHECK(local_state);
1195 // Test if file-selection dialogs are forbidden by policy.
1196 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs))
1197 return false;
1199 // We save the last committed entry (which the user is looking at), as
1200 // opposed to any pending URL that hasn't committed yet.
1201 NavigationEntry* entry =
1202 embedder_web_contents_->GetController().GetLastCommittedEntry();
1203 return content::IsSavableURL(entry ? entry->GetURL() : GURL());
1206 case IDC_CONTENT_CONTEXT_RELOADFRAME:
1207 return params_.frame_url.is_valid();
1209 case IDC_CONTENT_CONTEXT_UNDO:
1210 return !!(params_.edit_flags & WebContextMenuData::CanUndo);
1212 case IDC_CONTENT_CONTEXT_REDO:
1213 return !!(params_.edit_flags & WebContextMenuData::CanRedo);
1215 case IDC_CONTENT_CONTEXT_CUT:
1216 return !!(params_.edit_flags & WebContextMenuData::CanCut);
1218 case IDC_CONTENT_CONTEXT_COPY:
1219 return !!(params_.edit_flags & WebContextMenuData::CanCopy);
1221 case IDC_CONTENT_CONTEXT_PASTE: {
1222 if (!(params_.edit_flags & WebContextMenuData::CanPaste))
1223 return false;
1225 std::vector<base::string16> types;
1226 bool ignore;
1227 ui::Clipboard::GetForCurrentThread()->ReadAvailableTypes(
1228 ui::CLIPBOARD_TYPE_COPY_PASTE, &types, &ignore);
1229 return !types.empty();
1232 case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE: {
1233 if (!(params_.edit_flags & WebContextMenuData::CanPaste))
1234 return false;
1236 return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
1237 ui::Clipboard::GetPlainTextFormatType(),
1238 ui::CLIPBOARD_TYPE_COPY_PASTE);
1241 case IDC_CONTENT_CONTEXT_DELETE:
1242 return !!(params_.edit_flags & WebContextMenuData::CanDelete);
1244 case IDC_CONTENT_CONTEXT_SELECTALL:
1245 return !!(params_.edit_flags & WebContextMenuData::CanSelectAll);
1247 case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD:
1248 return !browser_context_->IsOffTheRecord() &&
1249 params_.link_url.is_valid() &&
1250 incognito_avail != IncognitoModePrefs::DISABLED;
1252 case IDC_PRINT:
1253 return prefs->GetBoolean(prefs::kPrintingEnabled) &&
1254 (params_.media_type == WebContextMenuData::MediaTypeNone ||
1255 params_.media_flags & WebContextMenuData::MediaCanPrint);
1257 case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
1258 case IDC_CONTENT_CONTEXT_GOTOURL:
1259 case IDC_SPELLPANEL_TOGGLE:
1260 case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS:
1261 return true;
1262 case IDC_CONTENT_CONTEXT_VIEWFRAMEINFO:
1263 // Disabled if no browser is associated (e.g. desktop notifications).
1264 if (chrome::FindBrowserWithWebContents(source_web_contents_) == NULL)
1265 return false;
1266 return true;
1268 case IDC_CHECK_SPELLING_WHILE_TYPING:
1269 return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck);
1271 #if !defined(OS_MACOSX) && defined(OS_POSIX)
1272 // TODO(suzhe): this should not be enabled for password fields.
1273 case IDC_INPUT_METHODS_MENU:
1274 return true;
1275 #endif
1277 case IDC_CONTENT_CONTEXT_ADDSEARCHENGINE:
1278 return !params_.keyword_url.is_empty();
1280 case IDC_SPELLCHECK_MENU:
1281 return true;
1283 case IDC_CONTENT_CONTEXT_OPENLINKWITH:
1284 return true;
1286 case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS:
1287 return true;
1289 default:
1290 NOTREACHED();
1291 return false;
1295 bool RenderViewContextMenu::IsCommandIdChecked(int id) const {
1296 if (RenderViewContextMenuBase::IsCommandIdChecked(id))
1297 return true;
1299 // See if the video is set to looping.
1300 if (id == IDC_CONTENT_CONTEXT_LOOP)
1301 return (params_.media_flags & WebContextMenuData::MediaLoop) != 0;
1303 if (id == IDC_CONTENT_CONTEXT_CONTROLS)
1304 return (params_.media_flags & WebContextMenuData::MediaControls) != 0;
1306 // Extension items.
1307 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
1308 return extension_items_.IsCommandIdChecked(id);
1310 return false;
1313 void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
1314 RenderViewContextMenuBase::ExecuteCommand(id, event_flags);
1315 if (command_executed_)
1316 return;
1317 command_executed_ = true;
1319 RenderFrameHost* render_frame_host = GetRenderFrameHost();
1321 // Process extension menu items.
1322 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) {
1323 extension_items_.ExecuteCommand(id, source_web_contents_, params_);
1324 return;
1327 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST &&
1328 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) {
1329 ProtocolHandlerRegistry::ProtocolHandlerList handlers =
1330 GetHandlersForLinkUrl();
1331 if (handlers.empty())
1332 return;
1334 content::RecordAction(
1335 UserMetricsAction("RegisterProtocolHandler.ContextMenu_Open"));
1336 int handlerIndex = id - IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST;
1337 WindowOpenDisposition disposition =
1338 ForceNewTabDispositionFromEventFlags(event_flags);
1339 OpenURL(handlers[handlerIndex].TranslateUrl(params_.link_url),
1340 GetDocumentURL(params_),
1341 disposition,
1342 ui::PAGE_TRANSITION_LINK);
1343 return;
1346 switch (id) {
1347 case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB: {
1348 Browser* browser =
1349 chrome::FindBrowserWithWebContents(source_web_contents_);
1350 OpenURL(params_.link_url,
1351 GetDocumentURL(params_),
1352 !browser || browser->is_app() ?
1353 NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB,
1354 ui::PAGE_TRANSITION_LINK);
1355 break;
1357 case IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW:
1358 OpenURL(params_.link_url,
1359 GetDocumentURL(params_),
1360 NEW_WINDOW,
1361 ui::PAGE_TRANSITION_LINK);
1362 break;
1364 case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD:
1365 OpenURL(params_.link_url, GURL(), OFF_THE_RECORD,
1366 ui::PAGE_TRANSITION_LINK);
1367 break;
1369 case IDC_CONTENT_CONTEXT_SAVELINKAS: {
1370 RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
1371 const GURL& url = params_.link_url;
1372 content::Referrer referrer = CreateSaveAsReferrer(url, params_);
1373 DownloadManager* dlm =
1374 BrowserContext::GetDownloadManager(browser_context_);
1375 scoped_ptr<DownloadUrlParameters> dl_params(
1376 DownloadUrlParameters::FromWebContents(source_web_contents_, url));
1377 dl_params->set_referrer(referrer);
1378 dl_params->set_referrer_encoding(params_.frame_charset);
1379 dl_params->set_suggested_name(params_.suggested_filename);
1380 dl_params->set_prompt(true);
1381 dlm->DownloadUrl(dl_params.Pass());
1382 break;
1385 case IDC_CONTENT_CONTEXT_SAVEAVAS:
1386 case IDC_CONTENT_CONTEXT_SAVEIMAGEAS: {
1387 bool is_large_data_url = params_.has_image_contents &&
1388 params_.src_url.is_empty();
1389 if (params_.media_type == WebContextMenuData::MediaTypeCanvas ||
1390 (params_.media_type == WebContextMenuData::MediaTypeImage &&
1391 is_large_data_url)) {
1392 source_web_contents_->GetRenderViewHost()->SaveImageAt(
1393 params_.x, params_.y);
1394 } else {
1395 RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
1396 const GURL& url = params_.src_url;
1397 content::Referrer referrer = CreateSaveAsReferrer(url, params_);
1399 std::string headers;
1400 DataReductionProxyChromeSettings* settings =
1401 DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
1402 browser_context_);
1403 if (params_.media_type == WebContextMenuData::MediaTypeImage &&
1404 settings && settings->CanUseDataReductionProxy(params_.src_url)) {
1405 headers = data_reduction_proxy::kDataReductionPassThroughHeader;
1408 source_web_contents_->SaveFrameWithHeaders(url, referrer, headers);
1410 break;
1413 case IDC_CONTENT_CONTEXT_COPYLINKLOCATION:
1414 WriteURLToClipboard(params_.unfiltered_link_url);
1415 break;
1417 case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION:
1418 case IDC_CONTENT_CONTEXT_COPYAVLOCATION:
1419 WriteURLToClipboard(params_.src_url);
1420 break;
1422 case IDC_CONTENT_CONTEXT_COPYIMAGE:
1423 CopyImageAt(params_.x, params_.y);
1424 break;
1426 case IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE:
1427 GetImageThumbnailForSearch();
1428 break;
1430 case IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB:
1431 OpenURLWithExtraHeaders(
1432 params_.src_url, GetDocumentURL(params_), NEW_BACKGROUND_TAB,
1433 ui::PAGE_TRANSITION_LINK,
1434 data_reduction_proxy::kDataReductionPassThroughHeader);
1435 break;
1437 case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB:
1438 case IDC_CONTENT_CONTEXT_OPENAVNEWTAB:
1439 OpenURL(params_.src_url,
1440 GetDocumentURL(params_),
1441 NEW_BACKGROUND_TAB,
1442 ui::PAGE_TRANSITION_LINK);
1443 break;
1445 case IDC_CONTENT_CONTEXT_PLAYPAUSE: {
1446 bool play = !!(params_.media_flags & WebContextMenuData::MediaPaused);
1447 if (play) {
1448 content::RecordAction(UserMetricsAction("MediaContextMenu_Play"));
1449 } else {
1450 content::RecordAction(UserMetricsAction("MediaContextMenu_Pause"));
1452 MediaPlayerActionAt(gfx::Point(params_.x, params_.y),
1453 WebMediaPlayerAction(
1454 WebMediaPlayerAction::Play, play));
1455 break;
1458 case IDC_CONTENT_CONTEXT_MUTE: {
1459 bool mute = !(params_.media_flags & WebContextMenuData::MediaMuted);
1460 if (mute) {
1461 content::RecordAction(UserMetricsAction("MediaContextMenu_Mute"));
1462 } else {
1463 content::RecordAction(UserMetricsAction("MediaContextMenu_Unmute"));
1465 MediaPlayerActionAt(gfx::Point(params_.x, params_.y),
1466 WebMediaPlayerAction(
1467 WebMediaPlayerAction::Mute, mute));
1468 break;
1471 case IDC_CONTENT_CONTEXT_LOOP:
1472 content::RecordAction(UserMetricsAction("MediaContextMenu_Loop"));
1473 MediaPlayerActionAt(gfx::Point(params_.x, params_.y),
1474 WebMediaPlayerAction(
1475 WebMediaPlayerAction::Loop,
1476 !IsCommandIdChecked(IDC_CONTENT_CONTEXT_LOOP)));
1477 break;
1479 case IDC_CONTENT_CONTEXT_CONTROLS:
1480 content::RecordAction(UserMetricsAction("MediaContextMenu_Controls"));
1481 MediaPlayerActionAt(
1482 gfx::Point(params_.x, params_.y),
1483 WebMediaPlayerAction(
1484 WebMediaPlayerAction::Controls,
1485 !IsCommandIdChecked(IDC_CONTENT_CONTEXT_CONTROLS)));
1486 break;
1488 case IDC_CONTENT_CONTEXT_ROTATECW:
1489 content::RecordAction(
1490 UserMetricsAction("PluginContextMenu_RotateClockwise"));
1491 PluginActionAt(
1492 gfx::Point(params_.x, params_.y),
1493 WebPluginAction(WebPluginAction::Rotate90Clockwise, true));
1494 break;
1496 case IDC_CONTENT_CONTEXT_ROTATECCW:
1497 content::RecordAction(
1498 UserMetricsAction("PluginContextMenu_RotateCounterclockwise"));
1499 PluginActionAt(
1500 gfx::Point(params_.x, params_.y),
1501 WebPluginAction(WebPluginAction::Rotate90Counterclockwise, true));
1502 break;
1504 case IDC_BACK:
1505 embedder_web_contents_->GetController().GoBack();
1506 break;
1508 case IDC_FORWARD:
1509 embedder_web_contents_->GetController().GoForward();
1510 break;
1512 case IDC_SAVE_PAGE:
1513 embedder_web_contents_->OnSavePage();
1514 break;
1516 case IDC_RELOAD:
1517 embedder_web_contents_->GetController().Reload(true);
1518 break;
1520 case IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP: {
1521 const Extension* platform_app = GetExtension();
1522 DCHECK(platform_app);
1523 DCHECK(platform_app->is_platform_app());
1525 extensions::ExtensionSystem::Get(browser_context_)
1526 ->extension_service()
1527 ->ReloadExtension(platform_app->id());
1528 break;
1531 case IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP: {
1532 const Extension* platform_app = GetExtension();
1533 DCHECK(platform_app);
1534 DCHECK(platform_app->is_platform_app());
1536 apps::AppLoadService::Get(GetProfile())
1537 ->RestartApplication(platform_app->id());
1538 break;
1541 case IDC_PRINT: {
1542 #if defined(ENABLE_PRINTING)
1543 if (params_.media_type != WebContextMenuData::MediaTypeNone) {
1544 if (render_frame_host) {
1545 render_frame_host->Send(new PrintMsg_PrintNodeUnderContextMenu(
1546 render_frame_host->GetRoutingID()));
1548 break;
1551 printing::StartPrint(
1552 source_web_contents_,
1553 GetPrefs(browser_context_)->GetBoolean(prefs::kPrintPreviewDisabled),
1554 !params_.selection_text.empty());
1555 #endif // ENABLE_PRINTING
1556 break;
1559 case IDC_VIEW_SOURCE:
1560 embedder_web_contents_->ViewSource();
1561 break;
1563 case IDC_CONTENT_CONTEXT_INSPECTELEMENT:
1564 Inspect(params_.x, params_.y);
1565 break;
1567 case IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE: {
1568 const Extension* platform_app = GetExtension();
1569 DCHECK(platform_app);
1570 DCHECK(platform_app->is_platform_app());
1572 extensions::devtools_util::InspectBackgroundPage(platform_app,
1573 GetProfile());
1574 break;
1577 case IDC_CONTENT_CONTEXT_VIEWPAGEINFO: {
1578 NavigationController* controller =
1579 &embedder_web_contents_->GetController();
1580 // Important to use GetVisibleEntry to match what's showing in the
1581 // omnibox. This may return null.
1582 NavigationEntry* nav_entry = controller->GetVisibleEntry();
1583 if (!nav_entry)
1584 return;
1585 Browser* browser =
1586 chrome::FindBrowserWithWebContents(embedder_web_contents_);
1587 chrome::ShowWebsiteSettings(browser, embedder_web_contents_,
1588 nav_entry->GetURL(), nav_entry->GetSSL());
1589 break;
1592 case IDC_CONTENT_CONTEXT_TRANSLATE: {
1593 // A translation might have been triggered by the time the menu got
1594 // selected, do nothing in that case.
1595 ChromeTranslateClient* chrome_translate_client =
1596 ChromeTranslateClient::FromWebContents(embedder_web_contents_);
1597 if (!chrome_translate_client ||
1598 chrome_translate_client->GetLanguageState().IsPageTranslated() ||
1599 chrome_translate_client->GetLanguageState().translation_pending()) {
1600 return;
1602 std::string original_lang =
1603 chrome_translate_client->GetLanguageState().original_language();
1604 std::string target_lang = g_browser_process->GetApplicationLocale();
1605 target_lang =
1606 translate::TranslateDownloadManager::GetLanguageCode(target_lang);
1607 // Since the user decided to translate for that language and site, clears
1608 // any preferences for not translating them.
1609 scoped_ptr<translate::TranslatePrefs> prefs(
1610 ChromeTranslateClient::CreateTranslatePrefs(
1611 GetPrefs(browser_context_)));
1612 prefs->UnblockLanguage(original_lang);
1613 prefs->RemoveSiteFromBlacklist(params_.page_url.HostNoBrackets());
1614 translate::TranslateManager* manager =
1615 chrome_translate_client->GetTranslateManager();
1616 DCHECK(manager);
1617 manager->TranslatePage(original_lang, target_lang, true);
1618 break;
1621 case IDC_CONTENT_CONTEXT_RELOADFRAME:
1622 // We always obey the cache here.
1623 // TODO(evanm): Perhaps we could allow shift-clicking the menu item to do
1624 // a cache-ignoring reload of the frame.
1625 source_web_contents_->ReloadFocusedFrame(false);
1626 break;
1628 case IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE:
1629 source_web_contents_->ViewFrameSource(params_.frame_url,
1630 params_.frame_page_state);
1631 break;
1633 case IDC_CONTENT_CONTEXT_VIEWFRAMEINFO: {
1634 Browser* browser = chrome::FindBrowserWithWebContents(
1635 source_web_contents_);
1636 chrome::ShowWebsiteSettings(browser, source_web_contents_,
1637 params_.frame_url, params_.security_info);
1638 break;
1641 case IDC_CONTENT_CONTEXT_UNDO:
1642 source_web_contents_->Undo();
1643 break;
1645 case IDC_CONTENT_CONTEXT_REDO:
1646 source_web_contents_->Redo();
1647 break;
1649 case IDC_CONTENT_CONTEXT_CUT:
1650 source_web_contents_->Cut();
1651 break;
1653 case IDC_CONTENT_CONTEXT_COPY:
1654 source_web_contents_->Copy();
1655 break;
1657 case IDC_CONTENT_CONTEXT_PASTE:
1658 source_web_contents_->Paste();
1659 break;
1661 case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE:
1662 source_web_contents_->PasteAndMatchStyle();
1663 break;
1665 case IDC_CONTENT_CONTEXT_DELETE:
1666 source_web_contents_->Delete();
1667 break;
1669 case IDC_CONTENT_CONTEXT_SELECTALL:
1670 source_web_contents_->SelectAll();
1671 break;
1673 case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
1674 case IDC_CONTENT_CONTEXT_GOTOURL: {
1675 WindowOpenDisposition disposition =
1676 ForceNewTabDispositionFromEventFlags(event_flags);
1677 OpenURL(selection_navigation_url_, GURL(), disposition,
1678 ui::PAGE_TRANSITION_LINK);
1679 break;
1681 case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS: {
1682 WindowOpenDisposition disposition =
1683 ForceNewTabDispositionFromEventFlags(event_flags);
1684 GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
1685 OpenURL(url, GURL(), disposition, ui::PAGE_TRANSITION_LINK);
1686 break;
1689 case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS: {
1690 content::RecordAction(
1691 UserMetricsAction("RegisterProtocolHandler.ContextMenu_Settings"));
1692 WindowOpenDisposition disposition =
1693 ForceNewTabDispositionFromEventFlags(event_flags);
1694 GURL url = chrome::GetSettingsUrl(chrome::kHandlerSettingsSubPage);
1695 OpenURL(url, GURL(), disposition, ui::PAGE_TRANSITION_LINK);
1696 break;
1699 case IDC_CONTENT_CONTEXT_ADDSEARCHENGINE: {
1700 // Make sure the model is loaded.
1701 TemplateURLService* model =
1702 TemplateURLServiceFactory::GetForProfile(GetProfile());
1703 if (!model)
1704 return;
1705 model->Load();
1707 SearchEngineTabHelper* search_engine_tab_helper =
1708 SearchEngineTabHelper::FromWebContents(source_web_contents_);
1709 if (search_engine_tab_helper &&
1710 search_engine_tab_helper->delegate()) {
1711 base::string16 keyword(TemplateURL::GenerateKeyword(params_.page_url));
1712 TemplateURLData data;
1713 data.short_name = keyword;
1714 data.SetKeyword(keyword);
1715 data.SetURL(params_.keyword_url.spec());
1716 data.favicon_url =
1717 TemplateURL::GenerateFaviconURL(params_.page_url.GetOrigin());
1718 // Takes ownership of the TemplateURL.
1719 search_engine_tab_helper->delegate()->ConfirmAddSearchProvider(
1720 new TemplateURL(data), GetProfile());
1722 break;
1725 default:
1726 NOTREACHED();
1727 break;
1731 ProtocolHandlerRegistry::ProtocolHandlerList
1732 RenderViewContextMenu::GetHandlersForLinkUrl() {
1733 ProtocolHandlerRegistry::ProtocolHandlerList handlers =
1734 protocol_handler_registry_->GetHandlersFor(params_.link_url.scheme());
1735 std::sort(handlers.begin(), handlers.end());
1736 return handlers;
1739 void RenderViewContextMenu::NotifyMenuShown() {
1740 content::NotificationService::current()->Notify(
1741 chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN,
1742 content::Source<RenderViewContextMenu>(this),
1743 content::NotificationService::NoDetails());
1746 void RenderViewContextMenu::NotifyURLOpened(
1747 const GURL& url,
1748 content::WebContents* new_contents) {
1749 RetargetingDetails details;
1750 details.source_web_contents = source_web_contents_;
1751 // Don't use GetRenderFrameHost() as it may be NULL. crbug.com/399789
1752 details.source_render_frame_id = render_frame_id_;
1753 details.target_url = url;
1754 details.target_web_contents = new_contents;
1755 details.not_yet_in_tabstrip = false;
1757 content::NotificationService::current()->Notify(
1758 chrome::NOTIFICATION_RETARGETING,
1759 content::Source<Profile>(GetProfile()),
1760 content::Details<RetargetingDetails>(&details));
1763 bool RenderViewContextMenu::IsDevCommandEnabled(int id) const {
1764 if (id == IDC_CONTENT_CONTEXT_INSPECTELEMENT ||
1765 id == IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE) {
1766 if (!GetPrefs(browser_context_)
1767 ->GetBoolean(prefs::kWebKitJavascriptEnabled))
1768 return false;
1770 // Don't enable the web inspector if the developer tools are disabled via
1771 // the preference dev-tools-disabled.
1772 if (GetPrefs(browser_context_)->GetBoolean(prefs::kDevToolsDisabled))
1773 return false;
1776 return true;
1779 base::string16 RenderViewContextMenu::PrintableSelectionText() {
1780 return gfx::TruncateString(params_.selection_text,
1781 kMaxSelectionTextLength,
1782 gfx::WORD_BREAK);
1785 // Controller functions --------------------------------------------------------
1787 void RenderViewContextMenu::CopyImageAt(int x, int y) {
1788 source_web_contents_->GetRenderViewHost()->CopyImageAt(x, y);
1791 void RenderViewContextMenu::GetImageThumbnailForSearch() {
1792 RenderFrameHost* render_frame_host = GetRenderFrameHost();
1793 if (!render_frame_host)
1794 return;
1795 render_frame_host->Send(new ChromeViewMsg_RequestThumbnailForContextNode(
1796 render_frame_host->GetRoutingID(),
1797 kImageSearchThumbnailMinSize,
1798 gfx::Size(kImageSearchThumbnailMaxWidth,
1799 kImageSearchThumbnailMaxHeight)));
1802 void RenderViewContextMenu::Inspect(int x, int y) {
1803 content::RecordAction(UserMetricsAction("DevTools_InspectElement"));
1804 RenderFrameHost* render_frame_host = GetRenderFrameHost();
1805 if (!render_frame_host)
1806 return;
1807 DevToolsWindow::InspectElement(
1808 WebContents::FromRenderFrameHost(render_frame_host), x, y);
1811 void RenderViewContextMenu::WriteURLToClipboard(const GURL& url) {
1812 chrome_common_net::WriteURLToClipboard(
1813 url, GetPrefs(browser_context_)->GetString(prefs::kAcceptLanguages));
1816 void RenderViewContextMenu::MediaPlayerActionAt(
1817 const gfx::Point& location,
1818 const WebMediaPlayerAction& action) {
1819 source_web_contents_->GetRenderViewHost()->
1820 ExecuteMediaPlayerActionAtLocation(location, action);
1823 void RenderViewContextMenu::PluginActionAt(
1824 const gfx::Point& location,
1825 const WebPluginAction& action) {
1826 source_web_contents_->GetRenderViewHost()->
1827 ExecutePluginActionAtLocation(location, action);