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