blob: fb746287b38ab68c3b97ca3486f46f5fb2067f3d [file] [log] [blame]
[email protected]25cc7502012-01-31 19:33:551// 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/icon_loader.h"
6
avi6846aef2015-12-26 01:09:387#include <stddef.h>
8
[email protected]25cc7502012-01-31 19:33:559#include <map>
10#include <string>
11#include <utility>
12
13#include "base/bind.h"
[email protected]bc0147b2013-04-03 20:50:5914#include "base/files/file_path.h"
[email protected]25cc7502012-01-31 19:33:5515#include "base/lazy_instance.h"
[email protected]90fa2652012-04-24 16:18:3516#include "base/memory/ref_counted_memory.h"
Avi Drissman5f0fb8c2018-12-25 23:20:4917#include "base/stl_util.h"
[email protected]9c7ddc92013-06-11 01:40:5718#include "base/strings/string_util.h"
Eric Seckler8652dcd52018-09-20 10:42:2819#include "base/task/post_task.h"
thestig4a9b0ef2016-08-29 08:22:1220#include "chrome/grit/theme_resources.h"
Eric Seckler8652dcd52018-09-20 10:42:2821#include "content/public/browser/browser_task_traits.h"
Gabriel Charette790754c2018-03-16 21:32:5922#include "content/public/browser/browser_thread.h"
Scott Violeta35f9a42018-03-22 22:00:4423#include "media/media_buildflags.h"
[email protected]25cc7502012-01-31 19:33:5524#include "third_party/skia/include/core/SkBitmap.h"
[email protected]c49201a2012-05-24 11:04:5725#include "ui/base/layout.h"
[email protected]25cc7502012-01-31 19:33:5526#include "ui/base/resource/resource_bundle.h"
[email protected]a7db88142012-03-14 14:43:0927#include "ui/gfx/canvas.h"
[email protected]25cc7502012-01-31 19:33:5528#include "ui/gfx/codec/png_codec.h"
29#include "ui/gfx/image/image.h"
[email protected]2b8ac342012-08-29 03:46:2730#include "ui/gfx/image/image_skia.h"
[email protected]679facce2012-07-25 16:13:1231#include "ui/gfx/image/image_skia_operations.h"
[email protected]25cc7502012-01-31 19:33:5532
33namespace {
34
[email protected]679facce2012-07-25 16:13:1235// Used with GenerateImageWithSize() to indicate that the image shouldn't be
[email protected]25cc7502012-01-31 19:33:5536// resized.
37const int kDoNotResize = -1;
38
39struct IdrBySize {
40 int idr_small;
41 int idr_normal;
42 int idr_large;
43};
44
45// Performs mapping of <file extension, icon size> to icon resource IDs.
46class IconMapper {
47 public:
48 IconMapper();
49
50 // Lookup icon resource ID for a given filename |extension| and
51 // |icon_size|. Defaults to generic icons if there are no icons for the given
52 // extension.
53 int Lookup(const std::string& extension, IconLoader::IconSize icon_size);
54
55 private:
56 typedef std::map<std::string, IdrBySize> ExtensionIconMap;
57
58 ExtensionIconMap extension_icon_map_;
59};
60
61const IdrBySize kAudioIdrs = {
[email protected]c069ebd2014-04-03 15:02:1462 IDR_FILETYPE_AUDIO,
63 IDR_FILETYPE_LARGE_AUDIO,
64 IDR_FILETYPE_LARGE_AUDIO
[email protected]25cc7502012-01-31 19:33:5565};
66const IdrBySize kGenericIdrs = {
[email protected]c069ebd2014-04-03 15:02:1467 IDR_FILETYPE_GENERIC,
68 IDR_FILETYPE_LARGE_GENERIC,
69 IDR_FILETYPE_LARGE_GENERIC
[email protected]25cc7502012-01-31 19:33:5570};
[email protected]25cc7502012-01-31 19:33:5571const IdrBySize kImageIdrs = {
[email protected]c069ebd2014-04-03 15:02:1472 IDR_FILETYPE_IMAGE,
73 IDR_FILETYPE_IMAGE,
74 IDR_FILETYPE_IMAGE
[email protected]25cc7502012-01-31 19:33:5575};
brettw68c77532017-01-21 00:28:0676#if BUILDFLAG(USE_PROPRIETARY_CODECS)
[email protected]25cc7502012-01-31 19:33:5577const IdrBySize kPdfIdrs = {
[email protected]c069ebd2014-04-03 15:02:1478 IDR_FILETYPE_PDF,
79 IDR_FILETYPE_PDF,
80 IDR_FILETYPE_PDF
[email protected]25cc7502012-01-31 19:33:5581};
[email protected]dfe8987d72013-10-19 16:20:5882#endif
[email protected]25cc7502012-01-31 19:33:5583const IdrBySize kVideoIdrs = {
[email protected]c069ebd2014-04-03 15:02:1484 IDR_FILETYPE_VIDEO,
85 IDR_FILETYPE_LARGE_VIDEO,
86 IDR_FILETYPE_LARGE_VIDEO
[email protected]25cc7502012-01-31 19:33:5587};
88
89IconMapper::IconMapper() {
90 // The code below should match translation in
[email protected]4ff3d9f2014-04-24 05:25:2091 // ui/file_manager/file_manager/js/file_manager.js
92 // ui/file_manager/file_manager/css/file_manager.css
[email protected]25cc7502012-01-31 19:33:5593 // 'audio': /\.(mp3|m4a|oga|ogg|wav)$/i,
94 // 'html': /\.(html?)$/i,
95 // 'image': /\.(bmp|gif|jpe?g|ico|png|webp)$/i,
96 // 'pdf' : /\.(pdf)$/i,
97 // 'text': /\.(pod|rst|txt|log)$/i,
98 // 'video': /\.(mov|mp4|m4v|mpe?g4?|ogm|ogv|ogx|webm)$/i
99
100 const ExtensionIconMap::value_type kExtensionIdrBySizeData[] = {
brettw68c77532017-01-21 00:28:06101#if BUILDFLAG(USE_PROPRIETARY_CODECS)
[email protected]25cc7502012-01-31 19:33:55102 std::make_pair(".m4a", kAudioIdrs),
103 std::make_pair(".mp3", kAudioIdrs),
104 std::make_pair(".pdf", kPdfIdrs),
105 std::make_pair(".3gp", kVideoIdrs),
106 std::make_pair(".avi", kVideoIdrs),
107 std::make_pair(".m4v", kVideoIdrs),
108 std::make_pair(".mov", kVideoIdrs),
109 std::make_pair(".mp4", kVideoIdrs),
110 std::make_pair(".mpeg", kVideoIdrs),
111 std::make_pair(".mpg", kVideoIdrs),
112 std::make_pair(".mpeg4", kVideoIdrs),
113 std::make_pair(".mpg4", kVideoIdrs),
114#endif
115 std::make_pair(".flac", kAudioIdrs),
116 std::make_pair(".oga", kAudioIdrs),
117 std::make_pair(".ogg", kAudioIdrs),
118 std::make_pair(".wav", kAudioIdrs),
[email protected]25cc7502012-01-31 19:33:55119 std::make_pair(".bmp", kImageIdrs),
120 std::make_pair(".gif", kImageIdrs),
121 std::make_pair(".ico", kImageIdrs),
122 std::make_pair(".jpeg", kImageIdrs),
123 std::make_pair(".jpg", kImageIdrs),
124 std::make_pair(".png", kImageIdrs),
125 std::make_pair(".webp", kImageIdrs),
[email protected]25cc7502012-01-31 19:33:55126 std::make_pair(".ogm", kVideoIdrs),
127 std::make_pair(".ogv", kVideoIdrs),
128 std::make_pair(".ogx", kVideoIdrs),
129 std::make_pair(".webm", kVideoIdrs),
130 };
131
Avi Drissman5f0fb8c2018-12-25 23:20:49132 const size_t kESize = base::size(kExtensionIdrBySizeData);
[email protected]25cc7502012-01-31 19:33:55133 ExtensionIconMap source(&kExtensionIdrBySizeData[0],
134 &kExtensionIdrBySizeData[kESize]);
135 extension_icon_map_.swap(source);
136}
137
138int IconMapper::Lookup(const std::string& extension,
139 IconLoader::IconSize icon_size) {
140 DCHECK(icon_size == IconLoader::SMALL ||
141 icon_size == IconLoader::NORMAL ||
142 icon_size == IconLoader::LARGE);
143 ExtensionIconMap::const_iterator it = extension_icon_map_.find(extension);
144 const IdrBySize& idrbysize =
145 ((it == extension_icon_map_.end()) ? kGenericIdrs : it->second);
146 int idr = -1;
147 switch (icon_size) {
148 case IconLoader::SMALL: idr = idrbysize.idr_small; break;
149 case IconLoader::NORMAL: idr = idrbysize.idr_normal; break;
150 case IconLoader::LARGE: idr = idrbysize.idr_large; break;
151 case IconLoader::ALL:
152 default:
153 NOTREACHED();
154 }
155 return idr;
156}
157
[email protected]679facce2012-07-25 16:13:12158// Returns a copy of |source| that is |dip_size| in width and height. If
159// |dip_size| is |kDoNotResize|, returns an unmodified copy of |source|.
[email protected]25cc7502012-01-31 19:33:55160// |source| must be a square image (width == height).
[email protected]679facce2012-07-25 16:13:12161gfx::ImageSkia ResizeImage(const gfx::ImageSkia& source, int dip_size) {
[email protected]93079e02012-05-15 15:42:59162 DCHECK(!source.isNull());
163 DCHECK(source.width() == source.height());
[email protected]25cc7502012-01-31 19:33:55164
[email protected]679facce2012-07-25 16:13:12165 if (dip_size == kDoNotResize || source.width() == dip_size)
[email protected]93079e02012-05-15 15:42:59166 return source;
[email protected]25cc7502012-01-31 19:33:55167
[email protected]679facce2012-07-25 16:13:12168 return gfx::ImageSkiaOperations::CreateResizedImage(source,
[email protected]3a49e502012-08-16 21:24:41169 skia::ImageOperations::RESIZE_BEST, gfx::Size(dip_size, dip_size));
[email protected]25cc7502012-01-31 19:33:55170}
171
[email protected]679facce2012-07-25 16:13:12172int IconSizeToDIPSize(IconLoader::IconSize size) {
[email protected]25cc7502012-01-31 19:33:55173 switch (size) {
174 case IconLoader::SMALL: return 16;
175 case IconLoader::NORMAL: return 32;
176 case IconLoader::LARGE: // fallthrough
177 // On ChromeOS, we consider LARGE to mean "the largest image we have."
178 // Since we have already chosen the largest applicable image resource, we
179 // return the image as-is.
180 case IconLoader::ALL: // fallthrough
181 default:
182 return kDoNotResize;
183 }
184}
185
186} // namespace
187
[email protected]bc0147b2013-04-03 20:50:59188// static
avi381f719f2016-12-16 00:05:02189IconLoader::IconGroup IconLoader::GroupForFilepath(
190 const base::FilePath& file_path) {
191 return base::ToLowerASCII(file_path.Extension());
[email protected]681b4b82013-04-09 23:34:21192}
193
[email protected]b3b6a372014-03-12 01:48:04194// static
avif4d431c2017-06-22 23:30:53195scoped_refptr<base::TaskRunner> IconLoader::GetReadIconTaskRunner() {
tzik65452e02017-02-22 22:53:16196 // ReadIcon touches non thread safe ResourceBundle images, so it must be on
197 // the UI thread.
Sami Kyostila7d640eb2019-07-31 18:50:26198 return base::CreateSingleThreadTaskRunner({content::BrowserThread::UI});
[email protected]b3b6a372014-03-12 01:48:04199}
200
[email protected]25cc7502012-01-31 19:33:55201void IconLoader::ReadIcon() {
202 static base::LazyInstance<IconMapper>::Leaky icon_mapper =
203 LAZY_INSTANCE_INITIALIZER;
204 int idr = icon_mapper.Get().Lookup(group_, icon_size_);
Lei Zhang7640d542017-10-03 16:26:49205 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
[email protected]2b8ac342012-08-29 03:46:27206 gfx::ImageSkia image_skia(ResizeImage(*(rb.GetImageNamed(idr)).ToImageSkia(),
207 IconSizeToDIPSize(icon_size_)));
208 image_skia.MakeThreadSafe();
Dana Friedfa14d5f2019-04-21 20:49:36209 gfx::Image image(image_skia);
pranay.kumar4b8db4d2015-04-29 11:12:04210 target_task_runner_->PostTask(
Avi Drissmanefe4dc82018-02-23 17:55:39211 FROM_HERE,
212 base::BindOnce(std::move(callback_), std::move(image), group_));
avif0a7b5b812016-12-17 19:01:31213 delete this;
[email protected]25cc7502012-01-31 19:33:55214}