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"
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
;
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
;
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
{
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
},
181 {25, IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP
},
182 {26, IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP
},
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
;
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
))
251 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id
))
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
;
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(
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("&&"),
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
,
287 // No patterns means no restriction, so that implicitly matches.
288 if (patterns
.is_empty())
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(
299 const content::ContextMenuParams
& params
) {
300 const GURL
& referring_url
= GetDocumentURL(params
);
301 return content::Referrer::SanitizeForRequest(
303 content::Referrer(referring_url
.GetAsReferrer(), params
.referrer_policy
));
306 bool g_custom_id_ranges_initialized
= false;
308 const int kSpellcheckRadioGroup
= 1;
313 bool RenderViewContextMenu::IsDevToolsURL(const GURL
& url
) {
314 return url
.SchemeIs(content::kChromeDevToolsScheme
);
318 bool RenderViewContextMenu::IsInternalResourcesURL(const GURL
& url
) {
319 if (!url
.SchemeIs(content::kChromeUIScheme
))
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_
,
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)
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
)))
365 if (has_link
&& contexts
.Contains(MenuItem::LINK
) &&
366 ExtensionPatternMatch(target_url_patterns
, params
.link_url
))
369 switch (params
.media_type
) {
370 case WebContextMenuData::MediaTypeImage
:
371 if (contexts
.Contains(MenuItem::IMAGE
) &&
372 ExtensionPatternMatch(target_url_patterns
, params
.src_url
))
376 case WebContextMenuData::MediaTypeVideo
:
377 if (contexts
.Contains(MenuItem::VIDEO
) &&
378 ExtensionPatternMatch(target_url_patterns
, params
.src_url
))
382 case WebContextMenuData::MediaTypeAudio
:
383 if (contexts
.Contains(MenuItem::AUDIO
) &&
384 ExtensionPatternMatch(target_url_patterns
, params
.src_url
))
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
))
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());
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();
421 return; // In unit-tests, we may not have an ExtensionService.
423 MenuManager
* menu_manager
= MenuManager::Get(browser_context_
);
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();
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())
452 const std::string app_locale
= g_browser_process
->GetApplicationLocale();
453 l10n_util::SortStrings16(app_locale
, &sorted_menu_titles
);
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
,
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();
472 // Only add extension items from this extension.
474 const MenuItem::ExtensionKey
key(
476 extensions::WebViewGuest::GetViewInstanceId(source_web_contents_
));
477 extension_items_
.AppendExtensionItems(key
,
478 PrintableSelectionText(),
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
))
491 if (content_type_
->SupportsGroup(ContextMenuContentType::ITEM_GROUP_FRAME
)) {
492 // Merge in frame items with page items if we clicked within a frame that
494 menu_model_
.AddSeparator(ui::NORMAL_SEPARATOR
);
498 if (content_type_
->SupportsGroup(ContextMenuContentType::ITEM_GROUP_LINK
)) {
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
)) {
509 if (content_type_
->SupportsGroup(
510 ContextMenuContentType::ITEM_GROUP_SEARCHWEBFORIMAGE
)) {
511 AppendSearchWebForImageItems();
514 if (content_type_
->SupportsGroup(
515 ContextMenuContentType::ITEM_GROUP_MEDIA_VIDEO
)) {
519 if (content_type_
->SupportsGroup(
520 ContextMenuContentType::ITEM_GROUP_MEDIA_AUDIO
)) {
524 if (content_type_
->SupportsGroup(
525 ContextMenuContentType::ITEM_GROUP_MEDIA_CANVAS
)) {
529 if (content_type_
->SupportsGroup(
530 ContextMenuContentType::ITEM_GROUP_MEDIA_PLUGIN
)) {
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
));
545 if (content_type_
->SupportsGroup(
546 ContextMenuContentType::ITEM_GROUP_SEARCH_PROVIDER
)) {
547 AppendSearchProvider();
550 if (content_type_
->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT
))
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
);
595 const size_t kMappingSize
= arraysize(kUmaEnumToControlId
);
596 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Used", enum_id
,
597 kUmaEnumToControlId
[kMappingSize
- 1].enum_id
);
599 NOTREACHED() << "Update kUmaEnumToControlId. Unhanded IDC: " << id
;
603 void RenderViewContextMenu::RecordShownItem(int id
) {
604 int enum_id
= FindUMAEnumValueForCommand(id
);
606 const size_t kMappingSize
= arraysize(kUmaEnumToControlId
);
607 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Shown", enum_id
,
608 kUmaEnumToControlId
[kMappingSize
- 1].enum_id
);
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());
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());
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
643 bool show_developer_items
= !IsDevToolsURL(params_
.page_url
);
645 #if defined(DEBUG_DEVTOOLS)
646 show_developer_items
= true;
649 if (!show_developer_items
)
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(
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
);
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())) {
724 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE
,
725 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFORIMAGE
,
726 default_provider
->short_name()));
730 void RenderViewContextMenu::AppendAudioItems() {
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() {
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())
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
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);
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 ¶ms_
.selection_text
);
864 if (params_
.selection_text
.empty())
867 base::ReplaceChars(params_
.selection_text
, AutocompleteMatch::kInvalidChars
,
868 base::ASCIIToUTF16(" "), ¶ms_
.selection_text
);
870 AutocompleteMatch match
;
871 AutocompleteClassifierFactory::GetForProfile(GetProfile())->Classify(
872 params_
.selection_text
,
875 metrics::OmniboxEventProto::INVALID_SPEC
,
878 selection_navigation_url_
= match
.destination_url
;
879 if (!selection_navigation_url_
.is_valid())
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
)
892 IDC_CONTENT_CONTEXT_SEARCHWEBFOR
,
893 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFOR
,
894 default_provider
->short_name(),
895 printable_selection_text
));
897 if ((selection_navigation_url_
!= params_
.link_url
) &&
898 ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
899 selection_navigation_url_
.scheme())) {
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())
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
))
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
))
1005 if (id
== IDC_SAVE_PAGE
&&
1006 (content_restrictions
& CONTENT_RESTRICTION_SAVE
)) {
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
);
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
) {
1027 IncognitoModePrefs::Availability incognito_avail
=
1028 IncognitoModePrefs::GetAvailability(prefs
);
1031 return embedder_web_contents_
->GetController().CanGoBack();
1034 return embedder_web_contents_
->GetController().CanGoForward();
1037 CoreTabHelper
* core_tab_helper
=
1038 CoreTabHelper::FromWebContents(embedder_web_contents_
);
1039 if (!core_tab_helper
)
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
)
1060 // Disabled if no browser is associated (e.g. desktop notifications).
1061 if (chrome::FindBrowserWithWebContents(embedder_web_contents_
) == NULL
)
1065 case IDC_CONTENT_CONTEXT_TRANSLATE
: {
1066 ChromeTranslateClient
* chrome_translate_client
=
1067 ChromeTranslateClient::FromWebContents(embedder_web_contents_
);
1068 if (!chrome_translate_client
)
1070 std::string original_lang
=
1071 chrome_translate_client
->GetLanguageState().original_language();
1072 std::string target_lang
= g_browser_process
->GetApplicationLocale();
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
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(
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
))
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
))
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
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
:
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
))
1164 const GURL
& url
= params_
.src_url
;
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
));
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
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
)
1188 CoreTabHelperDelegate
* core_delegate
= core_tab_helper
->delegate();
1189 if (core_delegate
&&
1190 !core_delegate
->CanSaveContents(embedder_web_contents_
))
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
))
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
))
1225 std::vector
<base::string16
> types
;
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
))
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
;
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
:
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
)
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
:
1277 case IDC_CONTENT_CONTEXT_ADDSEARCHENGINE
:
1278 return !params_
.keyword_url
.is_empty();
1280 case IDC_SPELLCHECK_MENU
:
1283 case IDC_CONTENT_CONTEXT_OPENLINKWITH
:
1286 case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS
:
1295 bool RenderViewContextMenu::IsCommandIdChecked(int id
) const {
1296 if (RenderViewContextMenuBase::IsCommandIdChecked(id
))
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;
1307 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id
))
1308 return extension_items_
.IsCommandIdChecked(id
);
1313 void RenderViewContextMenu::ExecuteCommand(int id
, int event_flags
) {
1314 RenderViewContextMenuBase::ExecuteCommand(id
, event_flags
);
1315 if (command_executed_
)
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_
);
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())
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_
),
1342 ui::PAGE_TRANSITION_LINK
);
1347 case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB
: {
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
);
1357 case IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW
:
1358 OpenURL(params_
.link_url
,
1359 GetDocumentURL(params_
),
1361 ui::PAGE_TRANSITION_LINK
);
1364 case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD
:
1365 OpenURL(params_
.link_url
, GURL(), OFF_THE_RECORD
,
1366 ui::PAGE_TRANSITION_LINK
);
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());
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
);
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(
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
);
1413 case IDC_CONTENT_CONTEXT_COPYLINKLOCATION
:
1414 WriteURLToClipboard(params_
.unfiltered_link_url
);
1417 case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION
:
1418 case IDC_CONTENT_CONTEXT_COPYAVLOCATION
:
1419 WriteURLToClipboard(params_
.src_url
);
1422 case IDC_CONTENT_CONTEXT_COPYIMAGE
:
1423 CopyImageAt(params_
.x
, params_
.y
);
1426 case IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE
:
1427 GetImageThumbnailForSearch();
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
);
1437 case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB
:
1438 case IDC_CONTENT_CONTEXT_OPENAVNEWTAB
:
1439 OpenURL(params_
.src_url
,
1440 GetDocumentURL(params_
),
1442 ui::PAGE_TRANSITION_LINK
);
1445 case IDC_CONTENT_CONTEXT_PLAYPAUSE
: {
1446 bool play
= !!(params_
.media_flags
& WebContextMenuData::MediaPaused
);
1448 content::RecordAction(UserMetricsAction("MediaContextMenu_Play"));
1450 content::RecordAction(UserMetricsAction("MediaContextMenu_Pause"));
1452 MediaPlayerActionAt(gfx::Point(params_
.x
, params_
.y
),
1453 WebMediaPlayerAction(
1454 WebMediaPlayerAction::Play
, play
));
1458 case IDC_CONTENT_CONTEXT_MUTE
: {
1459 bool mute
= !(params_
.media_flags
& WebContextMenuData::MediaMuted
);
1461 content::RecordAction(UserMetricsAction("MediaContextMenu_Mute"));
1463 content::RecordAction(UserMetricsAction("MediaContextMenu_Unmute"));
1465 MediaPlayerActionAt(gfx::Point(params_
.x
, params_
.y
),
1466 WebMediaPlayerAction(
1467 WebMediaPlayerAction::Mute
, mute
));
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
)));
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
)));
1488 case IDC_CONTENT_CONTEXT_ROTATECW
:
1489 content::RecordAction(
1490 UserMetricsAction("PluginContextMenu_RotateClockwise"));
1492 gfx::Point(params_
.x
, params_
.y
),
1493 WebPluginAction(WebPluginAction::Rotate90Clockwise
, true));
1496 case IDC_CONTENT_CONTEXT_ROTATECCW
:
1497 content::RecordAction(
1498 UserMetricsAction("PluginContextMenu_RotateCounterclockwise"));
1500 gfx::Point(params_
.x
, params_
.y
),
1501 WebPluginAction(WebPluginAction::Rotate90Counterclockwise
, true));
1505 embedder_web_contents_
->GetController().GoBack();
1509 embedder_web_contents_
->GetController().GoForward();
1513 embedder_web_contents_
->OnSavePage();
1517 embedder_web_contents_
->GetController().Reload(true);
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());
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());
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()));
1551 printing::StartPrint(
1552 source_web_contents_
,
1553 GetPrefs(browser_context_
)->GetBoolean(prefs::kPrintPreviewDisabled
),
1554 !params_
.selection_text
.empty());
1555 #endif // ENABLE_PRINTING
1559 case IDC_VIEW_SOURCE
:
1560 embedder_web_contents_
->ViewSource();
1563 case IDC_CONTENT_CONTEXT_INSPECTELEMENT
:
1564 Inspect(params_
.x
, params_
.y
);
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
,
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();
1586 chrome::FindBrowserWithWebContents(embedder_web_contents_
);
1587 chrome::ShowWebsiteSettings(browser
, embedder_web_contents_
,
1588 nav_entry
->GetURL(), nav_entry
->GetSSL());
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()) {
1602 std::string original_lang
=
1603 chrome_translate_client
->GetLanguageState().original_language();
1604 std::string target_lang
= g_browser_process
->GetApplicationLocale();
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();
1617 manager
->TranslatePage(original_lang
, target_lang
, true);
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);
1628 case IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE
:
1629 source_web_contents_
->ViewFrameSource(params_
.frame_url
,
1630 params_
.frame_page_state
);
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
);
1641 case IDC_CONTENT_CONTEXT_UNDO
:
1642 source_web_contents_
->Undo();
1645 case IDC_CONTENT_CONTEXT_REDO
:
1646 source_web_contents_
->Redo();
1649 case IDC_CONTENT_CONTEXT_CUT
:
1650 source_web_contents_
->Cut();
1653 case IDC_CONTENT_CONTEXT_COPY
:
1654 source_web_contents_
->Copy();
1657 case IDC_CONTENT_CONTEXT_PASTE
:
1658 source_web_contents_
->Paste();
1661 case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE
:
1662 source_web_contents_
->PasteAndMatchStyle();
1665 case IDC_CONTENT_CONTEXT_DELETE
:
1666 source_web_contents_
->Delete();
1669 case IDC_CONTENT_CONTEXT_SELECTALL
:
1670 source_web_contents_
->SelectAll();
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
);
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
);
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
);
1699 case IDC_CONTENT_CONTEXT_ADDSEARCHENGINE
: {
1700 // Make sure the model is loaded.
1701 TemplateURLService
* model
=
1702 TemplateURLServiceFactory::GetForProfile(GetProfile());
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());
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());
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());
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(
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
))
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
))
1779 base::string16
RenderViewContextMenu::PrintableSelectionText() {
1780 return gfx::TruncateString(params_
.selection_text
,
1781 kMaxSelectionTextLength
,
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
)
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
)
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
);