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 "chrome/browser/renderer_context_menu/render_view_context_menu.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 using extensions::Extension; | 135 using extensions::Extension; |
136 using extensions::MenuItem; | 136 using extensions::MenuItem; |
137 using extensions::MenuManager; | 137 using extensions::MenuManager; |
138 | 138 |
139 namespace { | 139 namespace { |
140 | 140 |
141 const int kImageSearchThumbnailMinSize = 300 * 300; | 141 const int kImageSearchThumbnailMinSize = 300 * 300; |
142 const int kImageSearchThumbnailMaxWidth = 600; | 142 const int kImageSearchThumbnailMaxWidth = 600; |
143 const int kImageSearchThumbnailMaxHeight = 600; | 143 const int kImageSearchThumbnailMaxHeight = 600; |
144 | 144 |
145 // The range of command IDs reserved for content's custom menus. | |
146 // TODO(oshima): These values will be injected by embedders. | |
147 const int content_context_custom_first = IDC_CONTENT_CONTEXT_CUSTOM_FIRST; | |
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 | 145 // Maps UMA enumeration to IDC. IDC could be changed so we can't use |
151 // just them and |UMA_HISTOGRAM_CUSTOM_ENUMERATION|. | 146 // just them and |UMA_HISTOGRAM_CUSTOM_ENUMERATION|. |
152 // Never change mapping or reuse |enum_id|. Always push back new items. | 147 // Never change mapping or reuse |enum_id|. Always push back new items. |
153 // Items that is not used any more by |RenderViewContextMenu.ExecuteCommand| | 148 // Items that is not used any more by |RenderViewContextMenu.ExecuteCommand| |
154 // could be deleted, but don't change the rest of |kUmaEnumToControlId|. | 149 // could be deleted, but don't change the rest of |kUmaEnumToControlId|. |
155 const struct UmaEnumCommandIdPair { | 150 const struct UmaEnumCommandIdPair { |
156 int enum_id; | 151 int enum_id; |
157 int control_id; | 152 int control_id; |
158 } kUmaEnumToControlId[] = { | 153 } kUmaEnumToControlId[] = { |
159 /* | 154 /* |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
255 id = CollapseCommandsForUMA(id); | 250 id = CollapseCommandsForUMA(id); |
256 const size_t kMappingSize = arraysize(kUmaEnumToControlId); | 251 const size_t kMappingSize = arraysize(kUmaEnumToControlId); |
257 for (size_t i = 0; i < kMappingSize; ++i) { | 252 for (size_t i = 0; i < kMappingSize; ++i) { |
258 if (kUmaEnumToControlId[i].control_id == id) { | 253 if (kUmaEnumToControlId[i].control_id == id) { |
259 return kUmaEnumToControlId[i].enum_id; | 254 return kUmaEnumToControlId[i].enum_id; |
260 } | 255 } |
261 } | 256 } |
262 return -1; | 257 return -1; |
263 } | 258 } |
264 | 259 |
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, | 260 // Usually a new tab is expected where this function is used, |
292 // however users should be able to open a tab in background | 261 // however users should be able to open a tab in background |
293 // or in a new window. | 262 // or in a new window. |
294 WindowOpenDisposition ForceNewTabDispositionFromEventFlags( | 263 WindowOpenDisposition ForceNewTabDispositionFromEventFlags( |
295 int event_flags) { | 264 int event_flags) { |
296 WindowOpenDisposition disposition = | 265 WindowOpenDisposition disposition = |
297 ui::DispositionFromEventFlags(event_flags); | 266 ui::DispositionFromEventFlags(event_flags); |
298 return disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition; | 267 return disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition; |
299 } | 268 } |
300 | 269 |
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) { | |
304 int action_id = | |
305 RenderViewContextMenu::ConvertToContentCustomCommandId(items[i].action); | |
306 if (action_id == id) | |
307 return items[i].enabled; | |
308 if (items[i].type == content::MenuItem::SUBMENU) { | |
309 if (IsCustomItemEnabled(items[i].submenu, id)) | |
310 return true; | |
311 } | |
312 } | |
313 return false; | |
314 } | |
315 | |
316 bool IsCustomItemChecked(const std::vector<content::MenuItem>& items, int id) { | |
317 DCHECK(RenderViewContextMenu::IsContentCustomCommandId(id)); | |
318 for (size_t i = 0; i < items.size(); ++i) { | |
319 int action_id = | |
320 RenderViewContextMenu::ConvertToContentCustomCommandId(items[i].action); | |
321 if (action_id == id) | |
322 return items[i].checked; | |
323 if (items[i].type == content::MenuItem::SUBMENU) { | |
324 if (IsCustomItemChecked(items[i].submenu, id)) | |
325 return true; | |
326 } | |
327 } | |
328 return false; | |
329 } | |
330 | |
331 const size_t kMaxCustomMenuDepth = 5; | |
332 const size_t kMaxCustomMenuTotalItems = 1000; | |
333 | |
334 void AddCustomItemsToMenu(const std::vector<content::MenuItem>& items, | |
335 size_t depth, | |
336 size_t* total_items, | |
337 ui::SimpleMenuModel::Delegate* delegate, | |
338 ui::SimpleMenuModel* menu_model) { | |
339 if (depth > kMaxCustomMenuDepth) { | |
340 LOG(ERROR) << "Custom menu too deeply nested."; | |
341 return; | |
342 } | |
343 for (size_t i = 0; i < items.size(); ++i) { | |
344 int command_id = | |
345 RenderViewContextMenu::ConvertToContentCustomCommandId(items[i].action); | |
346 if (!RenderViewContextMenu::IsContentCustomCommandId(command_id)) { | |
347 LOG(ERROR) << "Custom menu action value out of range."; | |
348 return; | |
349 } | |
350 if (*total_items >= kMaxCustomMenuTotalItems) { | |
351 LOG(ERROR) << "Custom menu too large (too many items)."; | |
352 return; | |
353 } | |
354 (*total_items)++; | |
355 switch (items[i].type) { | |
356 case content::MenuItem::OPTION: | |
357 menu_model->AddItem( | |
358 RenderViewContextMenu::ConvertToContentCustomCommandId( | |
359 items[i].action), | |
360 items[i].label); | |
361 break; | |
362 case content::MenuItem::CHECKABLE_OPTION: | |
363 menu_model->AddCheckItem( | |
364 RenderViewContextMenu::ConvertToContentCustomCommandId( | |
365 items[i].action), | |
366 items[i].label); | |
367 break; | |
368 case content::MenuItem::GROUP: | |
369 // TODO(viettrungluu): I don't know what this is supposed to do. | |
370 NOTREACHED(); | |
371 break; | |
372 case content::MenuItem::SEPARATOR: | |
373 menu_model->AddSeparator(ui::NORMAL_SEPARATOR); | |
374 break; | |
375 case content::MenuItem::SUBMENU: { | |
376 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate); | |
377 AddCustomItemsToMenu(items[i].submenu, depth + 1, total_items, delegate, | |
378 submenu); | |
379 menu_model->AddSubMenu( | |
380 RenderViewContextMenu::ConvertToContentCustomCommandId( | |
381 items[i].action), | |
382 items[i].label, | |
383 submenu); | |
384 break; | |
385 } | |
386 default: | |
387 NOTREACHED(); | |
388 break; | |
389 } | |
390 } | |
391 } | |
392 | |
393 // Helper function to escape "&" as "&&". | 270 // Helper function to escape "&" as "&&". |
394 void EscapeAmpersands(base::string16* text) { | 271 void EscapeAmpersands(base::string16* text) { |
395 base::ReplaceChars(*text, base::ASCIIToUTF16("&"), base::ASCIIToUTF16("&&"), | 272 base::ReplaceChars(*text, base::ASCIIToUTF16("&"), base::ASCIIToUTF16("&&"), |
396 text); | 273 text); |
397 } | 274 } |
398 | 275 |
399 // Returns the preference of the profile represented by the |context|. | 276 // Returns the preference of the profile represented by the |context|. |
400 PrefService* GetPrefs(content::BrowserContext* context) { | 277 PrefService* GetPrefs(content::BrowserContext* context) { |
401 return user_prefs::UserPrefs::Get(context); | 278 return user_prefs::UserPrefs::Get(context); |
402 } | 279 } |
403 | 280 |
281 bool custom_id_ranges_initialized = false; | |
lazyboy
2014/08/01 07:59:34
rename to g_custom_id_ranges_initialized
oshima
2014/08/01 10:38:44
this is file scoped, not global.
lazyboy
2014/08/01 20:15:54
OK.
I have seen a lot g_ identifiers for file leve
| |
282 | |
404 } // namespace | 283 } // namespace |
405 | 284 |
406 // static | 285 // static |
407 const size_t RenderViewContextMenu::kMaxSelectionTextLength = 50; | |
408 | |
409 // static | |
410 int RenderViewContextMenu::ConvertToContentCustomCommandId(int id) { | |
411 return content_context_custom_first + id; | |
412 } | |
413 | |
414 // static | |
415 bool RenderViewContextMenu::IsContentCustomCommandId(int id) { | |
416 return id >= content_context_custom_first && | |
417 id <= content_context_custom_last; | |
418 } | |
419 | |
420 // static | |
421 bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) { | 286 bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) { |
422 return url.SchemeIs(content::kChromeDevToolsScheme); | 287 return url.SchemeIs(content::kChromeDevToolsScheme); |
423 } | 288 } |
424 | 289 |
425 // static | 290 // static |
426 bool RenderViewContextMenu::IsInternalResourcesURL(const GURL& url) { | 291 bool RenderViewContextMenu::IsInternalResourcesURL(const GURL& url) { |
427 if (!url.SchemeIs(content::kChromeUIScheme)) | 292 if (!url.SchemeIs(content::kChromeUIScheme)) |
428 return false; | 293 return false; |
429 return url.host() == chrome::kChromeUISyncResourcesHost; | 294 return url.host() == chrome::kChromeUISyncResourcesHost; |
430 } | 295 } |
431 | 296 |
432 static const int kSpellcheckRadioGroup = 1; | 297 static const int kSpellcheckRadioGroup = 1; |
433 | 298 |
434 RenderViewContextMenu::RenderViewContextMenu( | 299 RenderViewContextMenu::RenderViewContextMenu( |
435 content::RenderFrameHost* render_frame_host, | 300 content::RenderFrameHost* render_frame_host, |
436 const content::ContextMenuParams& params) | 301 const content::ContextMenuParams& params) |
437 : params_(params), | 302 : RenderViewContextMenuBase(render_frame_host, params), |
438 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()), | |
442 menu_model_(this), | |
443 extension_items_(browser_context_, | 303 extension_items_(browser_context_, |
444 this, | 304 this, |
445 &menu_model_, | 305 &menu_model_, |
446 base::Bind(MenuItemMatchesParams, params_)), | 306 base::Bind(MenuItemMatchesParams, params_)), |
447 protocol_handler_submenu_model_(this), | 307 protocol_handler_submenu_model_(this), |
448 protocol_handler_registry_( | 308 protocol_handler_registry_( |
449 ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())), | 309 ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())) { |
450 command_executed_(false) { | 310 if (!custom_id_ranges_initialized) { |
451 content_type_.reset(ContextMenuContentTypeFactory::Create( | 311 custom_id_ranges_initialized = true; |
452 source_web_contents_, params)); | 312 SetContentCustomCommandIdRange(IDC_CONTENT_CONTEXT_CUSTOM_FIRST, |
313 IDC_CONTENT_CONTEXT_CUSTOM_LAST); | |
314 } | |
315 set_content_type(ContextMenuContentTypeFactory::Create( | |
316 source_web_contents_, params)); | |
453 } | 317 } |
454 | 318 |
455 RenderViewContextMenu::~RenderViewContextMenu() { | 319 RenderViewContextMenu::~RenderViewContextMenu() { |
456 } | 320 } |
457 | 321 |
458 // Menu construction functions ------------------------------------------------- | 322 // Menu construction functions ------------------------------------------------- |
459 | 323 |
460 void RenderViewContextMenu::Init() { | |
461 InitMenu(); | |
462 if (toolkit_delegate_) | |
463 toolkit_delegate_->Init(&menu_model_); | |
464 } | |
465 | |
466 void RenderViewContextMenu::Cancel() { | |
467 if (toolkit_delegate_) | |
468 toolkit_delegate_->Cancel(); | |
469 } | |
470 | |
471 static bool ExtensionPatternMatch(const extensions::URLPatternSet& patterns, | 324 static bool ExtensionPatternMatch(const extensions::URLPatternSet& patterns, |
472 const GURL& url) { | 325 const GURL& url) { |
473 // No patterns means no restriction, so that implicitly matches. | 326 // No patterns means no restriction, so that implicitly matches. |
474 if (patterns.is_empty()) | 327 if (patterns.is_empty()) |
475 return true; | 328 return true; |
476 return patterns.MatchesURL(url); | 329 return patterns.MatchesURL(url); |
477 } | 330 } |
478 | 331 |
479 // static | 332 // static |
480 bool RenderViewContextMenu::ExtensionContextAndPatternMatch( | 333 bool RenderViewContextMenu::ExtensionContextAndPatternMatch( |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
608 // Only add extension items from this extension. | 461 // Only add extension items from this extension. |
609 int index = 0; | 462 int index = 0; |
610 const MenuItem::ExtensionKey key( | 463 const MenuItem::ExtensionKey key( |
611 extension->id(), WebViewGuest::GetViewInstanceId(source_web_contents_)); | 464 extension->id(), WebViewGuest::GetViewInstanceId(source_web_contents_)); |
612 extension_items_.AppendExtensionItems( | 465 extension_items_.AppendExtensionItems( |
613 key, PrintableSelectionText(), &index); | 466 key, PrintableSelectionText(), &index); |
614 } | 467 } |
615 } | 468 } |
616 | 469 |
617 void RenderViewContextMenu::InitMenu() { | 470 void RenderViewContextMenu::InitMenu() { |
618 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_CUSTOM)) { | 471 RenderViewContextMenuBase::InitMenu(); |
619 AppendCustomItems(); | |
620 | |
621 const bool has_selection = !params_.selection_text.empty(); | |
622 if (has_selection) { | |
623 // We will add more items if there's a selection, so add a separator. | |
624 // TODO(lazyboy): Clean up separator logic. | |
625 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); | |
626 } | |
627 } | |
628 | 472 |
629 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE)) | 473 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE)) |
630 AppendPageItems(); | 474 AppendPageItems(); |
631 | 475 |
632 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_FRAME)) { | 476 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_FRAME)) { |
633 // Merge in frame items with page items if we clicked within a frame that | 477 // Merge in frame items with page items if we clicked within a frame that |
634 // needs them. | 478 // needs them. |
635 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); | 479 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); |
636 AppendFrameItems(); | 480 AppendFrameItems(); |
637 } | 481 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
718 if (content_type_->SupportsGroup( | 562 if (content_type_->SupportsGroup( |
719 ContextMenuContentType::ITEM_GROUP_PRINT_PREVIEW)) { | 563 ContextMenuContentType::ITEM_GROUP_PRINT_PREVIEW)) { |
720 AppendPrintPreviewItems(); | 564 AppendPrintPreviewItems(); |
721 } | 565 } |
722 } | 566 } |
723 | 567 |
724 Profile* RenderViewContextMenu::GetProfile() { | 568 Profile* RenderViewContextMenu::GetProfile() { |
725 return Profile::FromBrowserContext(browser_context_); | 569 return Profile::FromBrowserContext(browser_context_); |
726 } | 570 } |
727 | 571 |
572 void RenderViewContextMenu::RecordUsedItem(int id) { | |
573 int enum_id = FindUMAEnumValueForCommand(id); | |
574 if (enum_id != -1) { | |
575 const size_t kMappingSize = arraysize(kUmaEnumToControlId); | |
576 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Used", enum_id, | |
577 kUmaEnumToControlId[kMappingSize - 1].enum_id); | |
578 } else { | |
579 NOTREACHED() << "Update kUmaEnumToControlId. Unhanded IDC: " << id; | |
580 } | |
581 } | |
582 | |
583 void RenderViewContextMenu::RecordShownItem(int id) { | |
584 int enum_id = FindUMAEnumValueForCommand(id); | |
585 if (enum_id != -1) { | |
586 const size_t kMappingSize = arraysize(kUmaEnumToControlId); | |
587 UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Shown", enum_id, | |
588 kUmaEnumToControlId[kMappingSize - 1].enum_id); | |
589 } else { | |
590 // Just warning here. It's harder to maintain list of all possibly | |
591 // visible items than executable items. | |
592 DLOG(ERROR) << "Update kUmaEnumToControlId. Unhanded IDC: " << id; | |
593 } | |
594 } | |
595 | |
596 void RenderViewContextMenu::HandleAuthorizeAllPlugins() { | |
597 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins( | |
598 source_web_contents_, false, std::string()); | |
599 } | |
600 | |
728 void RenderViewContextMenu::AppendPrintPreviewItems() { | 601 void RenderViewContextMenu::AppendPrintPreviewItems() { |
729 #if defined(ENABLE_FULL_PRINTING) | 602 #if defined(ENABLE_FULL_PRINTING) |
730 if (!print_preview_menu_observer_.get()) { | 603 if (!print_preview_menu_observer_.get()) { |
731 print_preview_menu_observer_.reset( | 604 print_preview_menu_observer_.reset( |
732 new PrintPreviewContextMenuObserver(source_web_contents_)); | 605 new PrintPreviewContextMenuObserver(source_web_contents_)); |
733 } | 606 } |
734 | 607 |
735 observers_.AddObserver(print_preview_menu_observer_.get()); | 608 observers_.AddObserver(print_preview_menu_observer_.get()); |
736 #endif | 609 #endif |
737 } | 610 } |
738 | 611 |
739 const Extension* RenderViewContextMenu::GetExtension() const { | 612 const Extension* RenderViewContextMenu::GetExtension() const { |
740 extensions::ExtensionSystem* system = | 613 extensions::ExtensionSystem* system = |
741 extensions::ExtensionSystem::Get(browser_context_); | 614 extensions::ExtensionSystem::Get(browser_context_); |
742 // There is no process manager in some tests. | 615 // There is no process manager in some tests. |
743 if (!system->process_manager()) | 616 if (!system->process_manager()) |
744 return NULL; | 617 return NULL; |
745 | 618 |
746 return system->process_manager()->GetExtensionForRenderViewHost( | 619 return system->process_manager()->GetExtensionForRenderViewHost( |
747 source_web_contents_->GetRenderViewHost()); | 620 source_web_contents_->GetRenderViewHost()); |
748 } | 621 } |
749 | 622 |
750 void RenderViewContextMenu::AddMenuItem(int command_id, | |
751 const base::string16& title) { | |
752 menu_model_.AddItem(command_id, title); | |
753 } | |
754 | |
755 void RenderViewContextMenu::AddCheckItem(int command_id, | |
756 const base::string16& title) { | |
757 menu_model_.AddCheckItem(command_id, title); | |
758 } | |
759 | |
760 void RenderViewContextMenu::AddSeparator() { | |
761 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); | |
762 } | |
763 | |
764 void RenderViewContextMenu::AddSubMenu(int command_id, | |
765 const base::string16& label, | |
766 ui::MenuModel* model) { | |
767 menu_model_.AddSubMenu(command_id, label, model); | |
768 } | |
769 | |
770 void RenderViewContextMenu::UpdateMenuItem(int command_id, | |
771 bool enabled, | |
772 bool hidden, | |
773 const base::string16& label) { | |
774 if (toolkit_delegate_) { | |
775 toolkit_delegate_->UpdateMenuItem(command_id, | |
776 enabled, | |
777 hidden, | |
778 label); | |
779 } | |
780 } | |
781 | |
782 RenderViewHost* RenderViewContextMenu::GetRenderViewHost() const { | |
783 return source_web_contents_->GetRenderViewHost(); | |
784 } | |
785 | |
786 WebContents* RenderViewContextMenu::GetWebContents() const { | |
787 return source_web_contents_; | |
788 } | |
789 | |
790 BrowserContext* RenderViewContextMenu::GetBrowserContext() const { | |
791 return browser_context_; | |
792 } | |
793 | |
794 bool RenderViewContextMenu::AppendCustomItems() { | |
795 size_t total_items = 0; | |
796 AddCustomItemsToMenu(params_.custom_items, 0, &total_items, this, | |
797 &menu_model_); | |
798 return total_items > 0; | |
799 } | |
800 | |
801 void RenderViewContextMenu::AppendDeveloperItems() { | 623 void RenderViewContextMenu::AppendDeveloperItems() { |
802 // Show Inspect Element in DevTools itself only in case of the debug | 624 // Show Inspect Element in DevTools itself only in case of the debug |
803 // devtools build. | 625 // devtools build. |
804 bool show_developer_items = !IsDevToolsURL(params_.page_url); | 626 bool show_developer_items = !IsDevToolsURL(params_.page_url); |
805 | 627 |
806 #if defined(DEBUG_DEVTOOLS) | 628 #if defined(DEBUG_DEVTOOLS) |
807 show_developer_items = true; | 629 show_developer_items = true; |
808 #endif | 630 #endif |
809 | 631 |
810 if (!show_developer_items) | 632 if (!show_developer_items) |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1119 protocol_handler_submenu_model_.AddItem( | 941 protocol_handler_submenu_model_.AddItem( |
1120 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS, | 942 IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS, |
1121 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH_CONFIGURE)); | 943 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH_CONFIGURE)); |
1122 | 944 |
1123 menu_model_.AddSubMenu( | 945 menu_model_.AddSubMenu( |
1124 IDC_CONTENT_CONTEXT_OPENLINKWITH, | 946 IDC_CONTENT_CONTEXT_OPENLINKWITH, |
1125 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH), | 947 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_OPENLINKWITH), |
1126 &protocol_handler_submenu_model_); | 948 &protocol_handler_submenu_model_); |
1127 } | 949 } |
1128 | 950 |
1129 void RenderViewContextMenu::AppendPlatformEditableItems() { | |
1130 } | |
1131 | |
1132 // Menu delegate functions ----------------------------------------------------- | 951 // Menu delegate functions ----------------------------------------------------- |
1133 | 952 |
1134 bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { | 953 bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { |
1135 // If this command is is added by one of our observers, we dispatch it to the | 954 if (RenderViewContextMenuBase::IsCommandIdEnabled(id)) |
1136 // observer. | 955 return true; |
1137 ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_); | |
1138 RenderViewContextMenuObserver* observer; | |
1139 while ((observer = it.GetNext()) != NULL) { | |
1140 if (observer->IsCommandIdSupported(id)) | |
1141 return observer->IsCommandIdEnabled(id); | |
1142 } | |
1143 | 956 |
1144 CoreTabHelper* core_tab_helper = | 957 CoreTabHelper* core_tab_helper = |
1145 CoreTabHelper::FromWebContents(source_web_contents_); | 958 CoreTabHelper::FromWebContents(source_web_contents_); |
1146 int content_restrictions = 0; | 959 int content_restrictions = 0; |
1147 if (core_tab_helper) | 960 if (core_tab_helper) |
1148 content_restrictions = core_tab_helper->content_restrictions(); | 961 content_restrictions = core_tab_helper->content_restrictions(); |
1149 if (id == IDC_PRINT && (content_restrictions & CONTENT_RESTRICTION_PRINT)) | 962 if (id == IDC_PRINT && (content_restrictions & CONTENT_RESTRICTION_PRINT)) |
1150 return false; | 963 return false; |
1151 | 964 |
1152 if (id == IDC_SAVE_PAGE && | 965 if (id == IDC_SAVE_PAGE && |
1153 (content_restrictions & CONTENT_RESTRICTION_SAVE)) { | 966 (content_restrictions & CONTENT_RESTRICTION_SAVE)) { |
1154 return false; | 967 return false; |
1155 } | 968 } |
1156 | 969 |
1157 PrefService* prefs = GetPrefs(browser_context_); | 970 PrefService* prefs = GetPrefs(browser_context_); |
1158 | 971 |
1159 // Allow Spell Check language items on sub menu for text area context menu. | 972 // Allow Spell Check language items on sub menu for text area context menu. |
1160 if ((id >= IDC_SPELLCHECK_LANGUAGES_FIRST) && | 973 if ((id >= IDC_SPELLCHECK_LANGUAGES_FIRST) && |
1161 (id < IDC_SPELLCHECK_LANGUAGES_LAST)) { | 974 (id < IDC_SPELLCHECK_LANGUAGES_LAST)) { |
1162 return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck); | 975 return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck); |
1163 } | 976 } |
1164 | 977 |
1165 // Custom items. | |
1166 if (IsContentCustomCommandId(id)) | |
1167 return IsCustomItemEnabled(params_.custom_items, id); | |
1168 | |
1169 // Extension items. | 978 // Extension items. |
1170 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) | 979 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) |
1171 return extension_items_.IsCommandIdEnabled(id); | 980 return extension_items_.IsCommandIdEnabled(id); |
1172 | 981 |
1173 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST && | 982 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST && |
1174 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) { | 983 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) { |
1175 return true; | 984 return true; |
1176 } | 985 } |
1177 | 986 |
1178 IncognitoModePrefs::Availability incognito_avail = | 987 IncognitoModePrefs::Availability incognito_avail = |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1421 case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS: | 1230 case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS: |
1422 return true; | 1231 return true; |
1423 | 1232 |
1424 default: | 1233 default: |
1425 NOTREACHED(); | 1234 NOTREACHED(); |
1426 return false; | 1235 return false; |
1427 } | 1236 } |
1428 } | 1237 } |
1429 | 1238 |
1430 bool RenderViewContextMenu::IsCommandIdChecked(int id) const { | 1239 bool RenderViewContextMenu::IsCommandIdChecked(int id) const { |
1431 // If this command is is added by one of our observers, we dispatch it to the | 1240 if (RenderViewContextMenuBase::IsCommandIdChecked(id)) |
1432 // observer. | 1241 return true; |
1433 ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_); | |
1434 RenderViewContextMenuObserver* observer; | |
1435 while ((observer = it.GetNext()) != NULL) { | |
1436 if (observer->IsCommandIdSupported(id)) | |
1437 return observer->IsCommandIdChecked(id); | |
1438 } | |
1439 | 1242 |
1440 // See if the video is set to looping. | 1243 // See if the video is set to looping. |
1441 if (id == IDC_CONTENT_CONTEXT_LOOP) { | 1244 if (id == IDC_CONTENT_CONTEXT_LOOP) { |
1442 return (params_.media_flags & | 1245 return (params_.media_flags & |
1443 WebContextMenuData::MediaLoop) != 0; | 1246 WebContextMenuData::MediaLoop) != 0; |
1444 } | 1247 } |
1445 | 1248 |
1446 if (id == IDC_CONTENT_CONTEXT_CONTROLS) { | 1249 if (id == IDC_CONTENT_CONTEXT_CONTROLS) { |
1447 return (params_.media_flags & | 1250 return (params_.media_flags & |
1448 WebContextMenuData::MediaControls) != 0; | 1251 WebContextMenuData::MediaControls) != 0; |
1449 } | 1252 } |
1450 | 1253 |
1451 // Custom items. | |
1452 if (IsContentCustomCommandId(id)) | |
1453 return IsCustomItemChecked(params_.custom_items, id); | |
1454 | |
1455 // Extension items. | 1254 // Extension items. |
1456 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) | 1255 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) |
1457 return extension_items_.IsCommandIdChecked(id); | 1256 return extension_items_.IsCommandIdChecked(id); |
1458 | 1257 |
1459 return false; | 1258 return false; |
1460 } | 1259 } |
1461 | 1260 |
1462 void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { | 1261 void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { |
1262 RenderViewContextMenuBase::ExecuteCommand(id, event_flags); | |
1263 if (command_executed_) | |
1264 return; | |
1463 command_executed_ = true; | 1265 command_executed_ = true; |
1464 RecordUsedItem(id); | |
1465 | 1266 |
1466 // If this command is is added by one of our observers, we dispatch it to the | 1267 RenderFrameHost* render_frame_host = GetRenderFrameHost(); |
1467 // observer. | |
1468 ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_); | |
1469 RenderViewContextMenuObserver* observer; | |
1470 while ((observer = it.GetNext()) != NULL) { | |
1471 if (observer->IsCommandIdSupported(id)) | |
1472 return observer->ExecuteCommand(id); | |
1473 } | |
1474 | |
1475 RenderFrameHost* render_frame_host = | |
1476 RenderFrameHost::FromID(render_process_id_, render_frame_id_); | |
1477 | |
1478 // Process custom actions range. | |
1479 if (IsContentCustomCommandId(id)) { | |
1480 unsigned action = id - content_context_custom_first; | |
1481 const content::CustomContextMenuContext& context = params_.custom_context; | |
1482 #if defined(ENABLE_PLUGINS) | |
1483 if (context.request_id && !context.is_pepper_menu) { | |
1484 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins( | |
1485 source_web_contents_, false, std::string()); | |
1486 } | |
1487 #endif | |
1488 source_web_contents_->ExecuteCustomContextMenuCommand(action, context); | |
1489 return; | |
1490 } | |
1491 | 1268 |
1492 // Process extension menu items. | 1269 // Process extension menu items. |
1493 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) { | 1270 if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) { |
1494 extension_items_.ExecuteCommand(id, source_web_contents_, params_); | 1271 extension_items_.ExecuteCommand(id, source_web_contents_, params_); |
1495 return; | 1272 return; |
1496 } | 1273 } |
1497 | 1274 |
1498 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST && | 1275 if (id >= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST && |
1499 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) { | 1276 id <= IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST) { |
1500 ProtocolHandlerRegistry::ProtocolHandlerList handlers = | 1277 ProtocolHandlerRegistry::ProtocolHandlerList handlers = |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1902 } | 1679 } |
1903 | 1680 |
1904 ProtocolHandlerRegistry::ProtocolHandlerList | 1681 ProtocolHandlerRegistry::ProtocolHandlerList |
1905 RenderViewContextMenu::GetHandlersForLinkUrl() { | 1682 RenderViewContextMenu::GetHandlersForLinkUrl() { |
1906 ProtocolHandlerRegistry::ProtocolHandlerList handlers = | 1683 ProtocolHandlerRegistry::ProtocolHandlerList handlers = |
1907 protocol_handler_registry_->GetHandlersFor(params_.link_url.scheme()); | 1684 protocol_handler_registry_->GetHandlersFor(params_.link_url.scheme()); |
1908 std::sort(handlers.begin(), handlers.end()); | 1685 std::sort(handlers.begin(), handlers.end()); |
1909 return handlers; | 1686 return handlers; |
1910 } | 1687 } |
1911 | 1688 |
1912 void RenderViewContextMenu::MenuWillShow(ui::SimpleMenuModel* source) { | 1689 void RenderViewContextMenu::NotifyMenuShown() { |
1913 for (int i = 0; i < source->GetItemCount(); ++i) { | |
1914 if (source->IsVisibleAt(i) && | |
1915 source->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR) { | |
1916 RecordShownItem(source->GetCommandIdAt(i)); | |
1917 } | |
1918 } | |
1919 | |
1920 // Ignore notifications from submenus. | |
1921 if (source != &menu_model_) | |
1922 return; | |
1923 | |
1924 content::RenderWidgetHostView* view = | |
1925 source_web_contents_->GetRenderWidgetHostView(); | |
1926 if (view) | |
1927 view->SetShowingContextMenu(true); | |
1928 | |
1929 content::NotificationService::current()->Notify( | 1690 content::NotificationService::current()->Notify( |
1930 chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN, | 1691 chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN, |
1931 content::Source<RenderViewContextMenu>(this), | 1692 content::Source<RenderViewContextMenu>(this), |
1932 content::NotificationService::NoDetails()); | 1693 content::NotificationService::NoDetails()); |
1933 } | 1694 } |
1934 | 1695 |
1935 void RenderViewContextMenu::MenuClosed(ui::SimpleMenuModel* source) { | 1696 void RenderViewContextMenu::NotifyURLOpened( |
1936 // Ignore notifications from submenus. | 1697 const GURL& url, |
1937 if (source != &menu_model_) | 1698 content::WebContents* new_contents) { |
1938 return; | 1699 RetargetingDetails details; |
1700 details.source_web_contents = source_web_contents_; | |
1701 details.source_render_frame_id = GetRenderFrameHost()->GetRoutingID(); | |
1702 details.target_url = url; | |
1703 details.target_web_contents = new_contents; | |
1704 details.not_yet_in_tabstrip = false; | |
1939 | 1705 |
1940 content::RenderWidgetHostView* view = | 1706 content::NotificationService::current()->Notify( |
1941 source_web_contents_->GetRenderWidgetHostView(); | 1707 chrome::NOTIFICATION_RETARGETING, |
1942 if (view) | 1708 content::Source<Profile>(GetProfile()), |
1943 view->SetShowingContextMenu(false); | 1709 content::Details<RetargetingDetails>(&details)); |
1944 source_web_contents_->NotifyContextMenuClosed(params_.custom_context); | |
1945 | |
1946 if (!command_executed_) { | |
1947 FOR_EACH_OBSERVER(RenderViewContextMenuObserver, | |
1948 observers_, | |
1949 OnMenuCancel()); | |
1950 } | |
1951 } | 1710 } |
1952 | 1711 |
1953 bool RenderViewContextMenu::IsDevCommandEnabled(int id) const { | 1712 bool RenderViewContextMenu::IsDevCommandEnabled(int id) const { |
1954 if (id == IDC_CONTENT_CONTEXT_INSPECTELEMENT || | 1713 if (id == IDC_CONTENT_CONTEXT_INSPECTELEMENT || |
1955 id == IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE) { | 1714 id == IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE) { |
1956 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 1715 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
1957 if (!GetPrefs(browser_context_) | 1716 if (!GetPrefs(browser_context_) |
1958 ->GetBoolean(prefs::kWebKitJavascriptEnabled) || | 1717 ->GetBoolean(prefs::kWebKitJavascriptEnabled) || |
1959 command_line->HasSwitch(switches::kDisableJavaScript)) | 1718 command_line->HasSwitch(switches::kDisableJavaScript)) |
1960 return false; | 1719 return false; |
1961 | 1720 |
1962 // Don't enable the web inspector if the developer tools are disabled via | 1721 // Don't enable the web inspector if the developer tools are disabled via |
1963 // the preference dev-tools-disabled. | 1722 // the preference dev-tools-disabled. |
1964 if (GetPrefs(browser_context_)->GetBoolean(prefs::kDevToolsDisabled)) | 1723 if (GetPrefs(browser_context_)->GetBoolean(prefs::kDevToolsDisabled)) |
1965 return false; | 1724 return false; |
1966 } | 1725 } |
1967 | 1726 |
1968 return true; | 1727 return true; |
1969 } | 1728 } |
1970 | 1729 |
1971 base::string16 RenderViewContextMenu::PrintableSelectionText() { | 1730 base::string16 RenderViewContextMenu::PrintableSelectionText() { |
1972 return gfx::TruncateString(params_.selection_text, | 1731 return gfx::TruncateString(params_.selection_text, |
1973 kMaxSelectionTextLength, | 1732 kMaxSelectionTextLength, |
1974 gfx::WORD_BREAK); | 1733 gfx::WORD_BREAK); |
1975 } | 1734 } |
1976 | 1735 |
1977 // Controller functions -------------------------------------------------------- | 1736 // Controller functions -------------------------------------------------------- |
1978 | 1737 |
1979 void RenderViewContextMenu::OpenURL( | |
1980 const GURL& url, const GURL& referring_url, | |
1981 WindowOpenDisposition disposition, | |
1982 content::PageTransition transition) { | |
1983 content::Referrer referrer(referring_url.GetAsReferrer(), | |
1984 params_.referrer_policy); | |
1985 | |
1986 if (params_.link_url == url && disposition != OFF_THE_RECORD) | |
1987 params_.custom_context.link_followed = url; | |
1988 | |
1989 WebContents* new_contents = source_web_contents_->OpenURL(OpenURLParams( | |
1990 url, referrer, disposition, transition, false)); | |
1991 if (!new_contents) | |
1992 return; | |
1993 | |
1994 RetargetingDetails details; | |
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 } | |
2005 | |
2006 void RenderViewContextMenu::CopyImageAt(int x, int y) { | 1738 void RenderViewContextMenu::CopyImageAt(int x, int y) { |
2007 source_web_contents_->GetRenderViewHost()->CopyImageAt(x, y); | 1739 source_web_contents_->GetRenderViewHost()->CopyImageAt(x, y); |
2008 } | 1740 } |
2009 | 1741 |
2010 void RenderViewContextMenu::GetImageThumbnailForSearch() { | 1742 void RenderViewContextMenu::GetImageThumbnailForSearch() { |
2011 RenderFrameHost* render_frame_host = | 1743 RenderFrameHost* render_frame_host = GetRenderFrameHost(); |
2012 RenderFrameHost::FromID(render_process_id_, render_frame_id_); | |
2013 if (!render_frame_host) | 1744 if (!render_frame_host) |
2014 return; | 1745 return; |
2015 render_frame_host->Send(new ChromeViewMsg_RequestThumbnailForContextNode( | 1746 render_frame_host->Send(new ChromeViewMsg_RequestThumbnailForContextNode( |
2016 render_frame_host->GetRoutingID(), | 1747 render_frame_host->GetRoutingID(), |
2017 kImageSearchThumbnailMinSize, | 1748 kImageSearchThumbnailMinSize, |
2018 gfx::Size(kImageSearchThumbnailMaxWidth, | 1749 gfx::Size(kImageSearchThumbnailMaxWidth, |
2019 kImageSearchThumbnailMaxHeight))); | 1750 kImageSearchThumbnailMaxHeight))); |
2020 } | 1751 } |
2021 | 1752 |
2022 void RenderViewContextMenu::Inspect(int x, int y) { | 1753 void RenderViewContextMenu::Inspect(int x, int y) { |
2023 content::RecordAction(UserMetricsAction("DevTools_InspectElement")); | 1754 content::RecordAction(UserMetricsAction("DevTools_InspectElement")); |
2024 RenderFrameHost* render_frame_host = | 1755 RenderFrameHost* render_frame_host = GetRenderFrameHost(); |
2025 RenderFrameHost::FromID(render_process_id_, render_frame_id_); | |
2026 if (!render_frame_host) | 1756 if (!render_frame_host) |
2027 return; | 1757 return; |
2028 DevToolsWindow::InspectElement(render_frame_host->GetRenderViewHost(), x, y); | 1758 DevToolsWindow::InspectElement(render_frame_host->GetRenderViewHost(), x, y); |
2029 } | 1759 } |
2030 | 1760 |
2031 void RenderViewContextMenu::WriteURLToClipboard(const GURL& url) { | 1761 void RenderViewContextMenu::WriteURLToClipboard(const GURL& url) { |
2032 chrome_common_net::WriteURLToClipboard( | 1762 chrome_common_net::WriteURLToClipboard( |
2033 url, | 1763 url, |
2034 GetPrefs(browser_context_)->GetString(prefs::kAcceptLanguages), | 1764 GetPrefs(browser_context_)->GetString(prefs::kAcceptLanguages), |
2035 ui::Clipboard::GetForCurrentThread()); | 1765 ui::Clipboard::GetForCurrentThread()); |
2036 } | 1766 } |
2037 | 1767 |
2038 void RenderViewContextMenu::MediaPlayerActionAt( | 1768 void RenderViewContextMenu::MediaPlayerActionAt( |
2039 const gfx::Point& location, | 1769 const gfx::Point& location, |
2040 const WebMediaPlayerAction& action) { | 1770 const WebMediaPlayerAction& action) { |
2041 source_web_contents_->GetRenderViewHost()-> | 1771 source_web_contents_->GetRenderViewHost()-> |
2042 ExecuteMediaPlayerActionAtLocation(location, action); | 1772 ExecuteMediaPlayerActionAtLocation(location, action); |
2043 } | 1773 } |
2044 | 1774 |
2045 void RenderViewContextMenu::PluginActionAt( | 1775 void RenderViewContextMenu::PluginActionAt( |
2046 const gfx::Point& location, | 1776 const gfx::Point& location, |
2047 const WebPluginAction& action) { | 1777 const WebPluginAction& action) { |
2048 source_web_contents_->GetRenderViewHost()-> | 1778 source_web_contents_->GetRenderViewHost()-> |
2049 ExecutePluginActionAtLocation(location, action); | 1779 ExecutePluginActionAtLocation(location, action); |
2050 } | 1780 } |
OLD | NEW |