Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_icon_manager.cc
1 // Copyright (c) 2012 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/bind.h"
8 #include "base/logging.h"
9 #include "base/stl_util.h"
10 #include "chrome/browser/extensions/image_loader.h"
11 #include "extensions/common/constants.h"
12 #include "extensions/common/extension.h"
13 #include "extensions/common/extension_icon_set.h"
14 #include "extensions/common/extension_resource.h"
15 #include "extensions/common/manifest_handlers/icons_handler.h"
16 #include "grit/theme_resources.h"
17 #include "skia/ext/image_operations.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/color_utils.h"
21 #include "ui/gfx/favicon_size.h"
22 #include "ui/gfx/image/image.h"
23 #include "ui/gfx/size.h"
24 #include "ui/gfx/skbitmap_operations.h"
25
26 namespace {
27
28 // Helper function to create a new bitmap with |padding| amount of empty space
29 // around the original bitmap.
30 static SkBitmap ApplyPadding(const SkBitmap& source,
31                              const gfx::Insets& padding) {
32   scoped_ptr<gfx::Canvas> result(
33       new gfx::Canvas(gfx::Size(source.width() + padding.width(),
34                                 source.height() + padding.height()),
35                       1.0f,
36                       false));
37   result->DrawImageInt(
38       gfx::ImageSkia::CreateFrom1xBitmap(source),
39       0, 0, source.width(), source.height(),
40       padding.left(), padding.top(), source.width(), source.height(),
41       false);
42   return result->ExtractImageRep().sk_bitmap();
43 }
44
45 }  // namespace
46
47 ExtensionIconManager::ExtensionIconManager()
48     : monochrome_(false),
49       weak_ptr_factory_(this)  {
50 }
51
52 ExtensionIconManager::~ExtensionIconManager() {
53 }
54
55 void ExtensionIconManager::LoadIcon(content::BrowserContext* context,
56                                     const extensions::Extension* extension) {
57   extensions::ExtensionResource icon_resource =
58       extensions::IconsInfo::GetIconResource(
59           extension,
60           extension_misc::EXTENSION_ICON_BITTY,
61           ExtensionIconSet::MATCH_BIGGER);
62   if (!icon_resource.extension_root().empty()) {
63     // Insert into pending_icons_ first because LoadImage can call us back
64     // synchronously if the image is already cached.
65     pending_icons_.insert(extension->id());
66     extensions::ImageLoader* loader = extensions::ImageLoader::Get(context);
67     loader->LoadImageAsync(extension, icon_resource,
68                            gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize),
69                            base::Bind(
70                                &ExtensionIconManager::OnImageLoaded,
71                                weak_ptr_factory_.GetWeakPtr(),
72                                extension->id()));
73   }
74 }
75
76 const SkBitmap& ExtensionIconManager::GetIcon(const std::string& extension_id) {
77   const SkBitmap* result = NULL;
78   if (ContainsKey(icons_, extension_id)) {
79     result = &icons_[extension_id];
80   } else {
81     EnsureDefaultIcon();
82     result = &default_icon_;
83   }
84   DCHECK(result);
85   DCHECK_EQ(gfx::kFaviconSize + padding_.width(), result->width());
86   DCHECK_EQ(gfx::kFaviconSize + padding_.height(), result->height());
87   return *result;
88 }
89
90 void ExtensionIconManager::RemoveIcon(const std::string& extension_id) {
91   icons_.erase(extension_id);
92   pending_icons_.erase(extension_id);
93 }
94
95 void ExtensionIconManager::OnImageLoaded(const std::string& extension_id,
96                                          const gfx::Image& image) {
97   if (image.IsEmpty())
98     return;
99
100   // We may have removed the icon while waiting for it to load. In that case,
101   // do nothing.
102   if (!ContainsKey(pending_icons_, extension_id))
103     return;
104
105   pending_icons_.erase(extension_id);
106   icons_[extension_id] = ApplyTransforms(*image.ToSkBitmap());
107 }
108
109 void ExtensionIconManager::EnsureDefaultIcon() {
110   if (default_icon_.empty()) {
111     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
112     SkBitmap src = rb.GetImageNamed(IDR_EXTENSIONS_SECTION).AsBitmap();
113     default_icon_ = ApplyTransforms(src);
114   }
115 }
116
117 SkBitmap ExtensionIconManager::ApplyTransforms(const SkBitmap& source) {
118   SkBitmap result = source;
119
120   if (result.width() != gfx::kFaviconSize ||
121       result.height() != gfx::kFaviconSize) {
122     result = skia::ImageOperations::Resize(
123         result, skia::ImageOperations::RESIZE_LANCZOS3,
124         gfx::kFaviconSize, gfx::kFaviconSize);
125   }
126
127   if (monochrome_) {
128     color_utils::HSL shift = {-1, 0, 0.6};
129     result = SkBitmapOperations::CreateHSLShiftedBitmap(result, shift);
130   }
131
132   if (!padding_.empty())
133     result = ApplyPadding(result, padding_);
134
135   return result;
136 }