Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: chrome/browser/tab_contents/render_view_context_menu.cc

Issue 6253017: Pepper/Flapper: First pass at context menu implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more browser-side sanity checking Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/renderer_host/render_view_host.cc ('k') | chrome/common/render_messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <algorithm> 5 #include <algorithm>
6 #include <set> 6 #include <set>
7 7
8 #include "chrome/browser/tab_contents/render_view_context_menu.h" 8 #include "chrome/browser/tab_contents/render_view_context_menu.h"
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 #include "net/url_request/url_request.h" 53 #include "net/url_request/url_request.h"
54 #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" 54 #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
55 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction. h" 55 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction. h"
56 #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h" 56 #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
57 #include "ui/base/l10n/l10n_util.h" 57 #include "ui/base/l10n/l10n_util.h"
58 #include "webkit/glue/webmenuitem.h" 58 #include "webkit/glue/webmenuitem.h"
59 59
60 using WebKit::WebContextMenuData; 60 using WebKit::WebContextMenuData;
61 using WebKit::WebMediaPlayerAction; 61 using WebKit::WebMediaPlayerAction;
62 62
63 namespace {
64
65 bool IsCustomItemEnabled(const std::vector<WebMenuItem>& items, int id) {
66 DCHECK(id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
67 id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST);
68 for (size_t i = 0; i < items.size(); ++i) {
69 int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action;
70 if (action_id == id)
71 return items[i].enabled;
72 if (items[i].type == WebMenuItem::SUBMENU) {
73 if (IsCustomItemEnabled(items[i].submenu, id))
74 return true;
75 }
76 }
77 return false;
78 }
79
80 bool IsCustomItemChecked(const std::vector<WebMenuItem>& items, int id) {
81 DCHECK(id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
82 id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST);
83 for (size_t i = 0; i < items.size(); ++i) {
84 int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action;
85 if (action_id == id)
86 return items[i].checked;
87 if (items[i].type == WebMenuItem::SUBMENU) {
88 if (IsCustomItemChecked(items[i].submenu, id))
89 return true;
90 }
91 }
92 return false;
93 }
94
95 const size_t kMaxCustomMenuDepth = 5;
96 const size_t kMaxCustomMenuTotalItems = 1000;
97
98 void AddCustomItemsToMenuHelper(const std::vector<WebMenuItem>& items,
99 size_t depth,
100 size_t* total_items,
101 ui::SimpleMenuModel::Delegate* delegate,
102 ui::SimpleMenuModel* menu_model) {
103 if (depth > kMaxCustomMenuDepth) {
104 LOG(ERROR) << "Custom menu too deeply nested.";
105 return;
106 }
107 for (size_t i = 0; i < items.size(); ++i) {
108 if (IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action >=
109 IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
110 LOG(ERROR) << "Custom menu action value too big.";
111 return;
112 }
113 (*total_items)++;
114 if (*total_items > kMaxCustomMenuTotalItems) {
115 LOG(ERROR) << "Custom menu too large (too many items).";
116 return;
117 }
118 switch (items[i].type) {
119 case WebMenuItem::OPTION:
120 menu_model->AddItem(
121 items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
122 items[i].label);
123 break;
124 case WebMenuItem::CHECKABLE_OPTION:
125 menu_model->AddCheckItem(
126 items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
127 items[i].label);
128 break;
129 case WebMenuItem::GROUP:
130 // TODO(viettrungluu): I don't know what this is supposed to do.
131 NOTREACHED();
132 break;
133 case WebMenuItem::SEPARATOR:
134 menu_model->AddSeparator();
135 break;
136 case WebMenuItem::SUBMENU: {
137 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate);
138 AddCustomItemsToMenuHelper(items[i].submenu, depth + 1, total_items,
139 delegate, submenu);
140 menu_model->AddSubMenu(
141 items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
142 items[i].label,
143 submenu);
144 break;
145 }
146 default:
147 NOTREACHED();
148 break;
149 }
150 }
151 }
152
153 void AddCustomItemsToMenu(const std::vector<WebMenuItem>& items,
brettw 2011/01/31 20:40:49 It seems like this is unnecessary.
154 ui::SimpleMenuModel::Delegate* delegate,
155 ui::SimpleMenuModel* menu_model) {
156 size_t total_items = 0;
157 AddCustomItemsToMenuHelper(items, 0, &total_items, delegate, menu_model);
158 }
159
160 } // namespace
161
63 // static 162 // static
64 const size_t RenderViewContextMenu::kMaxExtensionItemTitleLength = 75; 163 const size_t RenderViewContextMenu::kMaxExtensionItemTitleLength = 75;
65 // static 164 // static
66 const size_t RenderViewContextMenu::kMaxSelectionTextLength = 50; 165 const size_t RenderViewContextMenu::kMaxSelectionTextLength = 50;
67 166
68 // static 167 // static
69 bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) { 168 bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) {
70 return url.SchemeIs(chrome::kChromeDevToolsScheme) && 169 return url.SchemeIs(chrome::kChromeDevToolsScheme) &&
71 url.host() == chrome::kChromeUIDevToolsHost; 170 url.host() == chrome::kChromeUIDevToolsHost;
72 } 171 }
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 UMA_HISTOGRAM_TIMES("Extensions.ContextMenus_BuildTime", 450 UMA_HISTOGRAM_TIMES("Extensions.ContextMenus_BuildTime",
352 base::TimeTicks::Now() - begin); 451 base::TimeTicks::Now() - begin);
353 UMA_HISTOGRAM_COUNTS("Extensions.ContextMenus_ItemCount", index); 452 UMA_HISTOGRAM_COUNTS("Extensions.ContextMenus_ItemCount", index);
354 } 453 }
355 454
356 void RenderViewContextMenu::InitMenu() { 455 void RenderViewContextMenu::InitMenu() {
357 bool has_link = !params_.link_url.is_empty(); 456 bool has_link = !params_.link_url.is_empty();
358 bool has_selection = !params_.selection_text.empty(); 457 bool has_selection = !params_.selection_text.empty();
359 458
360 if (AppendCustomItems()) { 459 if (AppendCustomItems()) {
361 AppendDeveloperItems(); 460 // Don't add items for Pepper menu.
461 if (!params_.custom_context.is_pepper_menu)
462 AppendDeveloperItems();
362 return; 463 return;
363 } 464 }
364 465
365 // When no special node or text is selected and selection has no link, 466 // When no special node or text is selected and selection has no link,
366 // show page items. 467 // show page items.
367 bool is_devtools = false; 468 bool is_devtools = false;
368 if (params_.media_type == WebContextMenuData::MediaTypeNone && 469 if (params_.media_type == WebContextMenuData::MediaTypeNone &&
369 !has_link && 470 !has_link &&
370 !params_.is_editable && 471 !params_.is_editable &&
371 !has_selection) { 472 !has_selection) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 518
418 AppendDeveloperItems(); 519 AppendDeveloperItems();
419 } 520 }
420 521
421 void RenderViewContextMenu::LookUpInDictionary() { 522 void RenderViewContextMenu::LookUpInDictionary() {
422 // Used only in the Mac port. 523 // Used only in the Mac port.
423 NOTREACHED(); 524 NOTREACHED();
424 } 525 }
425 526
426 bool RenderViewContextMenu::AppendCustomItems() { 527 bool RenderViewContextMenu::AppendCustomItems() {
427 std::vector<WebMenuItem>& custom_items = params_.custom_items; 528 AddCustomItemsToMenu(params_.custom_items, this, &menu_model_);
428 for (size_t i = 0; i < custom_items.size(); ++i) { 529 return params_.custom_items.size() > 0;
429 DCHECK(IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action <
430 IDC_CONTENT_CONTEXT_CUSTOM_LAST);
431 if (custom_items[i].type == WebMenuItem::SEPARATOR) {
432 menu_model_.AddSeparator();
433 } else if (custom_items[i].type == WebMenuItem::CHECKABLE_OPTION) {
434 menu_model_.AddCheckItem(
435 custom_items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
436 custom_items[i].label);
437 } else {
438 menu_model_.AddItem(
439 custom_items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
440 custom_items[i].label);
441 }
442 }
443 return custom_items.size() > 0;
444 } 530 }
445 531
446 void RenderViewContextMenu::AppendDeveloperItems() { 532 void RenderViewContextMenu::AppendDeveloperItems() {
447 if (g_browser_process->have_inspector_files()) { 533 if (g_browser_process->have_inspector_files()) {
448 // In the DevTools popup menu, "developer items" is normally the only 534 // In the DevTools popup menu, "developer items" is normally the only
449 // section, so omit the separator there. 535 // section, so omit the separator there.
450 if (menu_model_.GetItemCount() > 0) 536 if (menu_model_.GetItemCount() > 0)
451 menu_model_.AddSeparator(); 537 menu_model_.AddSeparator();
452 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_INSPECTELEMENT, 538 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_INSPECTELEMENT,
453 IDS_CONTENT_CONTEXT_INSPECTELEMENT); 539 IDS_CONTENT_CONTEXT_INSPECTELEMENT);
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 CONTENT_RESTRICTION_SAVE)) { 852 CONTENT_RESTRICTION_SAVE)) {
767 return false; 853 return false;
768 } 854 }
769 855
770 // Allow Spell Check language items on sub menu for text area context menu. 856 // Allow Spell Check language items on sub menu for text area context menu.
771 if ((id >= IDC_SPELLCHECK_LANGUAGES_FIRST) && 857 if ((id >= IDC_SPELLCHECK_LANGUAGES_FIRST) &&
772 (id < IDC_SPELLCHECK_LANGUAGES_LAST)) { 858 (id < IDC_SPELLCHECK_LANGUAGES_LAST)) {
773 return profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck); 859 return profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck);
774 } 860 }
775 861
776 // Process custom actions range. 862 // Custom items.
777 if ((id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST) &&
778 (id < IDC_CONTENT_CONTEXT_CUSTOM_LAST)) {
779 unsigned action = id - IDC_CONTENT_CONTEXT_CUSTOM_FIRST;
780 for (size_t i = 0; i < params_.custom_items.size(); ++i) {
781 if (params_.custom_items[i].action == action)
782 return params_.custom_items[i].enabled;
783 }
784 NOTREACHED();
785 return false;
786 }
787
788 // Custom WebKit items.
789 if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST && 863 if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
790 id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) { 864 id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
791 const std::vector<WebMenuItem>& custom_items = params_.custom_items; 865 return IsCustomItemEnabled(params_.custom_items, id);
792 for (size_t i = 0; i < custom_items.size(); ++i) {
793 int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action;
794 if (action_id == id)
795 return custom_items[i].enabled;
796 }
797 return true;
798 } 866 }
799 867
800 // Extension items. 868 // Extension items.
801 if (id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST && 869 if (id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
802 id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) { 870 id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
803 // In the future we may add APIs for extensions to disable items, but for 871 // In the future we may add APIs for extensions to disable items, but for
804 // now all items are implicitly enabled. 872 // now all items are implicitly enabled.
805 return true; 873 return true;
806 } 874 }
807 875
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 if (id == IDC_CONTENT_CONTEXT_LOOP) { 1081 if (id == IDC_CONTENT_CONTEXT_LOOP) {
1014 return (params_.media_flags & 1082 return (params_.media_flags &
1015 WebContextMenuData::MediaLoop) != 0; 1083 WebContextMenuData::MediaLoop) != 0;
1016 } 1084 }
1017 1085
1018 if (id == IDC_CONTENT_CONTEXT_CONTROLS) { 1086 if (id == IDC_CONTENT_CONTEXT_CONTROLS) {
1019 return (params_.media_flags & 1087 return (params_.media_flags &
1020 WebContextMenuData::MediaControls) != 0; 1088 WebContextMenuData::MediaControls) != 0;
1021 } 1089 }
1022 1090
1023 // Custom WebKit items. 1091 // Custom items.
1024 if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST && 1092 if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
1025 id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) { 1093 id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
1026 const std::vector<WebMenuItem>& custom_items = params_.custom_items; 1094 return IsCustomItemChecked(params_.custom_items, id);
1027 for (size_t i = 0; i < custom_items.size(); ++i) {
1028 int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action;
1029 if (action_id == id)
1030 return custom_items[i].checked;
1031 }
1032 return false;
1033 } 1095 }
1034 1096
1035 // Extension items. 1097 // Extension items.
1036 if (id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST && 1098 if (id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
1037 id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) { 1099 id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
1038 ExtensionMenuItem* item = GetExtensionMenuItem(id); 1100 ExtensionMenuItem* item = GetExtensionMenuItem(id);
1039 if (item) 1101 if (item)
1040 return item->checked(); 1102 return item->checked();
1041 else 1103 else
1042 return false; 1104 return false;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 if (language_number < languages.size()) { 1145 if (language_number < languages.size()) {
1084 StringPrefMember dictionary_language; 1146 StringPrefMember dictionary_language;
1085 dictionary_language.Init(prefs::kSpellCheckDictionary, 1147 dictionary_language.Init(prefs::kSpellCheckDictionary,
1086 profile_->GetPrefs(), NULL); 1148 profile_->GetPrefs(), NULL);
1087 dictionary_language.SetValue(languages[language_number]); 1149 dictionary_language.SetValue(languages[language_number]);
1088 } 1150 }
1089 return; 1151 return;
1090 } 1152 }
1091 1153
1092 // Process custom actions range. 1154 // Process custom actions range.
1093 if ((id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST) && 1155 if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
1094 (id < IDC_CONTENT_CONTEXT_CUSTOM_LAST)) { 1156 id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
1095 unsigned action = id - IDC_CONTENT_CONTEXT_CUSTOM_FIRST; 1157 unsigned action = id - IDC_CONTENT_CONTEXT_CUSTOM_FIRST;
1096 source_tab_contents_->render_view_host()-> 1158 source_tab_contents_->render_view_host()->PerformCustomContextMenuAction(
1097 PerformCustomContextMenuAction(action); 1159 params_.custom_context, action);
1098 return; 1160 return;
1099 } 1161 }
1100 1162
1101 // Process extension menu items. 1163 // Process extension menu items.
1102 if (id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST && 1164 if (id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
1103 id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) { 1165 id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
1104 ExtensionMenuManager* manager = 1166 ExtensionMenuManager* manager =
1105 profile_->GetExtensionService()->menu_manager(); 1167 profile_->GetExtensionService()->menu_manager();
1106 std::map<int, ExtensionMenuItem::Id>::const_iterator i = 1168 std::map<int, ExtensionMenuItem::Id>::const_iterator i =
1107 extension_item_map_.find(id); 1169 extension_item_map_.find(id);
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1392 break; 1454 break;
1393 #endif // OS_MACOSX 1455 #endif // OS_MACOSX
1394 1456
1395 default: 1457 default:
1396 NOTREACHED(); 1458 NOTREACHED();
1397 break; 1459 break;
1398 } 1460 }
1399 } 1461 }
1400 1462
1401 void RenderViewContextMenu::MenuClosed() { 1463 void RenderViewContextMenu::MenuClosed() {
1402 source_tab_contents_->render_view_host()->ContextMenuClosed(); 1464 source_tab_contents_->render_view_host()->ContextMenuClosed(
1465 params_.custom_context);
1403 } 1466 }
1404 1467
1405 bool RenderViewContextMenu::IsDevCommandEnabled(int id) const { 1468 bool RenderViewContextMenu::IsDevCommandEnabled(int id) const {
1406 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 1469 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1407 if (command_line.HasSwitch(switches::kAlwaysEnableDevTools)) 1470 if (command_line.HasSwitch(switches::kAlwaysEnableDevTools))
1408 return true; 1471 return true;
1409 1472
1410 NavigationEntry *active_entry = 1473 NavigationEntry *active_entry =
1411 source_tab_contents_->controller().GetActiveEntry(); 1474 source_tab_contents_->controller().GetActiveEntry();
1412 if (!active_entry) 1475 if (!active_entry)
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1472 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages), 1535 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
1473 g_browser_process->clipboard()); 1536 g_browser_process->clipboard());
1474 } 1537 }
1475 1538
1476 void RenderViewContextMenu::MediaPlayerActionAt( 1539 void RenderViewContextMenu::MediaPlayerActionAt(
1477 const gfx::Point& location, 1540 const gfx::Point& location,
1478 const WebMediaPlayerAction& action) { 1541 const WebMediaPlayerAction& action) {
1479 source_tab_contents_->render_view_host()->MediaPlayerActionAt( 1542 source_tab_contents_->render_view_host()->MediaPlayerActionAt(
1480 location, action); 1543 location, action);
1481 } 1544 }
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_view_host.cc ('k') | chrome/common/render_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698