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

Side by Side Diff: chrome/browser/extensions/context_menu_matcher.cc

Issue 359493005: Extend contextMenus API to support browser/page actions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Revert loop change in render_view_context_menu.cc Created 6 years, 4 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/extensions/context_menu_matcher.h" 5 #include "chrome/browser/extensions/context_menu_matcher.h"
6 6
7 #include "base/strings/utf_string_conversions.h" 7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/app/chrome_command_ids.h" 8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/extensions/extension_service.h" 9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_util.h" 10 #include "chrome/browser/extensions/extension_util.h"
11 #include "chrome/common/extensions/api/context_menus.h"
gpdavis 2014/08/05 01:02:13 This appears to be the cause of the failed trybots
Yoyo Zhou 2014/08/05 01:06:35 Yes, sort of. Move this to the bottom of the inclu
gpdavis 2014/08/05 01:52:28 Okay, cool. Don't I also need to wrap the code th
Yoyo Zhou 2014/08/05 02:16:52 Ah, sorry. Yes, you need to put that in an ifdef a
11 #include "content/public/browser/browser_context.h" 12 #include "content/public/browser/browser_context.h"
12 #include "content/public/common/context_menu_params.h" 13 #include "content/public/common/context_menu_params.h"
13 #include "extensions/browser/extension_system.h" 14 #include "extensions/browser/extension_system.h"
14 #include "ui/gfx/favicon_size.h" 15 #include "ui/gfx/favicon_size.h"
15 #include "ui/gfx/image/image.h" 16 #include "ui/gfx/image/image.h"
16 17
17 namespace extensions { 18 namespace extensions {
18 19
19 namespace { 20 namespace {
20 21
(...skipping 25 matching lines...) Expand all
46 const base::Callback<bool(const MenuItem*)>& filter) 47 const base::Callback<bool(const MenuItem*)>& filter)
47 : browser_context_(browser_context), 48 : browser_context_(browser_context),
48 menu_model_(menu_model), 49 menu_model_(menu_model),
49 delegate_(delegate), 50 delegate_(delegate),
50 filter_(filter) { 51 filter_(filter) {
51 } 52 }
52 53
53 void ContextMenuMatcher::AppendExtensionItems( 54 void ContextMenuMatcher::AppendExtensionItems(
54 const MenuItem::ExtensionKey& extension_key, 55 const MenuItem::ExtensionKey& extension_key,
55 const base::string16& selection_text, 56 const base::string16& selection_text,
56 int* index) { 57 int* index,
58 bool is_action_menu) {
57 DCHECK_GE(*index, 0); 59 DCHECK_GE(*index, 0);
58 int max_index = 60 int max_index =
59 extensions_context_custom_last - extensions_context_custom_first; 61 extensions_context_custom_last - extensions_context_custom_first;
60 if (*index >= max_index) 62 if (*index >= max_index)
61 return; 63 return;
62 64
63 const Extension* extension = NULL; 65 const Extension* extension = NULL;
64 MenuItem::List items; 66 MenuItem::List items;
65 bool can_cross_incognito; 67 bool can_cross_incognito;
66 if (!GetRelevantExtensionTopLevelItems( 68 if (!GetRelevantExtensionTopLevelItems(
67 extension_key, &extension, &can_cross_incognito, items)) 69 extension_key, &extension, &can_cross_incognito, items))
68 return; 70 return;
69 71
70 if (items.empty()) 72 if (items.empty())
71 return; 73 return;
72 74
73 // If this is the first extension-provided menu item, and there are other 75 // If this is the first extension-provided menu item, and there are other
74 // items in the menu, and the last item is not a separator add a separator. 76 // items in the menu, and the last item is not a separator add a separator.
75 if (*index == 0 && menu_model_->GetItemCount()) 77 if (*index == 0 && menu_model_->GetItemCount())
76 menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); 78 menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
77 79
78 // Extensions (other than platform apps) are only allowed one top-level slot 80 // Extensions (other than platform apps) are only allowed one top-level slot
79 // (and it can't be a radio or checkbox item because we are going to put the 81 // (and it can't be a radio or checkbox item because we are going to put the
80 // extension icon next to it). 82 // extension icon next to it), unless the context menu is an an action menu.
81 // If they have more than that, we automatically push them into a submenu. 83 // Action menus do not include the extension action, and they only include
82 if (extension->is_platform_app()) { 84 // items from one extension, so they are not placed within a submenu.
83 RecursivelyAppendExtensionItems(items, can_cross_incognito, selection_text, 85 // Otherwise, we automatically push them into a submenu if there is more than
84 menu_model_, index); 86 // one top-level item.
87 if (extension->is_platform_app() || is_action_menu) {
88 RecursivelyAppendExtensionItems(items,
89 can_cross_incognito,
90 selection_text,
91 menu_model_,
92 index,
93 is_action_menu);
85 } else { 94 } else {
86 int menu_id = ConvertToExtensionsCustomCommandId(*index); 95 int menu_id = ConvertToExtensionsCustomCommandId(*index);
87 (*index)++; 96 (*index)++;
88 base::string16 title; 97 base::string16 title;
89 MenuItem::List submenu_items; 98 MenuItem::List submenu_items;
90 99
91 if (items.size() > 1 || items[0]->type() != MenuItem::NORMAL) { 100 if (items.size() > 1 || items[0]->type() != MenuItem::NORMAL) {
92 title = base::UTF8ToUTF16(extension->name()); 101 title = base::UTF8ToUTF16(extension->name());
93 submenu_items = items; 102 submenu_items = items;
94 } else { 103 } else {
95 MenuItem* item = items[0]; 104 MenuItem* item = items[0];
96 extension_item_map_[menu_id] = item->id(); 105 extension_item_map_[menu_id] = item->id();
97 title = item->TitleWithReplacement(selection_text, 106 title = item->TitleWithReplacement(selection_text,
98 kMaxExtensionItemTitleLength); 107 kMaxExtensionItemTitleLength);
99 submenu_items = GetRelevantExtensionItems(item->children(), 108 submenu_items = GetRelevantExtensionItems(item->children(),
100 can_cross_incognito); 109 can_cross_incognito);
101 } 110 }
102 111
103 // Now add our item(s) to the menu_model_. 112 // Now add our item(s) to the menu_model_.
104 if (submenu_items.empty()) { 113 if (submenu_items.empty()) {
105 menu_model_->AddItem(menu_id, title); 114 menu_model_->AddItem(menu_id, title);
106 } else { 115 } else {
107 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_); 116 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_);
108 extension_menu_models_.push_back(submenu); 117 extension_menu_models_.push_back(submenu);
109 menu_model_->AddSubMenu(menu_id, title, submenu); 118 menu_model_->AddSubMenu(menu_id, title, submenu);
110 RecursivelyAppendExtensionItems(submenu_items, can_cross_incognito, 119 RecursivelyAppendExtensionItems(submenu_items,
111 selection_text, submenu, index); 120 can_cross_incognito,
121 selection_text,
122 submenu,
123 index,
124 false); // is_action_menu_top_level
112 } 125 }
113 SetExtensionIcon(extension_key.extension_id); 126 if (!is_action_menu)
127 SetExtensionIcon(extension_key.extension_id);
114 } 128 }
115 } 129 }
116 130
117 void ContextMenuMatcher::Clear() { 131 void ContextMenuMatcher::Clear() {
118 extension_item_map_.clear(); 132 extension_item_map_.clear();
119 extension_menu_models_.clear(); 133 extension_menu_models_.clear();
120 } 134 }
121 135
122 base::string16 ContextMenuMatcher::GetTopLevelContextMenuTitle( 136 base::string16 ContextMenuMatcher::GetTopLevelContextMenuTitle(
123 const MenuItem::ExtensionKey& extension_key, 137 const MenuItem::ExtensionKey& extension_key,
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 result.push_back(*i); 222 result.push_back(*i);
209 } 223 }
210 return result; 224 return result;
211 } 225 }
212 226
213 void ContextMenuMatcher::RecursivelyAppendExtensionItems( 227 void ContextMenuMatcher::RecursivelyAppendExtensionItems(
214 const MenuItem::List& items, 228 const MenuItem::List& items,
215 bool can_cross_incognito, 229 bool can_cross_incognito,
216 const base::string16& selection_text, 230 const base::string16& selection_text,
217 ui::SimpleMenuModel* menu_model, 231 ui::SimpleMenuModel* menu_model,
218 int* index) 232 int* index,
219 { 233 bool is_action_menu_top_level) {
220 MenuItem::Type last_type = MenuItem::NORMAL; 234 MenuItem::Type last_type = MenuItem::NORMAL;
221 int radio_group_id = 1; 235 int radio_group_id = 1;
236 int num_items = 0;
222 237
223 for (MenuItem::List::const_iterator i = items.begin(); 238 for (MenuItem::List::const_iterator i = items.begin();
224 i != items.end(); ++i) { 239 i != items.end(); ++i) {
225 MenuItem* item = *i; 240 MenuItem* item = *i;
226 241
227 // If last item was of type radio but the current one isn't, auto-insert 242 // If last item was of type radio but the current one isn't, auto-insert
228 // a separator. The converse case is handled below. 243 // a separator. The converse case is handled below.
229 if (last_type == MenuItem::RADIO && 244 if (last_type == MenuItem::RADIO &&
230 item->type() != MenuItem::RADIO) { 245 item->type() != MenuItem::RADIO) {
231 menu_model->AddSeparator(ui::NORMAL_SEPARATOR); 246 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
232 last_type = MenuItem::SEPARATOR; 247 last_type = MenuItem::SEPARATOR;
233 } 248 }
234 249
235 int menu_id = ConvertToExtensionsCustomCommandId(*index); 250 int menu_id = ConvertToExtensionsCustomCommandId(*index);
236 (*index)++; 251 ++(*index);
237 if (menu_id >= extensions_context_custom_last) 252 ++num_items;
253 // Action context menus have a limit for top level extension items to
254 // prevent control items from being pushed off the screen, since extension
255 // items will not be placed in a submenu.
256 if (menu_id >= extensions_context_custom_last ||
257 (is_action_menu_top_level &&
258 num_items >= api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT))
238 return; 259 return;
260
239 extension_item_map_[menu_id] = item->id(); 261 extension_item_map_[menu_id] = item->id();
240 base::string16 title = item->TitleWithReplacement(selection_text, 262 base::string16 title = item->TitleWithReplacement(selection_text,
241 kMaxExtensionItemTitleLength); 263 kMaxExtensionItemTitleLength);
242 if (item->type() == MenuItem::NORMAL) { 264 if (item->type() == MenuItem::NORMAL) {
243 MenuItem::List children = 265 MenuItem::List children =
244 GetRelevantExtensionItems(item->children(), can_cross_incognito); 266 GetRelevantExtensionItems(item->children(), can_cross_incognito);
245 if (children.empty()) { 267 if (children.empty()) {
246 menu_model->AddItem(menu_id, title); 268 menu_model->AddItem(menu_id, title);
247 } else { 269 } else {
248 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_); 270 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_);
249 extension_menu_models_.push_back(submenu); 271 extension_menu_models_.push_back(submenu);
250 menu_model->AddSubMenu(menu_id, title, submenu); 272 menu_model->AddSubMenu(menu_id, title, submenu);
251 RecursivelyAppendExtensionItems(children, can_cross_incognito, 273 RecursivelyAppendExtensionItems(children,
252 selection_text, submenu, index); 274 can_cross_incognito,
275 selection_text,
276 submenu,
277 index,
278 false); // is_action_menu_top_level
253 } 279 }
254 } else if (item->type() == MenuItem::CHECKBOX) { 280 } else if (item->type() == MenuItem::CHECKBOX) {
255 menu_model->AddCheckItem(menu_id, title); 281 menu_model->AddCheckItem(menu_id, title);
256 } else if (item->type() == MenuItem::RADIO) { 282 } else if (item->type() == MenuItem::RADIO) {
257 if (i != items.begin() && 283 if (i != items.begin() &&
258 last_type != MenuItem::RADIO) { 284 last_type != MenuItem::RADIO) {
259 radio_group_id++; 285 radio_group_id++;
260 286
261 // Auto-append a separator if needed. 287 // Auto-append a separator if needed.
262 menu_model->AddSeparator(ui::NORMAL_SEPARATOR); 288 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
(...skipping 26 matching lines...) Expand all
289 DCHECK_GE(index, 0); 315 DCHECK_GE(index, 0);
290 316
291 const SkBitmap& icon = menu_manager->GetIconForExtension(extension_id); 317 const SkBitmap& icon = menu_manager->GetIconForExtension(extension_id);
292 DCHECK(icon.width() == gfx::kFaviconSize); 318 DCHECK(icon.width() == gfx::kFaviconSize);
293 DCHECK(icon.height() == gfx::kFaviconSize); 319 DCHECK(icon.height() == gfx::kFaviconSize);
294 320
295 menu_model_->SetIcon(index, gfx::Image::CreateFrom1xBitmap(icon)); 321 menu_model_->SetIcon(index, gfx::Image::CreateFrom1xBitmap(icon));
296 } 322 }
297 323
298 } // namespace extensions 324 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/context_menu_matcher.h ('k') | chrome/browser/extensions/extension_context_menu_model.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698