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

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

Issue 10918103: Give platform apps control over launcher right-click context menu. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/utf_string_conversions.h"
6 #include "chrome/app/chrome_command_ids.h"
7 #include "chrome/browser/extensions/context_menu_manager.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "content/public/common/context_menu_params.h"
11 #include "ui/gfx/favicon_size.h"
12
13 namespace extensions {
14
15 // static
16 const size_t ContextMenuManager::kMaxExtensionItemTitleLength = 75;
17
18 ContextMenuManager::ContextMenuManager(
19 Profile* profile,
20 ui::SimpleMenuModel::Delegate* delegate,
21 ui::SimpleMenuModel* menu_model,
22 const base::Callback<bool(const MenuItem*)>& filter)
23 : profile_(profile), menu_model_(menu_model), delegate_(delegate),
24 filter_(filter) {
25 }
26
27 void ContextMenuManager::AppendExtensionItems(const std::string& extension_id,
28 const string16& selection_text,
29 int* index)
30 {
31 ExtensionService* service = profile_->GetExtensionService();
32 MenuManager* manager = service->menu_manager();
33 const Extension* extension = service->GetExtensionById(extension_id, false);
34 DCHECK_GE(*index, 0);
35 int max_index =
36 IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST - IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST;
37 if (!extension || *index >= max_index)
38 return;
39
40 // Find matching items.
41 const MenuItem::List* all_items = manager->MenuItems(extension_id);
42 if (!all_items || all_items->empty())
43 return;
44 bool can_cross_incognito = service->CanCrossIncognito(extension);
45 MenuItem::List items = GetRelevantExtensionItems(*all_items,
46 can_cross_incognito);
47
48 if (items.empty())
49 return;
50
51 // If this is the first extension-provided menu item, and there are other
52 // items in the menu, add a separator.
53 if (*index == 0 && menu_model_->GetItemCount())
54 menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
55
56 // Extensions (other than platform apps) are only allowed one top-level slot
57 // (and it can't be a radio or checkbox item because we are going to put the
58 // extension icon next to it).
59 // If they have more than that, we automatically push them into a submenu.
60 if (extension->is_platform_app()) {
61 RecursivelyAppendExtensionItems(items, can_cross_incognito, selection_text,
62 menu_model_, index);
63 } else {
64 int menu_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + (*index)++;
65 string16 title;
66 MenuItem::List submenu_items;
67
68 if (items.size() > 1 || items[0]->type() != MenuItem::NORMAL) {
69 title = UTF8ToUTF16(extension->name());
70 submenu_items = items;
71 } else {
72 MenuItem* item = items[0];
73 extension_item_map_[menu_id] = item->id();
74 title = item->TitleWithReplacement(selection_text,
75 kMaxExtensionItemTitleLength);
76 submenu_items = GetRelevantExtensionItems(item->children(),
77 can_cross_incognito);
78 }
79
80 // Now add our item(s) to the menu_model_.
81 if (submenu_items.empty()) {
82 menu_model_->AddItem(menu_id, title);
83 } else {
84 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_);
85 extension_menu_models_.push_back(submenu);
86 menu_model_->AddSubMenu(menu_id, title, submenu);
87 RecursivelyAppendExtensionItems(submenu_items, can_cross_incognito,
88 selection_text, submenu, index);
89 }
90 SetExtensionIcon(extension_id);
91 }
92 }
93
94 void ContextMenuManager::Clear() {
95 extension_item_map_.clear();
96 extension_menu_models_.clear();
97 }
98
99 bool ContextMenuManager::IsCommandIdChecked(int command_id) const {
100 MenuItem* item = GetExtensionMenuItem(command_id);
101 if (!item)
102 return false;
103 return item->checked();
104 }
105
106 bool ContextMenuManager::IsCommandIdEnabled(int command_id) const {
107 MenuItem* item = GetExtensionMenuItem(command_id);
108 if (!item)
109 return true;
110 return item->enabled();
111 }
112
113 void ContextMenuManager::ExecuteCommand(int command_id,
114 const content::ContextMenuParams& params) {
115 MenuManager* manager = profile_->GetExtensionService()->menu_manager();
116 MenuItem* item = GetExtensionMenuItem(command_id);
117 if (!item)
118 return;
119
120 manager->ExecuteCommand(profile_, NULL, params, item->id());
121 }
122
123 bool ContextMenuManager::ContextIsLauncher(const MenuItem* item) {
124 return item->contexts().Contains(MenuItem::LAUNCHER);
125 }
126
127
128 MenuItem::List ContextMenuManager::GetRelevantExtensionItems(
129 const MenuItem::List& items,
130 bool can_cross_incognito) {
131 MenuItem::List result;
132 for (MenuItem::List::const_iterator i = items.begin();
133 i != items.end(); ++i) {
134 const MenuItem* item = *i;
135
136 if (!filter_.Run(item))
137 continue;
138
139 if (item->id().incognito == profile_->IsOffTheRecord() ||
140 can_cross_incognito)
141 result.push_back(*i);
142 }
143 return result;
144 }
145
146 void ContextMenuManager::RecursivelyAppendExtensionItems(
147 const MenuItem::List& items,
148 bool can_cross_incognito,
149 const string16& selection_text,
150 ui::SimpleMenuModel* menu_model,
151 int* index)
152 {
153 MenuItem::Type last_type = MenuItem::NORMAL;
154 int radio_group_id = 1;
155
156 for (MenuItem::List::const_iterator i = items.begin();
157 i != items.end(); ++i) {
158 MenuItem* item = *i;
159
160 // If last item was of type radio but the current one isn't, auto-insert
161 // a separator. The converse case is handled below.
162 if (last_type == MenuItem::RADIO &&
163 item->type() != MenuItem::RADIO) {
164 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
165 last_type = MenuItem::SEPARATOR;
166 }
167
168 int menu_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + (*index)++;
169 if (menu_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST)
170 return;
171 extension_item_map_[menu_id] = item->id();
172 string16 title = item->TitleWithReplacement(selection_text,
173 kMaxExtensionItemTitleLength);
174 if (item->type() == MenuItem::NORMAL) {
175 MenuItem::List children =
176 GetRelevantExtensionItems(item->children(), can_cross_incognito);
177 if (children.empty()) {
178 menu_model->AddItem(menu_id, title);
179 } else {
180 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_);
181 extension_menu_models_.push_back(submenu);
182 menu_model->AddSubMenu(menu_id, title, submenu);
183 RecursivelyAppendExtensionItems(children, can_cross_incognito,
184 selection_text, submenu, index);
185 }
186 } else if (item->type() == MenuItem::CHECKBOX) {
187 menu_model->AddCheckItem(menu_id, title);
188 } else if (item->type() == MenuItem::RADIO) {
189 if (i != items.begin() &&
190 last_type != MenuItem::RADIO) {
191 radio_group_id++;
192
193 // Auto-append a separator if needed.
194 if (last_type != MenuItem::SEPARATOR)
195 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
196 }
197
198 menu_model->AddRadioItem(menu_id, title, radio_group_id);
199 } else if (item->type() == MenuItem::SEPARATOR) {
200 if (i != items.begin() && last_type != MenuItem::SEPARATOR) {
201 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
202 }
203 }
204 last_type = item->type();
205 }
206 }
207
208 MenuItem* ContextMenuManager::GetExtensionMenuItem(int id) const {
209 MenuManager* manager = profile_->GetExtensionService()->menu_manager();
210 std::map<int, MenuItem::Id>::const_iterator i =
211 extension_item_map_.find(id);
212 if (i != extension_item_map_.end()) {
213 MenuItem* item = manager->GetItemById(i->second);
214 if (item)
215 return item;
216 }
217 return NULL;
218 }
219
220 void ContextMenuManager::SetExtensionIcon(const std::string& extension_id) {
221 ExtensionService* service = profile_->GetExtensionService();
222 MenuManager* menu_manager = service->menu_manager();
223
224 int index = menu_model_->GetItemCount() - 1;
225 DCHECK_GE(index, 0);
226
227 const SkBitmap& icon = menu_manager->GetIconForExtension(extension_id);
228 DCHECK(icon.width() == gfx::kFaviconSize);
229 DCHECK(icon.height() == gfx::kFaviconSize);
230
231 menu_model_->SetIcon(index, gfx::Image(icon));
232 }
233
234 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698