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

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

Issue 2867008: Show extension icons next to their top-level context menu items.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 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
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/extension_menu_manager.h" 5 #include "chrome/browser/extensions/extension_menu_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "app/resource_bundle.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/string_util.h" 11 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
12 #include "base/values.h" 13 #include "base/values.h"
13 #include "base/json/json_writer.h" 14 #include "base/json/json_writer.h"
14 #include "chrome/app/chrome_dll_resource.h" 15 #include "chrome/app/chrome_dll_resource.h"
15 #include "chrome/browser/extensions/extension_message_service.h" 16 #include "chrome/browser/extensions/extension_message_service.h"
16 #include "chrome/browser/extensions/extension_tabs_module.h" 17 #include "chrome/browser/extensions/extension_tabs_module.h"
17 #include "chrome/browser/profile.h" 18 #include "chrome/browser/profile.h"
18 #include "chrome/common/extensions/extension.h" 19 #include "chrome/common/extensions/extension.h"
20 #include "chrome/common/extensions/extension_resource.h"
21 #include "gfx/favicon_size.h"
22 #include "gfx/size.h"
23 #include "grit/theme_resources.h"
24 #include "skia/ext/image_operations.h"
19 #include "webkit/glue/context_menu.h" 25 #include "webkit/glue/context_menu.h"
20 26
21 ExtensionMenuItem::ExtensionMenuItem(const std::string& extension_id, 27 ExtensionMenuItem::ExtensionMenuItem(const std::string& extension_id,
22 std::string title, 28 std::string title,
23 bool checked, Type type, 29 bool checked, Type type,
24 const ContextList& contexts, 30 const ContextList& contexts,
25 const ContextList& enabled_contexts) 31 const ContextList& enabled_contexts)
26 : extension_id_(extension_id), 32 : extension_id_(extension_id),
27 title_(title), 33 title_(title),
28 id_(0), 34 id_(0),
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 return false; 95 return false;
90 checked_ = checked; 96 checked_ = checked;
91 return true; 97 return true;
92 } 98 }
93 99
94 void ExtensionMenuItem::AddChild(ExtensionMenuItem* item) { 100 void ExtensionMenuItem::AddChild(ExtensionMenuItem* item) {
95 item->parent_id_ = id_; 101 item->parent_id_ = id_;
96 children_.push_back(item); 102 children_.push_back(item);
97 } 103 }
98 104
99 ExtensionMenuManager::ExtensionMenuManager() : next_item_id_(1) { 105 ExtensionMenuManager::ExtensionMenuManager()
106 : next_item_id_(1),
107 ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)) {
100 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, 108 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
101 NotificationService::AllSources()); 109 NotificationService::AllSources());
102 } 110 }
103 111
104 ExtensionMenuManager::~ExtensionMenuManager() { 112 ExtensionMenuManager::~ExtensionMenuManager() {
105 MenuItemMap::iterator i; 113 MenuItemMap::iterator i;
106 for (i = context_items_.begin(); i != context_items_.end(); ++i) { 114 for (i = context_items_.begin(); i != context_items_.end(); ++i) {
107 STLDeleteElements(&(i->second)); 115 STLDeleteElements(&(i->second));
108 } 116 }
109 } 117 }
110 118
111 std::set<std::string> ExtensionMenuManager::ExtensionIds() { 119 std::set<std::string> ExtensionMenuManager::ExtensionIds() {
112 std::set<std::string> id_set; 120 std::set<std::string> id_set;
113 for (MenuItemMap::const_iterator i = context_items_.begin(); 121 for (MenuItemMap::const_iterator i = context_items_.begin();
114 i != context_items_.end(); ++i) { 122 i != context_items_.end(); ++i) {
115 id_set.insert(i->first); 123 id_set.insert(i->first);
116 } 124 }
117 return id_set; 125 return id_set;
118 } 126 }
119 127
120 const ExtensionMenuItem::List* ExtensionMenuManager::MenuItems( 128 const ExtensionMenuItem::List* ExtensionMenuManager::MenuItems(
121 const std::string& extension_id) { 129 const std::string& extension_id) {
122 MenuItemMap::iterator i = context_items_.find(extension_id); 130 MenuItemMap::iterator i = context_items_.find(extension_id);
123 if (i != context_items_.end()) { 131 if (i != context_items_.end()) {
124 return &(i->second); 132 return &(i->second);
125 } 133 }
126 return NULL; 134 return NULL;
127 } 135 }
128 136
129 int ExtensionMenuManager::AddContextItem(ExtensionMenuItem* item) { 137 int ExtensionMenuManager::AddContextItem(Extension* extension,
138 ExtensionMenuItem* item) {
130 const std::string& extension_id = item->extension_id(); 139 const std::string& extension_id = item->extension_id();
131 // The item must have a non-empty extension id. 140 // The item must have a non-empty extension id.
132 if (extension_id.empty()) 141 if (extension_id.empty())
133 return 0; 142 return 0;
134 143
144 DCHECK_EQ(extension->id(), extension_id);
145
135 DCHECK_EQ(0, item->id()); 146 DCHECK_EQ(0, item->id());
136 item->set_id(next_item_id_++); 147 item->set_id(next_item_id_++);
137 148
149 bool first_item = !ContainsKey(context_items_, extension_id);
138 context_items_[extension_id].push_back(item); 150 context_items_[extension_id].push_back(item);
139 items_by_id_[item->id()] = item; 151 items_by_id_[item->id()] = item;
140 152
141 if (item->type() == ExtensionMenuItem::RADIO && item->checked()) 153 if (item->type() == ExtensionMenuItem::RADIO && item->checked())
142 RadioItemSelected(item); 154 RadioItemSelected(item);
143 155
156 // If this is the first item for this extension, start loading its icon.
157 if (first_item) {
158 ExtensionResource icon_resource;
159 extension->GetIconPathAllowLargerSize(&icon_resource,
160 Extension::EXTENSION_ICON_BITTY);
161 if (!icon_resource.extension_root().empty()) {
162 image_tracker_.LoadImage(extension,
163 icon_resource,
164 gfx::Size(kFavIconSize, kFavIconSize),
165 ImageLoadingTracker::CACHE);
166 }
167 }
168
144 return item->id(); 169 return item->id();
145 } 170 }
146 171
147 int ExtensionMenuManager::AddChildItem(int parent_id, 172 int ExtensionMenuManager::AddChildItem(int parent_id,
148 ExtensionMenuItem* child) { 173 ExtensionMenuItem* child) {
149 ExtensionMenuItem* parent = GetItemById(parent_id); 174 ExtensionMenuItem* parent = GetItemById(parent_id);
150 if (!parent || parent->type() != ExtensionMenuItem::NORMAL || 175 if (!parent || parent->type() != ExtensionMenuItem::NORMAL ||
151 parent->extension_id() != child->extension_id()) 176 parent->extension_id() != child->extension_id())
152 return 0; 177 return 0;
153 child->set_id(next_item_id_++); 178 child->set_id(next_item_id_++);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 if (!ContainsKey(items_by_id_, id)) 251 if (!ContainsKey(items_by_id_, id))
227 return false; 252 return false;
228 253
229 std::string extension_id = GetItemById(id)->extension_id(); 254 std::string extension_id = GetItemById(id)->extension_id();
230 MenuItemMap::iterator i = context_items_.find(extension_id); 255 MenuItemMap::iterator i = context_items_.find(extension_id);
231 if (i == context_items_.end()) { 256 if (i == context_items_.end()) {
232 NOTREACHED(); 257 NOTREACHED();
233 return false; 258 return false;
234 } 259 }
235 260
261 bool result = false;
236 ExtensionMenuItem::List& list = i->second; 262 ExtensionMenuItem::List& list = i->second;
237 ExtensionMenuItem::List::iterator j; 263 ExtensionMenuItem::List::iterator j;
238 for (j = list.begin(); j < list.end(); ++j) { 264 for (j = list.begin(); j < list.end(); ++j) {
239 // See if the current item is a match, or if one of its children was. 265 // See if the current item is a match, or if one of its children was.
240 if ((*j)->id() == id) { 266 if ((*j)->id() == id) {
241 delete *j; 267 delete *j;
242 list.erase(j); 268 list.erase(j);
243 items_by_id_.erase(id); 269 items_by_id_.erase(id);
244 return true; 270 result = true;
271 break;
245 } else if ((*j)->RemoveChild(id)) { 272 } else if ((*j)->RemoveChild(id)) {
246 items_by_id_.erase(id); 273 items_by_id_.erase(id);
247 return true; 274 result = true;
275 break;
248 } 276 }
249 } 277 }
250 NOTREACHED(); // The check at the very top should prevent getting here. 278 DCHECK(result); // The check at the very top should have prevented this.
251 return false; 279
280 if (list.empty() && ContainsKey(extension_icons_, extension_id))
281 extension_icons_.erase(extension_id);
282
283 return result;
252 } 284 }
253 285
254 void ExtensionMenuManager::RemoveAllContextItems(std::string extension_id) { 286 void ExtensionMenuManager::RemoveAllContextItems(std::string extension_id) {
255 ExtensionMenuItem::List::iterator i; 287 ExtensionMenuItem::List::iterator i;
256 for (i = context_items_[extension_id].begin(); 288 for (i = context_items_[extension_id].begin();
257 i != context_items_[extension_id].end(); ++i) { 289 i != context_items_[extension_id].end(); ++i) {
258 ExtensionMenuItem* item = *i; 290 ExtensionMenuItem* item = *i;
259 items_by_id_.erase(item->id()); 291 items_by_id_.erase(item->id());
260 292
261 // Remove descendants from this item and erase them from the lookup cache. 293 // Remove descendants from this item and erase them from the lookup cache.
262 std::set<int> removed_ids = item->RemoveAllDescendants(); 294 std::set<int> removed_ids = item->RemoveAllDescendants();
263 for (std::set<int>::const_iterator j = removed_ids.begin(); 295 for (std::set<int>::const_iterator j = removed_ids.begin();
264 j != removed_ids.end(); ++j) { 296 j != removed_ids.end(); ++j) {
265 items_by_id_.erase(*j); 297 items_by_id_.erase(*j);
266 } 298 }
267 } 299 }
268 STLDeleteElements(&context_items_[extension_id]); 300 STLDeleteElements(&context_items_[extension_id]);
269 context_items_.erase(extension_id); 301 context_items_.erase(extension_id);
302
303 if (ContainsKey(extension_icons_, extension_id))
304 extension_icons_.erase(extension_id);
270 } 305 }
271 306
272 ExtensionMenuItem* ExtensionMenuManager::GetItemById(int id) const { 307 ExtensionMenuItem* ExtensionMenuManager::GetItemById(int id) const {
273 std::map<int, ExtensionMenuItem*>::const_iterator i = items_by_id_.find(id); 308 std::map<int, ExtensionMenuItem*>::const_iterator i = items_by_id_.find(id);
274 if (i != items_by_id_.end()) 309 if (i != items_by_id_.end())
275 return i->second; 310 return i->second;
276 else 311 else
277 return NULL; 312 return NULL;
278 } 313 }
279 314
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 // Remove menu items for disabled/uninstalled extensions. 450 // Remove menu items for disabled/uninstalled extensions.
416 if (type != NotificationType::EXTENSION_UNLOADED) { 451 if (type != NotificationType::EXTENSION_UNLOADED) {
417 NOTREACHED(); 452 NOTREACHED();
418 return; 453 return;
419 } 454 }
420 Extension* extension = Details<Extension>(details).ptr(); 455 Extension* extension = Details<Extension>(details).ptr();
421 if (ContainsKey(context_items_, extension->id())) { 456 if (ContainsKey(context_items_, extension->id())) {
422 RemoveAllContextItems(extension->id()); 457 RemoveAllContextItems(extension->id());
423 } 458 }
424 } 459 }
460
461 const SkBitmap& ExtensionMenuManager::GetIconForExtension(
462 const std::string& extension_id) {
463 const SkBitmap* result = NULL;
464 if (ContainsKey(extension_icons_, extension_id)) {
465 result = &(extension_icons_[extension_id]);
466 } else {
467 EnsureDefaultIcon();
468 result = &default_icon_;
469 }
470 DCHECK(result);
471 DCHECK(result->width() == kFavIconSize);
472 DCHECK(result->height() == kFavIconSize);
473 return *result;
474 }
475
476 void ExtensionMenuManager::OnImageLoaded(SkBitmap* image,
477 ExtensionResource resource,
478 int index) {
479 if (!image)
480 return;
481
482 const std::string extension_id = resource.extension_id();
483
484 // Make sure we still have menu items for this extension (since image loading
485 // is asynchronous, there's a slight chance they may have all been removed
486 // while the icon was loading).
487 if (!ContainsKey(context_items_, extension_id))
488 return;
489
490 if (image->width() == kFavIconSize && image->height() == kFavIconSize)
491 extension_icons_[extension_id] = *image;
492 else
493 extension_icons_[extension_id] = ScaleToFavIconSize(*image);
494 }
495
496 void ExtensionMenuManager::EnsureDefaultIcon() {
497 if (default_icon_.empty()) {
498 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
499 SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION);
500 if (src->width() == kFavIconSize && src->height() == kFavIconSize) {
501 default_icon_ = *src;
502 } else {
503 default_icon_ = SkBitmap(ScaleToFavIconSize(*src));
504 }
505 }
506 }
507
508 SkBitmap ExtensionMenuManager::ScaleToFavIconSize(const SkBitmap& source) {
509 return skia::ImageOperations::Resize(source,
510 skia::ImageOperations::RESIZE_LANCZOS3,
511 kFavIconSize,
512 kFavIconSize);
513 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_menu_manager.h ('k') | chrome/browser/extensions/extension_menu_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698