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. 4 5#include "chrome/browser/renderer_context_menu/render_view_context_menu.h" 6 7#include <algorithm> 8#include <set> 9#include <utility> 10 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/plugins/chrome_plugin_service_filter.h" 35#include "chrome/browser/prefs/incognito_mode_prefs.h" 36#include "chrome/browser/profiles/profile.h" 37#include "chrome/browser/profiles/profile_io_data.h" 38#include "chrome/browser/renderer_context_menu/context_menu_content_type_factory.h" 39#include "chrome/browser/renderer_context_menu/spellchecker_submenu_observer.h" 40#include "chrome/browser/renderer_context_menu/spelling_menu_observer.h" 41#include "chrome/browser/search/search.h" 42#include "chrome/browser/search_engines/template_url_service_factory.h" 43#include "chrome/browser/spellchecker/spellcheck_host_metrics.h" 44#include "chrome/browser/spellchecker/spellcheck_service.h" 45#include "chrome/browser/tab_contents/retargeting_details.h" 46#include "chrome/browser/translate/chrome_translate_client.h" 47#include "chrome/browser/translate/translate_service.h" 48#include "chrome/browser/ui/browser.h" 49#include "chrome/browser/ui/browser_commands.h" 50#include "chrome/browser/ui/browser_finder.h" 51#include "chrome/browser/ui/chrome_pages.h" 52#include "chrome/browser/ui/search_engines/search_engine_tab_helper.h" 53#include "chrome/browser/ui/tab_contents/core_tab_helper.h" 54#include "chrome/common/chrome_constants.h" 55#include "chrome/common/chrome_switches.h" 56#include "chrome/common/content_restriction.h" 57#include "chrome/common/net/url_util.h" 58#include "chrome/common/pref_names.h" 59#include "chrome/common/render_messages.h" 60#include "chrome/common/spellcheck_messages.h" 61#include "chrome/common/url_constants.h" 62#include "chrome/grit/generated_resources.h" 63#include "components/google/core/browser/google_util.h" 64#include "components/metrics/proto/omnibox_input_type.pb.h" 65#include "components/omnibox/autocomplete_match.h" 66#include "components/search_engines/template_url.h" 67#include "components/search_engines/template_url_service.h" 68#include "components/translate/core/browser/translate_download_manager.h" 69#include "components/translate/core/browser/translate_manager.h" 70#include "components/translate/core/browser/translate_prefs.h" 71#include "components/user_prefs/user_prefs.h" 72#include "content/public/browser/child_process_security_policy.h" 73#include "content/public/browser/download_manager.h" 74#include "content/public/browser/download_save_info.h" 75#include "content/public/browser/download_url_parameters.h" 76#include "content/public/browser/navigation_details.h" 77#include "content/public/browser/navigation_entry.h" 78#include "content/public/browser/notification_service.h" 79#include "content/public/browser/render_frame_host.h" 80#include "content/public/browser/render_process_host.h" 81#include "content/public/browser/render_view_host.h" 82#include "content/public/browser/render_widget_host_view.h" 83#include "content/public/browser/user_metrics.h" 84#include "content/public/browser/web_contents.h" 85#include "content/public/common/menu_item.h" 86#include "content/public/common/ssl_status.h" 87#include "content/public/common/url_utils.h" 88#include "extensions/browser/extension_host.h" 89#include "extensions/browser/extension_system.h" 90#include "extensions/browser/guest_view/web_view/web_view_guest.h" 91#include "extensions/browser/view_type_utils.h" 92#include "extensions/common/extension.h" 93#include "net/base/escape.h" 94#include "third_party/WebKit/public/web/WebContextMenuData.h" 95#include "third_party/WebKit/public/web/WebMediaPlayerAction.h" 96#include "third_party/WebKit/public/web/WebPluginAction.h" 97#include "ui/base/clipboard/clipboard.h" 98#include "ui/base/l10n/l10n_util.h" 99#include "ui/gfx/favicon_size.h" 100#include "ui/gfx/point.h" 101#include "ui/gfx/size.h" 102#include "ui/gfx/text_elider.h" 103 104#if defined(ENABLE_PRINTING) 105#include "chrome/common/print_messages.h" 106 107#if defined(ENABLE_FULL_PRINTING) 108#include "chrome/browser/printing/print_preview_context_menu_observer.h" 109#include "chrome/browser/printing/print_preview_dialog_controller.h" 110#include "chrome/browser/printing/print_view_manager.h" 111#else 112#include "chrome/browser/printing/print_view_manager_basic.h" 113#endif // defined(ENABLE_FULL_PRINTING) 114#endif // defined(ENABLE_PRINTING) 115 116using base::UserMetricsAction; 117using blink::WebContextMenuData; 118using blink::WebMediaPlayerAction; 119using blink::WebPluginAction; 120using blink::WebString; 121using blink::WebURL; 122using content::BrowserContext; 123using content::ChildProcessSecurityPolicy; 124using content::DownloadManager; 125using content::DownloadUrlParameters; 126using content::NavigationController; 127using content::NavigationEntry; 128using content::OpenURLParams; 129using content::RenderFrameHost; 130using content::RenderViewHost; 131using content::SSLStatus; 132using content::WebContents; 133using extensions::ContextMenuMatcher; 134using extensions::Extension; 135using extensions::MenuItem; 136using extensions::MenuManager; 137 138namespace { 139 140const int kImageSearchThumbnailMinSize = 300 * 300; 141const int kImageSearchThumbnailMaxWidth = 600; 142const int kImageSearchThumbnailMaxHeight = 600; 143 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|. 149const struct UmaEnumCommandIdPair { 150 int enum_id; 151 int control_id; 152} kUmaEnumToControlId[] = { 153 /* 154 enum id for 0, 1 are detected using 155 RenderViewContextMenu::IsContentCustomCommandId and 156 ContextMenuMatcher::IsExtensionsCustomCommandId 157 */ 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 // Add new items here and use |enum_id| from the next line. 215 {61, 0}, // Must be the last. Increment |enum_id| when new IDC was added. 216}; 217 218// Collapses large ranges of ids before looking for UMA enum. 219int CollapseCommandsForUMA(int id) { 220 DCHECK(!RenderViewContextMenu::IsContentCustomCommandId(id)); 221 DCHECK(!ContextMenuMatcher::IsExtensionsCustomCommandId(id)); 222 223 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST && 224 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) { 225 return IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST; 226 } 227 228 if (id >= IDC_SPELLCHECK_LANGUAGES_FIRST && 229 id <= IDC_SPELLCHECK_LANGUAGES_LAST) { 230 return IDC_SPELLCHECK_LANGUAGES_FIRST; 231 } 232 233 if (id >= IDC_SPELLCHECK_SUGGESTION_0 && 234 id <= IDC_SPELLCHECK_SUGGESTION_LAST) { 235 return IDC_SPELLCHECK_SUGGESTION_0; 236 } 237 238 return id; 239} 240 241// Returns UMA enum value for command specified by |id| or -1 if not found. 242int FindUMAEnumValueForCommand(int id) { 243 if (RenderViewContextMenu::IsContentCustomCommandId(id)) 244 return 0; 245 246 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) 247 return 1; 248 249 id = CollapseCommandsForUMA(id); 250 const size_t kMappingSize = arraysize(kUmaEnumToControlId); 251 for (size_t i = 0; i < kMappingSize; ++i) { 252 if (kUmaEnumToControlId[i].control_id == id) { 253 return kUmaEnumToControlId[i].enum_id; 254 } 255 } 256 return -1; 257} 258 259// Usually a new tab is expected where this function is used, 260// however users should be able to open a tab in background 261// or in a new window. 262WindowOpenDisposition ForceNewTabDispositionFromEventFlags( 263 int event_flags) { 264 WindowOpenDisposition disposition = 265 ui::DispositionFromEventFlags(event_flags); 266 return disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition; 267} 268 269// Helper function to escape "&" as "&&". 270void EscapeAmpersands(base::string16* text) { 271 base::ReplaceChars(*text, base::ASCIIToUTF16("&"), base::ASCIIToUTF16("&&"), 272 text); 273} 274 275// Returns the preference of the profile represented by the |context|. 276PrefService* GetPrefs(content::BrowserContext* context) { 277 return user_prefs::UserPrefs::Get(context); 278} 279 280bool ExtensionPatternMatch(const extensions::URLPatternSet& patterns, 281 const GURL& url) { 282 // No patterns means no restriction, so that implicitly matches. 283 if (patterns.is_empty()) 284 return true; 285 return patterns.MatchesURL(url); 286} 287 288const GURL& GetDocumentURL(const content::ContextMenuParams& params) { 289 return params.frame_url.is_empty() ? params.page_url : params.frame_url; 290} 291 292content::Referrer CreateSaveAsReferrer( 293 const GURL& url, 294 const content::ContextMenuParams& params) { 295 const GURL& referring_url = GetDocumentURL(params); 296 return content::Referrer::SanitizeForRequest( 297 url, 298 content::Referrer(referring_url.GetAsReferrer(), params.referrer_policy)); 299} 300 301bool g_custom_id_ranges_initialized = false; 302 303const int kSpellcheckRadioGroup = 1; 304 305} // namespace 306 307// static 308bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) { 309 return url.SchemeIs(content::kChromeDevToolsScheme); 310} 311 312// static 313bool RenderViewContextMenu::IsInternalResourcesURL(const GURL& url) { 314 if (!url.SchemeIs(content::kChromeUIScheme)) 315 return false; 316 return url.host() == chrome::kChromeUISyncResourcesHost; 317} 318 319RenderViewContextMenu::RenderViewContextMenu( 320 content::RenderFrameHost* render_frame_host, 321 const content::ContextMenuParams& params) 322 : RenderViewContextMenuBase(render_frame_host, params), 323 extension_items_(browser_context_, 324 this, 325 &menu_model_, 326 base::Bind(MenuItemMatchesParams, params_)), 327 protocol_handler_submenu_model_(this), 328 protocol_handler_registry_( 329 ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())) { 330 if (!g_custom_id_ranges_initialized) { 331 g_custom_id_ranges_initialized = true; 332 SetContentCustomCommandIdRange(IDC_CONTENT_CONTEXT_CUSTOM_FIRST, 333 IDC_CONTENT_CONTEXT_CUSTOM_LAST); 334 } 335 set_content_type(ContextMenuContentTypeFactory::Create( 336 source_web_contents_, params)); 337} 338 339RenderViewContextMenu::~RenderViewContextMenu() { 340} 341 342// Menu construction functions ------------------------------------------------- 343 344// static 345bool RenderViewContextMenu::ExtensionContextAndPatternMatch( 346 const content::ContextMenuParams& params, 347 const MenuItem::ContextList& contexts, 348 const extensions::URLPatternSet& target_url_patterns) { 349 const bool has_link = !params.link_url.is_empty(); 350 const bool has_selection = !params.selection_text.empty(); 351 const bool in_frame = !params.frame_url.is_empty(); 352 353 if (contexts.Contains(MenuItem::ALL) || 354 (has_selection && contexts.Contains(MenuItem::SELECTION)) || 355 (params.is_editable && contexts.Contains(MenuItem::EDITABLE)) || 356 (in_frame && contexts.Contains(MenuItem::FRAME))) 357 return true; 358 359 if (has_link && contexts.Contains(MenuItem::LINK) && 360 ExtensionPatternMatch(target_url_patterns, params.link_url)) 361 return true; 362 363 switch (params.media_type) { 364 case WebContextMenuData::MediaTypeImage: 365 if (contexts.Contains(MenuItem::IMAGE) && 366 ExtensionPatternMatch(target_url_patterns, params.src_url)) 367 return true; 368 break; 369 370 case WebContextMenuData::MediaTypeVideo: 371 if (contexts.Contains(MenuItem::VIDEO) && 372 ExtensionPatternMatch(target_url_patterns, params.src_url)) 373 return true; 374 break; 375 376 case WebContextMenuData::MediaTypeAudio: 377 if (contexts.Contains(MenuItem::AUDIO) && 378 ExtensionPatternMatch(target_url_patterns, params.src_url)) 379 return true; 380 break; 381 382 default: 383 break; 384 } 385 386 // PAGE is the least specific context, so we only examine that if none of the 387 // other contexts apply (except for FRAME, which is included in PAGE for 388 // backwards compatibility). 389 if (!has_link && !has_selection && !params.is_editable && 390 params.media_type == WebContextMenuData::MediaTypeNone && 391 contexts.Contains(MenuItem::PAGE)) 392 return true; 393 394 return false; 395} 396 397// static 398bool RenderViewContextMenu::MenuItemMatchesParams( 399 const content::ContextMenuParams& params, 400 const extensions::MenuItem* item) { 401 bool match = ExtensionContextAndPatternMatch(params, item->contexts(), 402 item->target_url_patterns()); 403 if (!match) 404 return false; 405 406 const GURL& document_url = GetDocumentURL(params); 407 return ExtensionPatternMatch(item->document_url_patterns(), document_url); 408} 409 410void RenderViewContextMenu::AppendAllExtensionItems() { 411 extension_items_.Clear(); 412 ExtensionService* service = 413 extensions::ExtensionSystem::Get(browser_context_)->extension_service(); 414 if (!service) 415 return; // In unit-tests, we may not have an ExtensionService. 416 417 MenuManager* menu_manager = MenuManager::Get(browser_context_); 418 if (!menu_manager) 419 return; 420 421 base::string16 printable_selection_text = PrintableSelectionText(); 422 EscapeAmpersands(&printable_selection_text); 423 424 // Get a list of extension id's that have context menu items, and sort by the 425 // top level context menu title of the extension. 426 std::set<MenuItem::ExtensionKey> ids = menu_manager->ExtensionIds(); 427 std::vector<base::string16> sorted_menu_titles; 428 std::map<base::string16, std::string> map_ids; 429 for (std::set<MenuItem::ExtensionKey>::iterator iter = ids.begin(); 430 iter != ids.end(); 431 ++iter) { 432 const Extension* extension = 433 service->GetExtensionById(iter->extension_id, false); 434 // Platform apps have their context menus created directly in 435 // AppendPlatformAppItems. 436 if (extension && !extension->is_platform_app()) { 437 base::string16 menu_title = extension_items_.GetTopLevelContextMenuTitle( 438 *iter, printable_selection_text); 439 map_ids[menu_title] = iter->extension_id; 440 sorted_menu_titles.push_back(menu_title); 441 } 442 } 443 if (sorted_menu_titles.empty()) 444 return; 445 446 const std::string app_locale = g_browser_process->GetApplicationLocale(); 447 l10n_util::SortStrings16(app_locale, &sorted_menu_titles); 448 449 int index = 0; 450 for (size_t i = 0; i < sorted_menu_titles.size(); ++i) { 451 const std::string& id = map_ids[sorted_menu_titles[i]]; 452 const MenuItem::ExtensionKey extension_key(id); 453 extension_items_.AppendExtensionItems(extension_key, 454 printable_selection_text, 455 &index, 456 false); // is_action_menu 457 } 458} 459 460void RenderViewContextMenu::AppendCurrentExtensionItems() { 461 // Avoid appending extension related items when |extension| is null. 462 // For Panel, this happens when the panel is navigated to a url outside of the 463 // extension's package. 464 const Extension* extension = GetExtension(); 465 if (extension) { 466 // Only add extension items from this extension. 467 int index = 0; 468 const MenuItem::ExtensionKey key( 469 extension->id(), 470 extensions::WebViewGuest::GetViewInstanceId(source_web_contents_)); 471 extension_items_.AppendExtensionItems(key, 472 PrintableSelectionText(), 473 &index, 474 false); // is_action_menu 475 } 476} 477 478void RenderViewContextMenu::InitMenu() { 479 RenderViewContextMenuBase::InitMenu(); 480 481 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE)) 482 AppendPageItems(); 483 484 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_FRAME)) { 485 // Merge in frame items with page items if we clicked within a frame that 486 // needs them. 487 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 488 AppendFrameItems(); 489 } 490 491 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_LINK)) { 492 AppendLinkItems(); 493 if (params_.media_type != WebContextMenuData::MediaTypeNone) 494 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 495 } 496 497 if (content_type_->SupportsGroup( 498 ContextMenuContentType::ITEM_GROUP_MEDIA_IMAGE)) { 499 AppendImageItems(); 500 } 501 502 if (content_type_->SupportsGroup( 503 ContextMenuContentType::ITEM_GROUP_SEARCHWEBFORIMAGE)) { 504 AppendSearchWebForImageItems(); 505 } 506 507 if (content_type_->SupportsGroup( 508 ContextMenuContentType::ITEM_GROUP_MEDIA_VIDEO)) { 509 AppendVideoItems(); 510 } 511 512 if (content_type_->SupportsGroup( 513 ContextMenuContentType::ITEM_GROUP_MEDIA_AUDIO)) { 514 AppendAudioItems(); 515 } 516 517 if (content_type_->SupportsGroup( 518 ContextMenuContentType::ITEM_GROUP_MEDIA_CANVAS)) { 519 AppendCanvasItems(); 520 } 521 522 if (content_type_->SupportsGroup( 523 ContextMenuContentType::ITEM_GROUP_MEDIA_PLUGIN)) { 524 AppendPluginItems(); 525 } 526 527 // ITEM_GROUP_MEDIA_FILE has no specific items. 528 529 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_EDITABLE)) 530 AppendEditableItems(); 531 532 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_COPY)) { 533 DCHECK(!content_type_->SupportsGroup( 534 ContextMenuContentType::ITEM_GROUP_EDITABLE)); 535 AppendCopyItem(); 536 } 537 538 if (content_type_->SupportsGroup( 539 ContextMenuContentType::ITEM_GROUP_SEARCH_PROVIDER)) { 540 AppendSearchProvider(); 541 } 542 543 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT)) 544 AppendPrintItem(); 545 546 if (content_type_->SupportsGroup( 547 ContextMenuContentType::ITEM_GROUP_ALL_EXTENSION)) { 548 DCHECK(!content_type_->SupportsGroup( 549 ContextMenuContentType::ITEM_GROUP_CURRENT_EXTENSION)); 550 AppendAllExtensionItems(); 551 } 552 553 if (content_type_->SupportsGroup( 554 ContextMenuContentType::ITEM_GROUP_CURRENT_EXTENSION)) { 555 DCHECK(!content_type_->SupportsGroup( 556 ContextMenuContentType::ITEM_GROUP_ALL_EXTENSION)); 557 AppendCurrentExtensionItems(); 558 } 559 560 if (content_type_->SupportsGroup( 561 ContextMenuContentType::ITEM_GROUP_DEVELOPER)) { 562 AppendDeveloperItems(); 563 } 564 565 if (content_type_->SupportsGroup( 566 ContextMenuContentType::ITEM_GROUP_DEVTOOLS_UNPACKED_EXT)) { 567 AppendDevtoolsForUnpackedExtensions(); 568 } 569 570 if (content_type_->SupportsGroup( 571 ContextMenuContentType::ITEM_GROUP_PRINT_PREVIEW)) { 572 AppendPrintPreviewItems(); 573 } 574} 575 576Profile* RenderViewContextMenu::GetProfile() { 577 return Profile::FromBrowserContext(browser_context_); 578} 579 580void RenderViewContextMenu::RecordUsedItem(int id) { 581 int enum_id = FindUMAEnumValueForCommand(id); 582 if (enum_id != -1) { 583 const size_t kMappingSize = arraysize(kUmaEnumToControlId); 584 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Used", enum_id, 585 kUmaEnumToControlId[kMappingSize - 1].enum_id); 586 } else { 587 NOTREACHED() << "Update kUmaEnumToControlId. Unhanded IDC: " << id; 588 } 589} 590 591void RenderViewContextMenu::RecordShownItem(int id) { 592 int enum_id = FindUMAEnumValueForCommand(id); 593 if (enum_id != -1) { 594 const size_t kMappingSize = arraysize(kUmaEnumToControlId); 595 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Shown", enum_id, 596 kUmaEnumToControlId[kMappingSize - 1].enum_id); 597 } else { 598 // Just warning here. It's harder to maintain list of all possibly 599 // visible items than executable items. 600 DLOG(ERROR) << "Update kUmaEnumToControlId. Unhanded IDC: " << id; 601 } 602} 603 604#if defined(ENABLE_PLUGINS) 605void RenderViewContextMenu::HandleAuthorizeAllPlugins() { 606 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins( 607 source_web_contents_, false, std::string()); 608} 609#endif 610 611void RenderViewContextMenu::AppendPrintPreviewItems() { 612#if defined(ENABLE_FULL_PRINTING) 613 if (!print_preview_menu_observer_.get()) { 614 print_preview_menu_observer_.reset( 615 new PrintPreviewContextMenuObserver(source_web_contents_)); 616 } 617 618 observers_.AddObserver(print_preview_menu_observer_.get()); 619#endif 620} 621 622const Extension* RenderViewContextMenu::GetExtension() const { 623 extensions::ExtensionSystem* system = 624 extensions::ExtensionSystem::Get(browser_context_); 625 // There is no process manager in some tests. 626 if (!system->process_manager()) 627 return NULL; 628 629 return system->process_manager()->GetExtensionForRenderViewHost( 630 source_web_contents_->GetRenderViewHost()); 631} 632 633void RenderViewContextMenu::AppendDeveloperItems() { 634 // Show Inspect Element in DevTools itself only in case of the debug 635 // devtools build. 636 bool show_developer_items = !IsDevToolsURL(params_.page_url); 637 638#if defined(DEBUG_DEVTOOLS) 639 show_developer_items = true; 640#endif 641 642 if (!show_developer_items) 643 return; 644 645 // In the DevTools popup menu, "developer items" is normally the only 646 // section, so omit the separator there. 647 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 648 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_INSPECTELEMENT, 649 IDS_CONTENT_CONTEXT_INSPECTELEMENT); 650} 651 652void RenderViewContextMenu::AppendDevtoolsForUnpackedExtensions() { 653 // Add a separator if there are any items already in the menu. 654 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 655 656 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP, 657 IDS_CONTENT_CONTEXT_RELOAD_PACKAGED_APP); 658 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP, 659 IDS_CONTENT_CONTEXT_RESTART_APP); 660 AppendDeveloperItems(); 661 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE, 662 IDS_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE); 663} 664 665void RenderViewContextMenu::AppendLinkItems() { 666 if (!params_.link_url.is_empty()) { 667 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, 668 IDS_CONTENT_CONTEXT_OPENLINKNEWTAB); 669 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW, 670 IDS_CONTENT_CONTEXT_OPENLINKNEWWINDOW); 671 if (params_.link_url.is_valid()) { 672 AppendProtocolHandlerSubMenu(); 673 } 674 675 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD, 676 IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD); 677 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVELINKAS, 678 IDS_CONTENT_CONTEXT_SAVELINKAS); 679 } 680 681 menu_model_.AddItemWithStringId( 682 IDC_CONTENT_CONTEXT_COPYLINKLOCATION, 683 params_.link_url.SchemeIs(url::kMailToScheme) ? 684 IDS_CONTENT_CONTEXT_COPYEMAILADDRESS : 685 IDS_CONTENT_CONTEXT_COPYLINKLOCATION); 686} 687 688void RenderViewContextMenu::AppendImageItems() { 689 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 690 IDS_CONTENT_CONTEXT_SAVEIMAGEAS); 691 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGELOCATION, 692 IDS_CONTENT_CONTEXT_COPYIMAGELOCATION); 693 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGE, 694 IDS_CONTENT_CONTEXT_COPYIMAGE); 695 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB, 696 IDS_CONTENT_CONTEXT_OPENIMAGENEWTAB); 697} 698 699void RenderViewContextMenu::AppendSearchWebForImageItems() { 700 TemplateURLService* service = 701 TemplateURLServiceFactory::GetForProfile(GetProfile()); 702 const TemplateURL* const default_provider = 703 service->GetDefaultSearchProvider(); 704 if (params_.has_image_contents && default_provider && 705 !default_provider->image_url().empty() && 706 default_provider->image_url_ref().IsValid(service->search_terms_data())) { 707 menu_model_.AddItem( 708 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE, 709 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFORIMAGE, 710 default_provider->short_name())); 711 } 712} 713 714void RenderViewContextMenu::AppendAudioItems() { 715 AppendMediaItems(); 716 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 717 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS, 718 IDS_CONTENT_CONTEXT_SAVEAUDIOAS); 719 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION, 720 IDS_CONTENT_CONTEXT_COPYAUDIOLOCATION); 721 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENAVNEWTAB, 722 IDS_CONTENT_CONTEXT_OPENAUDIONEWTAB); 723} 724 725void RenderViewContextMenu::AppendCanvasItems() { 726 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 727 IDS_CONTENT_CONTEXT_SAVEIMAGEAS); 728 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGE, 729 IDS_CONTENT_CONTEXT_COPYIMAGE); 730} 731 732void RenderViewContextMenu::AppendVideoItems() { 733 AppendMediaItems(); 734 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 735 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS, 736 IDS_CONTENT_CONTEXT_SAVEVIDEOAS); 737 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION, 738 IDS_CONTENT_CONTEXT_COPYVIDEOLOCATION); 739 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENAVNEWTAB, 740 IDS_CONTENT_CONTEXT_OPENVIDEONEWTAB); 741} 742 743void RenderViewContextMenu::AppendMediaItems() { 744 int media_flags = params_.media_flags; 745 746 menu_model_.AddItemWithStringId( 747 IDC_CONTENT_CONTEXT_PLAYPAUSE, 748 media_flags & WebContextMenuData::MediaPaused ? 749 IDS_CONTENT_CONTEXT_PLAY : 750 IDS_CONTENT_CONTEXT_PAUSE); 751 752 menu_model_.AddItemWithStringId( 753 IDC_CONTENT_CONTEXT_MUTE, 754 media_flags & WebContextMenuData::MediaMuted ? 755 IDS_CONTENT_CONTEXT_UNMUTE : 756 IDS_CONTENT_CONTEXT_MUTE); 757 758 menu_model_.AddCheckItemWithStringId(IDC_CONTENT_CONTEXT_LOOP, 759 IDS_CONTENT_CONTEXT_LOOP); 760 menu_model_.AddCheckItemWithStringId(IDC_CONTENT_CONTEXT_CONTROLS, 761 IDS_CONTENT_CONTEXT_CONTROLS); 762} 763 764void RenderViewContextMenu::AppendPluginItems() { 765 if (params_.page_url == params_.src_url) { 766 // Full page plugin, so show page menu items. 767 if (params_.link_url.is_empty() && params_.selection_text.empty()) 768 AppendPageItems(); 769 } else { 770 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS, 771 IDS_CONTENT_CONTEXT_SAVEPAGEAS); 772 menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT); 773 } 774 775 if (params_.media_flags & WebContextMenuData::MediaCanRotate) { 776 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 777 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_ROTATECW, 778 IDS_CONTENT_CONTEXT_ROTATECW); 779 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_ROTATECCW, 780 IDS_CONTENT_CONTEXT_ROTATECCW); 781 } 782} 783 784void RenderViewContextMenu::AppendPageItems() { 785 menu_model_.AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK); 786 menu_model_.AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD); 787 menu_model_.AddItemWithStringId(IDC_RELOAD, IDS_CONTENT_CONTEXT_RELOAD); 788 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 789 menu_model_.AddItemWithStringId(IDC_SAVE_PAGE, 790 IDS_CONTENT_CONTEXT_SAVEPAGEAS); 791 menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT); 792 793 if (TranslateService::IsTranslatableURL(params_.page_url)) { 794 std::string locale = g_browser_process->GetApplicationLocale(); 795 locale = translate::TranslateDownloadManager::GetLanguageCode(locale); 796 base::string16 language = 797 l10n_util::GetDisplayNameForLocale(locale, locale, true); 798 menu_model_.AddItem( 799 IDC_CONTENT_CONTEXT_TRANSLATE, 800 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_TRANSLATE, language)); 801 } 802 803 menu_model_.AddItemWithStringId(IDC_VIEW_SOURCE, 804 IDS_CONTENT_CONTEXT_VIEWPAGESOURCE); 805 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 806 IDS_CONTENT_CONTEXT_VIEWPAGEINFO); 807} 808 809void RenderViewContextMenu::AppendFrameItems() { 810 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_RELOADFRAME, 811 IDS_CONTENT_CONTEXT_RELOADFRAME); 812 // These two menu items have yet to be implemented. 813 // http://code.google.com/p/chromium/issues/detail?id=11827 814 // IDS_CONTENT_CONTEXT_SAVEFRAMEAS 815 // IDS_CONTENT_CONTEXT_PRINTFRAME 816 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE, 817 IDS_CONTENT_CONTEXT_VIEWFRAMESOURCE); 818 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_VIEWFRAMEINFO, 819 IDS_CONTENT_CONTEXT_VIEWFRAMEINFO); 820} 821 822void RenderViewContextMenu::AppendCopyItem() { 823 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPY, 824 IDS_CONTENT_CONTEXT_COPY); 825} 826 827void RenderViewContextMenu::AppendPrintItem() { 828 if (GetPrefs(browser_context_)->GetBoolean(prefs::kPrintingEnabled) && 829 (params_.media_type == WebContextMenuData::MediaTypeNone || 830 params_.media_flags & WebContextMenuData::MediaCanPrint)) { 831 menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT); 832 } 833} 834 835void RenderViewContextMenu::AppendSearchProvider() { 836 DCHECK(browser_context_); 837 838 base::TrimWhitespace(params_.selection_text, base::TRIM_ALL, 839 ¶ms_.selection_text); 840 if (params_.selection_text.empty()) 841 return; 842 843 base::ReplaceChars(params_.selection_text, AutocompleteMatch::kInvalidChars, 844 base::ASCIIToUTF16(" "), ¶ms_.selection_text); 845 846 AutocompleteMatch match; 847 AutocompleteClassifierFactory::GetForProfile(GetProfile())->Classify( 848 params_.selection_text, 849 false, 850 false, 851 metrics::OmniboxEventProto::INVALID_SPEC, 852 &match, 853 NULL); 854 selection_navigation_url_ = match.destination_url; 855 if (!selection_navigation_url_.is_valid()) 856 return; 857 858 base::string16 printable_selection_text = PrintableSelectionText(); 859 EscapeAmpersands(&printable_selection_text); 860 861 if (AutocompleteMatch::IsSearchType(match.type)) { 862 const TemplateURL* const default_provider = 863 TemplateURLServiceFactory::GetForProfile(GetProfile()) 864 ->GetDefaultSearchProvider(); 865 if (!default_provider) 866 return; 867 menu_model_.AddItem( 868 IDC_CONTENT_CONTEXT_SEARCHWEBFOR, 869 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFOR, 870 default_provider->short_name(), 871 printable_selection_text)); 872 } else { 873 if ((selection_navigation_url_ != params_.link_url) && 874 ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme( 875 selection_navigation_url_.scheme())) { 876 menu_model_.AddItem( 877 IDC_CONTENT_CONTEXT_GOTOURL, 878 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_GOTOURL, 879 printable_selection_text)); 880 } 881 } 882} 883 884void RenderViewContextMenu::AppendEditableItems() { 885 const bool use_spellcheck_and_search = !chrome::IsRunningInForcedAppMode(); 886 887 if (use_spellcheck_and_search) 888 AppendSpellingSuggestionsSubMenu(); 889 890 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_UNDO, 891 IDS_CONTENT_CONTEXT_UNDO); 892 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_REDO, 893 IDS_CONTENT_CONTEXT_REDO); 894 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 895 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_CUT, 896 IDS_CONTENT_CONTEXT_CUT); 897 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPY, 898 IDS_CONTENT_CONTEXT_COPY); 899 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_PASTE, 900 IDS_CONTENT_CONTEXT_PASTE); 901 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE, 902 IDS_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE); 903 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_DELETE, 904 IDS_CONTENT_CONTEXT_DELETE); 905 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 906 907 if (use_spellcheck_and_search && !params_.keyword_url.is_empty()) { 908 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_ADDSEARCHENGINE, 909 IDS_CONTENT_CONTEXT_ADDSEARCHENGINE); 910 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 911 } 912 913 if (use_spellcheck_and_search) 914 AppendSpellcheckOptionsSubMenu(); 915 AppendPlatformEditableItems(); 916 917 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 918 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SELECTALL, 919 IDS_CONTENT_CONTEXT_SELECTALL); 920} 921 922void RenderViewContextMenu::AppendSpellingSuggestionsSubMenu() { 923 if (!spelling_menu_observer_.get()) 924 spelling_menu_observer_.reset(new SpellingMenuObserver(this)); 925 observers_.AddObserver(spelling_menu_observer_.get()); 926 spelling_menu_observer_->InitMenu(params_); 927} 928 929void RenderViewContextMenu::AppendSpellcheckOptionsSubMenu() { 930 if (!spellchecker_submenu_observer_.get()) { 931 spellchecker_submenu_observer_.reset(new SpellCheckerSubMenuObserver( 932 this, this, kSpellcheckRadioGroup)); 933 } 934 spellchecker_submenu_observer_->InitMenu(params_); 935 observers_.AddObserver(spellchecker_submenu_observer_.get()); 936} 937 938void RenderViewContextMenu::AppendProtocolHandlerSubMenu() { 939 const ProtocolHandlerRegistry::ProtocolHandlerList handlers = 940 GetHandlersForLinkUrl(); 941 if (handlers.empty()) 942 return; 943 size_t max = IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST - 944 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST; 945 for (size_t i = 0; i < handlers.size() && i <= max; i++) { 946 protocol_handler_submenu_model_.AddItem( 947 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST + i, 948 base::UTF8ToUTF16(handlers[i].url().host())); 949 } 950 protocol_handler_submenu_model_.AddSeparator(ui::NORMAL_SEPARATOR); 951 protocol_handler_submenu_model_.AddItem( 952 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS, 953 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH_CONFIGURE)); 954 955 menu_model_.AddSubMenu( 956 IDC_CONTENT_CONTEXT_OPENLINKWITH, 957 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH), 958 &protocol_handler_submenu_model_); 959} 960 961// Menu delegate functions ----------------------------------------------------- 962 963bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { 964 { 965 bool enabled = false; 966 if (RenderViewContextMenuBase::IsCommandIdKnown(id, &enabled)) 967 return enabled; 968 } 969 970 CoreTabHelper* core_tab_helper = 971 CoreTabHelper::FromWebContents(source_web_contents_); 972 int content_restrictions = 0; 973 if (core_tab_helper) 974 content_restrictions = core_tab_helper->content_restrictions(); 975 if (id == IDC_PRINT && (content_restrictions & CONTENT_RESTRICTION_PRINT)) 976 return false; 977 978 if (id == IDC_SAVE_PAGE && 979 (content_restrictions & CONTENT_RESTRICTION_SAVE)) { 980 return false; 981 } 982 983 PrefService* prefs = GetPrefs(browser_context_); 984 985 // Allow Spell Check language items on sub menu for text area context menu. 986 if ((id >= IDC_SPELLCHECK_LANGUAGES_FIRST) && 987 (id < IDC_SPELLCHECK_LANGUAGES_LAST)) { 988 return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck); 989 } 990 991 // Extension items. 992 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) 993 return extension_items_.IsCommandIdEnabled(id); 994 995 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST && 996 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) { 997 return true; 998 } 999 1000 IncognitoModePrefs::Availability incognito_avail = 1001 IncognitoModePrefs::GetAvailability(prefs); 1002 switch (id) { 1003 case IDC_BACK: 1004 return source_web_contents_->GetController().CanGoBack(); 1005 1006 case IDC_FORWARD: 1007 return source_web_contents_->GetController().CanGoForward(); 1008 1009 case IDC_RELOAD: { 1010 CoreTabHelper* core_tab_helper = 1011 CoreTabHelper::FromWebContents(source_web_contents_); 1012 if (!core_tab_helper) 1013 return false; 1014 1015 CoreTabHelperDelegate* core_delegate = core_tab_helper->delegate(); 1016 return !core_delegate || 1017 core_delegate->CanReloadContents(source_web_contents_); 1018 } 1019 1020 case IDC_VIEW_SOURCE: 1021 case IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE: 1022 return source_web_contents_->GetController().CanViewSource(); 1023 1024 case IDC_CONTENT_CONTEXT_INSPECTELEMENT: 1025 case IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE: 1026 case IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP: 1027 case IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP: 1028 return IsDevCommandEnabled(id); 1029 1030 case IDC_CONTENT_CONTEXT_VIEWPAGEINFO: 1031 if (source_web_contents_->GetController().GetVisibleEntry() == NULL) 1032 return false; 1033 // Disabled if no browser is associated (e.g. desktop notifications). 1034 if (chrome::FindBrowserWithWebContents(source_web_contents_) == NULL) 1035 return false; 1036 return true; 1037 1038 case IDC_CONTENT_CONTEXT_TRANSLATE: { 1039 ChromeTranslateClient* chrome_translate_client = 1040 ChromeTranslateClient::FromWebContents(source_web_contents_); 1041 if (!chrome_translate_client) 1042 return false; 1043 std::string original_lang = 1044 chrome_translate_client->GetLanguageState().original_language(); 1045 std::string target_lang = g_browser_process->GetApplicationLocale(); 1046 target_lang = 1047 translate::TranslateDownloadManager::GetLanguageCode(target_lang); 1048 // Note that we intentionally enable the menu even if the original and 1049 // target languages are identical. This is to give a way to user to 1050 // translate a page that might contains text fragments in a different 1051 // language. 1052 return ((params_.edit_flags & WebContextMenuData::CanTranslate) != 0) && 1053 !original_lang.empty() && // Did we receive the page language yet? 1054 !chrome_translate_client->GetLanguageState().IsPageTranslated() && 1055 !source_web_contents_->GetInterstitialPage() && 1056 // There are some application locales which can't be used as a 1057 // target language for translation. 1058 translate::TranslateDownloadManager::IsSupportedLanguage( 1059 target_lang) && 1060 // Disable on the Instant Extended NTP. 1061 !chrome::IsInstantNTP(source_web_contents_); 1062 } 1063 1064 case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB: 1065 case IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW: 1066 return params_.link_url.is_valid(); 1067 1068 case IDC_CONTENT_CONTEXT_COPYLINKLOCATION: 1069 return params_.unfiltered_link_url.is_valid(); 1070 1071 case IDC_CONTENT_CONTEXT_SAVELINKAS: { 1072 PrefService* local_state = g_browser_process->local_state(); 1073 DCHECK(local_state); 1074 // Test if file-selection dialogs are forbidden by policy. 1075 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs)) 1076 return false; 1077 1078 return params_.link_url.is_valid() && 1079 ProfileIOData::IsHandledProtocol(params_.link_url.scheme()); 1080 } 1081 1082 case IDC_CONTENT_CONTEXT_SAVEIMAGEAS: { 1083 PrefService* local_state = g_browser_process->local_state(); 1084 DCHECK(local_state); 1085 // Test if file-selection dialogs are forbidden by policy. 1086 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs)) 1087 return false; 1088 1089 return params_.has_image_contents; 1090 } 1091 1092 // The images shown in the most visited thumbnails can't be opened or 1093 // searched for conventionally. 1094 case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB: 1095 case IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE: 1096 return params_.src_url.is_valid() && 1097 (params_.src_url.scheme() != content::kChromeUIScheme); 1098 1099 case IDC_CONTENT_CONTEXT_COPYIMAGE: 1100 return params_.has_image_contents; 1101 1102 // Media control commands should all be disabled if the player is in an 1103 // error state. 1104 case IDC_CONTENT_CONTEXT_PLAYPAUSE: 1105 case IDC_CONTENT_CONTEXT_LOOP: 1106 return (params_.media_flags & 1107 WebContextMenuData::MediaInError) == 0; 1108 1109 // Mute and unmute should also be disabled if the player has no audio. 1110 case IDC_CONTENT_CONTEXT_MUTE: 1111 return (params_.media_flags & 1112 WebContextMenuData::MediaHasAudio) != 0 && 1113 (params_.media_flags & 1114 WebContextMenuData::MediaInError) == 0; 1115 1116 case IDC_CONTENT_CONTEXT_CONTROLS: 1117 return (params_.media_flags & 1118 WebContextMenuData::MediaCanToggleControls) != 0; 1119 1120 case IDC_CONTENT_CONTEXT_ROTATECW: 1121 case IDC_CONTENT_CONTEXT_ROTATECCW: 1122 return 1123 (params_.media_flags & WebContextMenuData::MediaCanRotate) != 0; 1124 1125 case IDC_CONTENT_CONTEXT_COPYAVLOCATION: 1126 case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION: 1127 return params_.src_url.is_valid(); 1128 1129 case IDC_CONTENT_CONTEXT_SAVEAVAS: { 1130 PrefService* local_state = g_browser_process->local_state(); 1131 DCHECK(local_state); 1132 // Test if file-selection dialogs are forbidden by policy. 1133 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs)) 1134 return false; 1135 1136 const GURL& url = params_.src_url; 1137 bool can_save = 1138 (params_.media_flags & WebContextMenuData::MediaCanSave) && 1139 url.is_valid() && ProfileIOData::IsHandledProtocol(url.scheme()); 1140#if defined(ENABLE_FULL_PRINTING) 1141 // Do not save the preview PDF on the print preview page. 1142 can_save = can_save && 1143 !(printing::PrintPreviewDialogController::IsPrintPreviewURL(url)); 1144#endif 1145 return can_save; 1146 } 1147 1148 case IDC_CONTENT_CONTEXT_OPENAVNEWTAB: 1149 return true; 1150 1151 case IDC_SAVE_PAGE: { 1152 CoreTabHelper* core_tab_helper = 1153 CoreTabHelper::FromWebContents(source_web_contents_); 1154 if (!core_tab_helper) 1155 return false; 1156 1157 CoreTabHelperDelegate* core_delegate = core_tab_helper->delegate(); 1158 if (core_delegate && 1159 !core_delegate->CanSaveContents(source_web_contents_)) 1160 return false; 1161 1162 PrefService* local_state = g_browser_process->local_state(); 1163 DCHECK(local_state); 1164 // Test if file-selection dialogs are forbidden by policy. 1165 if (!local_state->GetBoolean(prefs::kAllowFileSelectionDialogs)) 1166 return false; 1167 1168 // We save the last committed entry (which the user is looking at), as 1169 // opposed to any pending URL that hasn't committed yet. 1170 NavigationEntry* entry = 1171 source_web_contents_->GetController().GetLastCommittedEntry(); 1172 return content::IsSavableURL(entry ? entry->GetURL() : GURL()); 1173 } 1174 1175 case IDC_CONTENT_CONTEXT_RELOADFRAME: 1176 return params_.frame_url.is_valid(); 1177 1178 case IDC_CONTENT_CONTEXT_UNDO: 1179 return !!(params_.edit_flags & WebContextMenuData::CanUndo); 1180 1181 case IDC_CONTENT_CONTEXT_REDO: 1182 return !!(params_.edit_flags & WebContextMenuData::CanRedo); 1183 1184 case IDC_CONTENT_CONTEXT_CUT: 1185 return !!(params_.edit_flags & WebContextMenuData::CanCut); 1186 1187 case IDC_CONTENT_CONTEXT_COPY: 1188 return !!(params_.edit_flags & WebContextMenuData::CanCopy); 1189 1190 case IDC_CONTENT_CONTEXT_PASTE: 1191 case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE: { 1192 std::vector<base::string16> types; 1193 bool ignore; 1194 ui::Clipboard::GetForCurrentThread()->ReadAvailableTypes( 1195 ui::CLIPBOARD_TYPE_COPY_PASTE, &types, &ignore); 1196 return !types.empty(); 1197 } 1198 case IDC_CONTENT_CONTEXT_DELETE: 1199 return !!(params_.edit_flags & WebContextMenuData::CanDelete); 1200 1201 case IDC_CONTENT_CONTEXT_SELECTALL: 1202 return !!(params_.edit_flags & WebContextMenuData::CanSelectAll); 1203 1204 case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD: 1205 return !browser_context_->IsOffTheRecord() && 1206 params_.link_url.is_valid() && 1207 incognito_avail != IncognitoModePrefs::DISABLED; 1208 1209 case IDC_PRINT: 1210 return prefs->GetBoolean(prefs::kPrintingEnabled) && 1211 (params_.media_type == WebContextMenuData::MediaTypeNone || 1212 params_.media_flags & WebContextMenuData::MediaCanPrint); 1213 1214 case IDC_CONTENT_CONTEXT_SEARCHWEBFOR: 1215 case IDC_CONTENT_CONTEXT_GOTOURL: 1216 case IDC_SPELLPANEL_TOGGLE: 1217 case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS: 1218 return true; 1219 case IDC_CONTENT_CONTEXT_VIEWFRAMEINFO: 1220 // Disabled if no browser is associated (e.g. desktop notifications). 1221 if (chrome::FindBrowserWithWebContents(source_web_contents_) == NULL) 1222 return false; 1223 return true; 1224 1225 case IDC_CHECK_SPELLING_WHILE_TYPING: 1226 return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck); 1227 1228#if !defined(OS_MACOSX) && defined(OS_POSIX) 1229 // TODO(suzhe): this should not be enabled for password fields. 1230 case IDC_INPUT_METHODS_MENU: 1231 return true; 1232#endif 1233 1234 case IDC_CONTENT_CONTEXT_ADDSEARCHENGINE: 1235 return !params_.keyword_url.is_empty(); 1236 1237 case IDC_SPELLCHECK_MENU: 1238 return true; 1239 1240 case IDC_CONTENT_CONTEXT_OPENLINKWITH: 1241 return true; 1242 1243 case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS: 1244 return true; 1245 1246 default: 1247 NOTREACHED(); 1248 return false; 1249 } 1250} 1251 1252bool RenderViewContextMenu::IsCommandIdChecked(int id) const { 1253 if (RenderViewContextMenuBase::IsCommandIdChecked(id)) 1254 return true; 1255 1256 // See if the video is set to looping. 1257 if (id == IDC_CONTENT_CONTEXT_LOOP) 1258 return (params_.media_flags & WebContextMenuData::MediaLoop) != 0; 1259 1260 if (id == IDC_CONTENT_CONTEXT_CONTROLS) 1261 return (params_.media_flags & WebContextMenuData::MediaControls) != 0; 1262 1263 // Extension items. 1264 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) 1265 return extension_items_.IsCommandIdChecked(id); 1266 1267 return false; 1268} 1269 1270void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { 1271 RenderViewContextMenuBase::ExecuteCommand(id, event_flags); 1272 if (command_executed_) 1273 return; 1274 command_executed_ = true; 1275 1276 RenderFrameHost* render_frame_host = GetRenderFrameHost(); 1277 1278 // Process extension menu items. 1279 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) { 1280 extension_items_.ExecuteCommand(id, source_web_contents_, params_); 1281 return; 1282 } 1283 1284 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST && 1285 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) { 1286 ProtocolHandlerRegistry::ProtocolHandlerList handlers = 1287 GetHandlersForLinkUrl(); 1288 if (handlers.empty()) 1289 return; 1290 1291 content::RecordAction( 1292 UserMetricsAction("RegisterProtocolHandler.ContextMenu_Open")); 1293 int handlerIndex = id - IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST; 1294 WindowOpenDisposition disposition = 1295 ForceNewTabDispositionFromEventFlags(event_flags); 1296 OpenURL(handlers[handlerIndex].TranslateUrl(params_.link_url), 1297 GetDocumentURL(params_), 1298 disposition, 1299 ui::PAGE_TRANSITION_LINK); 1300 return; 1301 } 1302 1303 switch (id) { 1304 case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB: { 1305 Browser* browser = 1306 chrome::FindBrowserWithWebContents(source_web_contents_); 1307 OpenURL(params_.link_url, 1308 GetDocumentURL(params_), 1309 !browser || browser->is_app() ? 1310 NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB, 1311 ui::PAGE_TRANSITION_LINK); 1312 break; 1313 } 1314 case IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW: 1315 OpenURL(params_.link_url, 1316 GetDocumentURL(params_), 1317 NEW_WINDOW, 1318 ui::PAGE_TRANSITION_LINK); 1319 break; 1320 1321 case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD: 1322 OpenURL(params_.link_url, GURL(), OFF_THE_RECORD, 1323 ui::PAGE_TRANSITION_LINK); 1324 break; 1325 1326 case IDC_CONTENT_CONTEXT_SAVELINKAS: { 1327 RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU); 1328 const GURL& url = params_.link_url; 1329 content::Referrer referrer = CreateSaveAsReferrer(url, params_); 1330 DownloadManager* dlm = 1331 BrowserContext::GetDownloadManager(browser_context_); 1332 scoped_ptr<DownloadUrlParameters> dl_params( 1333 DownloadUrlParameters::FromWebContents(source_web_contents_, url)); 1334 dl_params->set_referrer(referrer); 1335 dl_params->set_referrer_encoding(params_.frame_charset); 1336 dl_params->set_suggested_name(params_.suggested_filename); 1337 dl_params->set_prompt(true); 1338 dlm->DownloadUrl(dl_params.Pass()); 1339 break; 1340 } 1341 1342 case IDC_CONTENT_CONTEXT_SAVEAVAS: 1343 case IDC_CONTENT_CONTEXT_SAVEIMAGEAS: { 1344 bool is_large_data_url = params_.has_image_contents && 1345 params_.src_url.is_empty(); 1346 if (params_.media_type == WebContextMenuData::MediaTypeCanvas || 1347 (params_.media_type == WebContextMenuData::MediaTypeImage && 1348 is_large_data_url)) { 1349 source_web_contents_->GetRenderViewHost()->SaveImageAt( 1350 params_.x, params_.y); 1351 } else { 1352 RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU); 1353 const GURL& url = params_.src_url; 1354 content::Referrer referrer = CreateSaveAsReferrer(url, params_); 1355 source_web_contents_->SaveFrame(url, referrer); 1356 } 1357 break; 1358 } 1359 1360 case IDC_CONTENT_CONTEXT_COPYLINKLOCATION: 1361 WriteURLToClipboard(params_.unfiltered_link_url); 1362 break; 1363 1364 case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION: 1365 case IDC_CONTENT_CONTEXT_COPYAVLOCATION: 1366 WriteURLToClipboard(params_.src_url); 1367 break; 1368 1369 case IDC_CONTENT_CONTEXT_COPYIMAGE: 1370 CopyImageAt(params_.x, params_.y); 1371 break; 1372 1373 case IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE: 1374 GetImageThumbnailForSearch(); 1375 break; 1376 1377 case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB: 1378 case IDC_CONTENT_CONTEXT_OPENAVNEWTAB: 1379 OpenURL(params_.src_url, 1380 GetDocumentURL(params_), 1381 NEW_BACKGROUND_TAB, 1382 ui::PAGE_TRANSITION_LINK); 1383 break; 1384 1385 case IDC_CONTENT_CONTEXT_PLAYPAUSE: { 1386 bool play = !!(params_.media_flags & WebContextMenuData::MediaPaused); 1387 if (play) { 1388 content::RecordAction(UserMetricsAction("MediaContextMenu_Play")); 1389 } else { 1390 content::RecordAction(UserMetricsAction("MediaContextMenu_Pause")); 1391 } 1392 MediaPlayerActionAt(gfx::Point(params_.x, params_.y), 1393 WebMediaPlayerAction( 1394 WebMediaPlayerAction::Play, play)); 1395 break; 1396 } 1397 1398 case IDC_CONTENT_CONTEXT_MUTE: { 1399 bool mute = !(params_.media_flags & WebContextMenuData::MediaMuted); 1400 if (mute) { 1401 content::RecordAction(UserMetricsAction("MediaContextMenu_Mute")); 1402 } else { 1403 content::RecordAction(UserMetricsAction("MediaContextMenu_Unmute")); 1404 } 1405 MediaPlayerActionAt(gfx::Point(params_.x, params_.y), 1406 WebMediaPlayerAction( 1407 WebMediaPlayerAction::Mute, mute)); 1408 break; 1409 } 1410 1411 case IDC_CONTENT_CONTEXT_LOOP: 1412 content::RecordAction(UserMetricsAction("MediaContextMenu_Loop")); 1413 MediaPlayerActionAt(gfx::Point(params_.x, params_.y), 1414 WebMediaPlayerAction( 1415 WebMediaPlayerAction::Loop, 1416 !IsCommandIdChecked(IDC_CONTENT_CONTEXT_LOOP))); 1417 break; 1418 1419 case IDC_CONTENT_CONTEXT_CONTROLS: 1420 content::RecordAction(UserMetricsAction("MediaContextMenu_Controls")); 1421 MediaPlayerActionAt( 1422 gfx::Point(params_.x, params_.y), 1423 WebMediaPlayerAction( 1424 WebMediaPlayerAction::Controls, 1425 !IsCommandIdChecked(IDC_CONTENT_CONTEXT_CONTROLS))); 1426 break; 1427 1428 case IDC_CONTENT_CONTEXT_ROTATECW: 1429 content::RecordAction( 1430 UserMetricsAction("PluginContextMenu_RotateClockwise")); 1431 PluginActionAt( 1432 gfx::Point(params_.x, params_.y), 1433 WebPluginAction(WebPluginAction::Rotate90Clockwise, true)); 1434 break; 1435 1436 case IDC_CONTENT_CONTEXT_ROTATECCW: 1437 content::RecordAction( 1438 UserMetricsAction("PluginContextMenu_RotateCounterclockwise")); 1439 PluginActionAt( 1440 gfx::Point(params_.x, params_.y), 1441 WebPluginAction(WebPluginAction::Rotate90Counterclockwise, true)); 1442 break; 1443 1444 case IDC_BACK: 1445 source_web_contents_->GetController().GoBack(); 1446 break; 1447 1448 case IDC_FORWARD: 1449 source_web_contents_->GetController().GoForward(); 1450 break; 1451 1452 case IDC_SAVE_PAGE: 1453 source_web_contents_->OnSavePage(); 1454 break; 1455 1456 case IDC_RELOAD: 1457 source_web_contents_->GetController().Reload(true); 1458 break; 1459 1460 case IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP: { 1461 const Extension* platform_app = GetExtension(); 1462 DCHECK(platform_app); 1463 DCHECK(platform_app->is_platform_app()); 1464 1465 extensions::ExtensionSystem::Get(browser_context_) 1466 ->extension_service() 1467 ->ReloadExtension(platform_app->id()); 1468 break; 1469 } 1470 1471 case IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP: { 1472 const Extension* platform_app = GetExtension(); 1473 DCHECK(platform_app); 1474 DCHECK(platform_app->is_platform_app()); 1475 1476 apps::AppLoadService::Get(GetProfile()) 1477 ->RestartApplication(platform_app->id()); 1478 break; 1479 } 1480 1481 case IDC_PRINT: { 1482#if defined(ENABLE_PRINTING) 1483 if (params_.media_type != WebContextMenuData::MediaTypeNone) { 1484 if (render_frame_host) { 1485 render_frame_host->Send(new PrintMsg_PrintNodeUnderContextMenu( 1486 render_frame_host->GetRoutingID())); 1487 } 1488 break; 1489 } 1490 1491#if defined(ENABLE_FULL_PRINTING) 1492 printing::PrintViewManager* print_view_manager = 1493 printing::PrintViewManager::FromWebContents(source_web_contents_); 1494 if (!print_view_manager) 1495 break; 1496 if (!GetPrefs(browser_context_) 1497 ->GetBoolean(prefs::kPrintPreviewDisabled)) { 1498 print_view_manager->PrintPreviewNow(!params_.selection_text.empty()); 1499 break; 1500 } 1501#else // ENABLE_FULL_PRINTING 1502 printing::PrintViewManagerBasic* print_view_manager = 1503 printing::PrintViewManagerBasic::FromWebContents( 1504 source_web_contents_); 1505 if (!print_view_manager) 1506 break; 1507#endif // ENABLE_FULL_PRINTING 1508 1509#if !defined(DISABLE_BASIC_PRINTING) 1510 print_view_manager->PrintNow(); 1511#endif // !DISABLE_BASIC_PRINTING 1512 1513#endif // ENABLE_PRINTING 1514 break; 1515 } 1516 1517 case IDC_VIEW_SOURCE: 1518 source_web_contents_->ViewSource(); 1519 break; 1520 1521 case IDC_CONTENT_CONTEXT_INSPECTELEMENT: 1522 Inspect(params_.x, params_.y); 1523 break; 1524 1525 case IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE: { 1526 const Extension* platform_app = GetExtension(); 1527 DCHECK(platform_app); 1528 DCHECK(platform_app->is_platform_app()); 1529 1530 extensions::devtools_util::InspectBackgroundPage(platform_app, 1531 GetProfile()); 1532 break; 1533 } 1534 1535 case IDC_CONTENT_CONTEXT_VIEWPAGEINFO: { 1536 NavigationController* controller = &source_web_contents_->GetController(); 1537 // Important to use GetVisibleEntry to match what's showing in the 1538 // omnibox. This may return null. 1539 NavigationEntry* nav_entry = controller->GetVisibleEntry(); 1540 if (!nav_entry) 1541 return; 1542 Browser* browser = 1543 chrome::FindBrowserWithWebContents(source_web_contents_); 1544 chrome::ShowWebsiteSettings(browser, source_web_contents_, 1545 nav_entry->GetURL(), nav_entry->GetSSL()); 1546 break; 1547 } 1548 1549 case IDC_CONTENT_CONTEXT_TRANSLATE: { 1550 // A translation might have been triggered by the time the menu got 1551 // selected, do nothing in that case. 1552 ChromeTranslateClient* chrome_translate_client = 1553 ChromeTranslateClient::FromWebContents(source_web_contents_); 1554 if (!chrome_translate_client || 1555 chrome_translate_client->GetLanguageState().IsPageTranslated() || 1556 chrome_translate_client->GetLanguageState().translation_pending()) { 1557 return; 1558 } 1559 std::string original_lang = 1560 chrome_translate_client->GetLanguageState().original_language(); 1561 std::string target_lang = g_browser_process->GetApplicationLocale(); 1562 target_lang = 1563 translate::TranslateDownloadManager::GetLanguageCode(target_lang); 1564 // Since the user decided to translate for that language and site, clears 1565 // any preferences for not translating them. 1566 scoped_ptr<translate::TranslatePrefs> prefs( 1567 ChromeTranslateClient::CreateTranslatePrefs( 1568 GetPrefs(browser_context_))); 1569 prefs->UnblockLanguage(original_lang); 1570 prefs->RemoveSiteFromBlacklist(params_.page_url.HostNoBrackets()); 1571 translate::TranslateManager* manager = 1572 chrome_translate_client->GetTranslateManager(); 1573 DCHECK(manager); 1574 manager->TranslatePage(original_lang, target_lang, true); 1575 break; 1576 } 1577 1578 case IDC_CONTENT_CONTEXT_RELOADFRAME: 1579 // We always obey the cache here. 1580 // TODO(evanm): Perhaps we could allow shift-clicking the menu item to do 1581 // a cache-ignoring reload of the frame. 1582 source_web_contents_->ReloadFocusedFrame(false); 1583 break; 1584 1585 case IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE: 1586 source_web_contents_->ViewFrameSource(params_.frame_url, 1587 params_.frame_page_state); 1588 break; 1589 1590 case IDC_CONTENT_CONTEXT_VIEWFRAMEINFO: { 1591 Browser* browser = chrome::FindBrowserWithWebContents( 1592 source_web_contents_); 1593 chrome::ShowWebsiteSettings(browser, source_web_contents_, 1594 params_.frame_url, params_.security_info); 1595 break; 1596 } 1597 1598 case IDC_CONTENT_CONTEXT_UNDO: 1599 source_web_contents_->Undo(); 1600 break; 1601 1602 case IDC_CONTENT_CONTEXT_REDO: 1603 source_web_contents_->Redo(); 1604 break; 1605 1606 case IDC_CONTENT_CONTEXT_CUT: 1607 source_web_contents_->Cut(); 1608 break; 1609 1610 case IDC_CONTENT_CONTEXT_COPY: 1611 source_web_contents_->Copy(); 1612 break; 1613 1614 case IDC_CONTENT_CONTEXT_PASTE: 1615 source_web_contents_->Paste(); 1616 break; 1617 1618 case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE: 1619 source_web_contents_->PasteAndMatchStyle(); 1620 break; 1621 1622 case IDC_CONTENT_CONTEXT_DELETE: 1623 source_web_contents_->Delete(); 1624 break; 1625 1626 case IDC_CONTENT_CONTEXT_SELECTALL: 1627 source_web_contents_->SelectAll(); 1628 break; 1629 1630 case IDC_CONTENT_CONTEXT_SEARCHWEBFOR: 1631 case IDC_CONTENT_CONTEXT_GOTOURL: { 1632 WindowOpenDisposition disposition = 1633 ForceNewTabDispositionFromEventFlags(event_flags); 1634 OpenURL(selection_navigation_url_, GURL(), disposition, 1635 ui::PAGE_TRANSITION_LINK); 1636 break; 1637 } 1638 case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS: { 1639 WindowOpenDisposition disposition = 1640 ForceNewTabDispositionFromEventFlags(event_flags); 1641 GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage); 1642 OpenURL(url, GURL(), disposition, ui::PAGE_TRANSITION_LINK); 1643 break; 1644 } 1645 1646 case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS: { 1647 content::RecordAction( 1648 UserMetricsAction("RegisterProtocolHandler.ContextMenu_Settings")); 1649 WindowOpenDisposition disposition = 1650 ForceNewTabDispositionFromEventFlags(event_flags); 1651 GURL url = chrome::GetSettingsUrl(chrome::kHandlerSettingsSubPage); 1652 OpenURL(url, GURL(), disposition, ui::PAGE_TRANSITION_LINK); 1653 break; 1654 } 1655 1656 case IDC_CONTENT_CONTEXT_ADDSEARCHENGINE: { 1657 // Make sure the model is loaded. 1658 TemplateURLService* model = 1659 TemplateURLServiceFactory::GetForProfile(GetProfile()); 1660 if (!model) 1661 return; 1662 model->Load(); 1663 1664 SearchEngineTabHelper* search_engine_tab_helper = 1665 SearchEngineTabHelper::FromWebContents(source_web_contents_); 1666 if (search_engine_tab_helper && 1667 search_engine_tab_helper->delegate()) { 1668 base::string16 keyword(TemplateURL::GenerateKeyword(params_.page_url)); 1669 TemplateURLData data; 1670 data.short_name = keyword; 1671 data.SetKeyword(keyword); 1672 data.SetURL(params_.keyword_url.spec()); 1673 data.favicon_url = 1674 TemplateURL::GenerateFaviconURL(params_.page_url.GetOrigin()); 1675 // Takes ownership of the TemplateURL. 1676 search_engine_tab_helper->delegate()->ConfirmAddSearchProvider( 1677 new TemplateURL(data), GetProfile()); 1678 } 1679 break; 1680 } 1681 1682 default: 1683 NOTREACHED(); 1684 break; 1685 } 1686} 1687 1688ProtocolHandlerRegistry::ProtocolHandlerList 1689 RenderViewContextMenu::GetHandlersForLinkUrl() { 1690 ProtocolHandlerRegistry::ProtocolHandlerList handlers = 1691 protocol_handler_registry_->GetHandlersFor(params_.link_url.scheme()); 1692 std::sort(handlers.begin(), handlers.end()); 1693 return handlers; 1694} 1695 1696void RenderViewContextMenu::NotifyMenuShown() { 1697 content::NotificationService::current()->Notify( 1698 chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN, 1699 content::Source<RenderViewContextMenu>(this), 1700 content::NotificationService::NoDetails()); 1701} 1702 1703void RenderViewContextMenu::NotifyURLOpened( 1704 const GURL& url, 1705 content::WebContents* new_contents) { 1706 RetargetingDetails details; 1707 details.source_web_contents = source_web_contents_; 1708 // Don't use GetRenderFrameHost() as it may be NULL. crbug.com/399789 1709 details.source_render_frame_id = render_frame_id_; 1710 details.target_url = url; 1711 details.target_web_contents = new_contents; 1712 details.not_yet_in_tabstrip = false; 1713 1714 content::NotificationService::current()->Notify( 1715 chrome::NOTIFICATION_RETARGETING, 1716 content::Source<Profile>(GetProfile()), 1717 content::Details<RetargetingDetails>(&details)); 1718} 1719 1720bool RenderViewContextMenu::IsDevCommandEnabled(int id) const { 1721 if (id == IDC_CONTENT_CONTEXT_INSPECTELEMENT || 1722 id == IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE) { 1723 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 1724 if (!GetPrefs(browser_context_) 1725 ->GetBoolean(prefs::kWebKitJavascriptEnabled) || 1726 command_line->HasSwitch(switches::kDisableJavaScript)) 1727 return false; 1728 1729 // Don't enable the web inspector if the developer tools are disabled via 1730 // the preference dev-tools-disabled. 1731 if (GetPrefs(browser_context_)->GetBoolean(prefs::kDevToolsDisabled)) 1732 return false; 1733 } 1734 1735 return true; 1736} 1737 1738base::string16 RenderViewContextMenu::PrintableSelectionText() { 1739 return gfx::TruncateString(params_.selection_text, 1740 kMaxSelectionTextLength, 1741 gfx::WORD_BREAK); 1742} 1743 1744// Controller functions -------------------------------------------------------- 1745 1746void RenderViewContextMenu::CopyImageAt(int x, int y) { 1747 source_web_contents_->GetRenderViewHost()->CopyImageAt(x, y); 1748} 1749 1750void RenderViewContextMenu::GetImageThumbnailForSearch() { 1751 RenderFrameHost* render_frame_host = GetRenderFrameHost(); 1752 if (!render_frame_host) 1753 return; 1754 render_frame_host->Send(new ChromeViewMsg_RequestThumbnailForContextNode( 1755 render_frame_host->GetRoutingID(), 1756 kImageSearchThumbnailMinSize, 1757 gfx::Size(kImageSearchThumbnailMaxWidth, 1758 kImageSearchThumbnailMaxHeight))); 1759} 1760 1761void RenderViewContextMenu::Inspect(int x, int y) { 1762 content::RecordAction(UserMetricsAction("DevTools_InspectElement")); 1763 RenderFrameHost* render_frame_host = GetRenderFrameHost(); 1764 if (!render_frame_host) 1765 return; 1766 DevToolsWindow::InspectElement( 1767 WebContents::FromRenderFrameHost(render_frame_host), x, y); 1768} 1769 1770void RenderViewContextMenu::WriteURLToClipboard(const GURL& url) { 1771 chrome_common_net::WriteURLToClipboard( 1772 url, GetPrefs(browser_context_)->GetString(prefs::kAcceptLanguages)); 1773} 1774 1775void RenderViewContextMenu::MediaPlayerActionAt( 1776 const gfx::Point& location, 1777 const WebMediaPlayerAction& action) { 1778 source_web_contents_->GetRenderViewHost()-> 1779 ExecuteMediaPlayerActionAtLocation(location, action); 1780} 1781 1782void RenderViewContextMenu::PluginActionAt( 1783 const gfx::Point& location, 1784 const WebPluginAction& action) { 1785 source_web_contents_->GetRenderViewHost()-> 1786 ExecutePluginActionAtLocation(location, action); 1787} 1788