| Index: chrome/browser/extensions/extension_menu_manager.cc
|
| ===================================================================
|
| --- chrome/browser/extensions/extension_menu_manager.cc (revision 50770)
|
| +++ chrome/browser/extensions/extension_menu_manager.cc (working copy)
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <algorithm>
|
|
|
| +#include "app/resource_bundle.h"
|
| #include "base/logging.h"
|
| #include "base/string_util.h"
|
| #include "base/utf_string_conversions.h"
|
| @@ -16,6 +17,11 @@
|
| #include "chrome/browser/extensions/extension_tabs_module.h"
|
| #include "chrome/browser/profile.h"
|
| #include "chrome/common/extensions/extension.h"
|
| +#include "chrome/common/extensions/extension_resource.h"
|
| +#include "gfx/favicon_size.h"
|
| +#include "gfx/size.h"
|
| +#include "grit/theme_resources.h"
|
| +#include "skia/ext/image_operations.h"
|
| #include "webkit/glue/context_menu.h"
|
|
|
| ExtensionMenuItem::ExtensionMenuItem(const std::string& extension_id,
|
| @@ -96,7 +102,9 @@
|
| children_.push_back(item);
|
| }
|
|
|
| -ExtensionMenuManager::ExtensionMenuManager() : next_item_id_(1) {
|
| +ExtensionMenuManager::ExtensionMenuManager()
|
| + : next_item_id_(1),
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)) {
|
| registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
|
| NotificationService::AllSources());
|
| }
|
| @@ -126,21 +134,38 @@
|
| return NULL;
|
| }
|
|
|
| -int ExtensionMenuManager::AddContextItem(ExtensionMenuItem* item) {
|
| +int ExtensionMenuManager::AddContextItem(Extension* extension,
|
| + ExtensionMenuItem* item) {
|
| const std::string& extension_id = item->extension_id();
|
| // The item must have a non-empty extension id.
|
| if (extension_id.empty())
|
| return 0;
|
|
|
| + DCHECK_EQ(extension->id(), extension_id);
|
| +
|
| DCHECK_EQ(0, item->id());
|
| item->set_id(next_item_id_++);
|
|
|
| + bool first_item = !ContainsKey(context_items_, extension_id);
|
| context_items_[extension_id].push_back(item);
|
| items_by_id_[item->id()] = item;
|
|
|
| if (item->type() == ExtensionMenuItem::RADIO && item->checked())
|
| RadioItemSelected(item);
|
|
|
| + // If this is the first item for this extension, start loading its icon.
|
| + if (first_item) {
|
| + ExtensionResource icon_resource;
|
| + extension->GetIconPathAllowLargerSize(&icon_resource,
|
| + Extension::EXTENSION_ICON_BITTY);
|
| + if (!icon_resource.extension_root().empty()) {
|
| + image_tracker_.LoadImage(extension,
|
| + icon_resource,
|
| + gfx::Size(kFavIconSize, kFavIconSize),
|
| + ImageLoadingTracker::CACHE);
|
| + }
|
| + }
|
| +
|
| return item->id();
|
| }
|
|
|
| @@ -233,6 +258,7 @@
|
| return false;
|
| }
|
|
|
| + bool result = false;
|
| ExtensionMenuItem::List& list = i->second;
|
| ExtensionMenuItem::List::iterator j;
|
| for (j = list.begin(); j < list.end(); ++j) {
|
| @@ -241,14 +267,20 @@
|
| delete *j;
|
| list.erase(j);
|
| items_by_id_.erase(id);
|
| - return true;
|
| + result = true;
|
| + break;
|
| } else if ((*j)->RemoveChild(id)) {
|
| items_by_id_.erase(id);
|
| - return true;
|
| + result = true;
|
| + break;
|
| }
|
| }
|
| - NOTREACHED(); // The check at the very top should prevent getting here.
|
| - return false;
|
| + DCHECK(result); // The check at the very top should have prevented this.
|
| +
|
| + if (list.empty() && ContainsKey(extension_icons_, extension_id))
|
| + extension_icons_.erase(extension_id);
|
| +
|
| + return result;
|
| }
|
|
|
| void ExtensionMenuManager::RemoveAllContextItems(std::string extension_id) {
|
| @@ -267,6 +299,9 @@
|
| }
|
| STLDeleteElements(&context_items_[extension_id]);
|
| context_items_.erase(extension_id);
|
| +
|
| + if (ContainsKey(extension_icons_, extension_id))
|
| + extension_icons_.erase(extension_id);
|
| }
|
|
|
| ExtensionMenuItem* ExtensionMenuManager::GetItemById(int id) const {
|
| @@ -422,3 +457,57 @@
|
| RemoveAllContextItems(extension->id());
|
| }
|
| }
|
| +
|
| +const SkBitmap& ExtensionMenuManager::GetIconForExtension(
|
| + const std::string& extension_id) {
|
| + const SkBitmap* result = NULL;
|
| + if (ContainsKey(extension_icons_, extension_id)) {
|
| + result = &(extension_icons_[extension_id]);
|
| + } else {
|
| + EnsureDefaultIcon();
|
| + result = &default_icon_;
|
| + }
|
| + DCHECK(result);
|
| + DCHECK(result->width() == kFavIconSize);
|
| + DCHECK(result->height() == kFavIconSize);
|
| + return *result;
|
| +}
|
| +
|
| +void ExtensionMenuManager::OnImageLoaded(SkBitmap* image,
|
| + ExtensionResource resource,
|
| + int index) {
|
| + if (!image)
|
| + return;
|
| +
|
| + const std::string extension_id = resource.extension_id();
|
| +
|
| + // Make sure we still have menu items for this extension (since image loading
|
| + // is asynchronous, there's a slight chance they may have all been removed
|
| + // while the icon was loading).
|
| + if (!ContainsKey(context_items_, extension_id))
|
| + return;
|
| +
|
| + if (image->width() == kFavIconSize && image->height() == kFavIconSize)
|
| + extension_icons_[extension_id] = *image;
|
| + else
|
| + extension_icons_[extension_id] = ScaleToFavIconSize(*image);
|
| +}
|
| +
|
| +void ExtensionMenuManager::EnsureDefaultIcon() {
|
| + if (default_icon_.empty()) {
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION);
|
| + if (src->width() == kFavIconSize && src->height() == kFavIconSize) {
|
| + default_icon_ = *src;
|
| + } else {
|
| + default_icon_ = SkBitmap(ScaleToFavIconSize(*src));
|
| + }
|
| + }
|
| +}
|
| +
|
| +SkBitmap ExtensionMenuManager::ScaleToFavIconSize(const SkBitmap& source) {
|
| + return skia::ImageOperations::Resize(source,
|
| + skia::ImageOperations::RESIZE_LANCZOS3,
|
| + kFavIconSize,
|
| + kFavIconSize);
|
| +}
|
|
|