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.
5 #include "chrome/browser/extensions/extension_icon_manager.h"
8 #include "base/logging.h"
9 #include "base/stl_util.h"
10 #include "extensions/browser/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/geometry/size.h"
23 #include "ui/gfx/image/image.h"
24 #include "ui/gfx/skbitmap_operations.h"
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()),
38 gfx::ImageSkia::CreateFrom1xBitmap(source
),
39 0, 0, source
.width(), source
.height(),
40 padding
.left(), padding
.top(), source
.width(), source
.height(),
42 return result
->ExtractImageRep().sk_bitmap();
47 ExtensionIconManager::ExtensionIconManager()
49 weak_ptr_factory_(this) {
52 ExtensionIconManager::~ExtensionIconManager() {
55 void ExtensionIconManager::LoadIcon(content::BrowserContext
* context
,
56 const extensions::Extension
* extension
) {
57 extensions::ExtensionResource icon_resource
=
58 extensions::IconsInfo::GetIconResource(
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
),
70 &ExtensionIconManager::OnImageLoaded
,
71 weak_ptr_factory_
.GetWeakPtr(),
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
];
82 result
= &default_icon_
;
85 DCHECK_EQ(gfx::kFaviconSize
+ padding_
.width(), result
->width());
86 DCHECK_EQ(gfx::kFaviconSize
+ padding_
.height(), result
->height());
90 void ExtensionIconManager::RemoveIcon(const std::string
& extension_id
) {
91 icons_
.erase(extension_id
);
92 pending_icons_
.erase(extension_id
);
95 void ExtensionIconManager::OnImageLoaded(const std::string
& extension_id
,
96 const gfx::Image
& image
) {
100 // We may have removed the icon while waiting for it to load. In that case,
102 if (!ContainsKey(pending_icons_
, extension_id
))
105 pending_icons_
.erase(extension_id
);
106 icons_
[extension_id
] = ApplyTransforms(*image
.ToSkBitmap());
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
);
117 SkBitmap
ExtensionIconManager::ApplyTransforms(const SkBitmap
& source
) {
118 SkBitmap result
= source
;
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
);
128 color_utils::HSL shift
= {-1, 0, 0.6};
129 result
= SkBitmapOperations::CreateHSLShiftedBitmap(result
, shift
);
132 if (!padding_
.empty())
133 result
= ApplyPadding(result
, padding_
);