Home | History | Annotate | Download | only in extensions
      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