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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/extension_icon_manager.h" 6 7 #include "base/logging.h" 8 #include "base/stl_util-inl.h" 9 #include "chrome/common/extensions/extension.h" 10 #include "chrome/common/extensions/extension_icon_set.h" 11 #include "chrome/common/extensions/extension_resource.h" 12 #include "grit/theme_resources.h" 13 #include "skia/ext/image_operations.h" 14 #include "ui/base/resource/resource_bundle.h" 15 #include "ui/gfx/canvas_skia.h" 16 #include "ui/gfx/color_utils.h" 17 #include "ui/gfx/favicon_size.h" 18 #include "ui/gfx/size.h" 19 #include "ui/gfx/skbitmap_operations.h" 20 21 namespace { 22 23 // Helper function to create a new bitmap with |padding| amount of empty space 24 // around the original bitmap. 25 static SkBitmap ApplyPadding(const SkBitmap& source, 26 const gfx::Insets& padding) { 27 scoped_ptr<gfx::CanvasSkia> result( 28 new gfx::CanvasSkia(source.width() + padding.width(), 29 source.height() + padding.height(), false)); 30 result->DrawBitmapInt( 31 source, 32 0, 0, source.width(), source.height(), 33 padding.left(), padding.top(), source.width(), source.height(), 34 false); 35 return result->ExtractBitmap(); 36 } 37 38 } // namespace 39 40 ExtensionIconManager::ExtensionIconManager() 41 : ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)), 42 monochrome_(false) { 43 } 44 45 ExtensionIconManager::~ExtensionIconManager() { 46 } 47 48 void ExtensionIconManager::LoadIcon(const Extension* extension) { 49 ExtensionResource icon_resource = extension->GetIconResource( 50 Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_BIGGER); 51 if (!icon_resource.extension_root().empty()) { 52 // Insert into pending_icons_ first because LoadImage can call us back 53 // synchronously if the image is already cached. 54 pending_icons_.insert(extension->id()); 55 image_tracker_.LoadImage(extension, 56 icon_resource, 57 gfx::Size(kFaviconSize, kFaviconSize), 58 ImageLoadingTracker::CACHE); 59 } 60 } 61 62 const SkBitmap& ExtensionIconManager::GetIcon(const std::string& extension_id) { 63 const SkBitmap* result = NULL; 64 if (ContainsKey(icons_, extension_id)) { 65 result = &icons_[extension_id]; 66 } else { 67 EnsureDefaultIcon(); 68 result = &default_icon_; 69 } 70 DCHECK(result); 71 DCHECK_EQ(kFaviconSize + padding_.width(), result->width()); 72 DCHECK_EQ(kFaviconSize + padding_.height(), result->height()); 73 return *result; 74 } 75 76 void ExtensionIconManager::RemoveIcon(const std::string& extension_id) { 77 icons_.erase(extension_id); 78 pending_icons_.erase(extension_id); 79 } 80 81 void ExtensionIconManager::OnImageLoaded(SkBitmap* image, 82 const ExtensionResource& resource, 83 int index) { 84 if (!image) 85 return; 86 87 const std::string extension_id = resource.extension_id(); 88 89 // We may have removed the icon while waiting for it to load. In that case, 90 // do nothing. 91 if (!ContainsKey(pending_icons_, extension_id)) 92 return; 93 94 pending_icons_.erase(extension_id); 95 icons_[extension_id] = ApplyTransforms(*image); 96 } 97 98 void ExtensionIconManager::EnsureDefaultIcon() { 99 if (default_icon_.empty()) { 100 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 101 SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); 102 default_icon_ = ApplyTransforms(*src); 103 } 104 } 105 106 SkBitmap ExtensionIconManager::ApplyTransforms(const SkBitmap& source) { 107 SkBitmap result = source; 108 109 if (result.width() != kFaviconSize || result.height() != kFaviconSize) { 110 result = skia::ImageOperations::Resize( 111 result, skia::ImageOperations::RESIZE_LANCZOS3, 112 kFaviconSize, kFaviconSize); 113 } 114 115 if (monochrome_) { 116 color_utils::HSL shift = {-1, 0, 0.6}; 117 result = SkBitmapOperations::CreateHSLShiftedBitmap(result, shift); 118 } 119 120 if (!padding_.empty()) 121 result = ApplyPadding(result, padding_); 122 123 return result; 124 } 125