1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_icon_manager.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/extensions/extension_icon_set.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_resource.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/image_operations.h" 1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia.h" 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/color_utils.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/favicon_size.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/size.h" 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skbitmap_operations.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace { 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Helper function to create a new bitmap with |padding| amount of empty space 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// around the original bitmap. 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic SkBitmap ApplyPadding(const SkBitmap& source, 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const gfx::Insets& padding) { 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<gfx::CanvasSkia> result( 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new gfx::CanvasSkia(source.width() + padding.width(), 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick source.height() + padding.height(), false)); 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result->DrawBitmapInt( 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick source, 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, 0, source.width(), source.height(), 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick padding.left(), padding.top(), source.width(), source.height(), 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick false); 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return result->ExtractBitmap(); 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochExtensionIconManager::ExtensionIconManager() 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)), 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch monochrome_(false) { 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickExtensionIconManager::~ExtensionIconManager() { 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ExtensionIconManager::LoadIcon(const Extension* extension) { 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ExtensionResource icon_resource = extension->GetIconResource( 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_BIGGER); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!icon_resource.extension_root().empty()) { 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Insert into pending_icons_ first because LoadImage can call us back 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // synchronously if the image is already cached. 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pending_icons_.insert(extension->id()); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_tracker_.LoadImage(extension, 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icon_resource, 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Size(kFaviconSize, kFaviconSize), 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ImageLoadingTracker::CACHE); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkBitmap& ExtensionIconManager::GetIcon(const std::string& extension_id) { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap* result = NULL; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ContainsKey(icons_, extension_id)) { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = &icons_[extension_id]; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EnsureDefaultIcon(); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = &default_icon_; 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(result); 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(kFaviconSize + padding_.width(), result->width()); 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(kFaviconSize + padding_.height(), result->height()); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return *result; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionIconManager::RemoveIcon(const std::string& extension_id) { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icons_.erase(extension_id); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_icons_.erase(extension_id); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionIconManager::OnImageLoaded(SkBitmap* image, 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ExtensionResource& resource, 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!image) 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string extension_id = resource.extension_id(); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We may have removed the icon while waiting for it to load. In that case, 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // do nothing. 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ContainsKey(pending_icons_, extension_id)) 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_icons_.erase(extension_id); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icons_[extension_id] = ApplyTransforms(*image); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionIconManager::EnsureDefaultIcon() { 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (default_icon_.empty()) { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default_icon_ = ApplyTransforms(*src); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSkBitmap ExtensionIconManager::ApplyTransforms(const SkBitmap& source) { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap result = source; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (result.width() != kFaviconSize || result.height() != kFaviconSize) { 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = skia::ImageOperations::Resize( 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result, skia::ImageOperations::RESIZE_LANCZOS3, 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kFaviconSize, kFaviconSize); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (monochrome_) { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch color_utils::HSL shift = {-1, 0, 0.6}; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = SkBitmapOperations::CreateHSLShiftedBitmap(result, shift); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!padding_.empty()) 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result = ApplyPadding(result, padding_); 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 125