[email protected] | 326e6f0 | 2014-06-20 04:53:37 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 326e6f0 | 2014-06-20 04:53:37 | [diff] [blame] | 5 | #include "extensions/browser/image_loader.h" |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 6 | |
avi | c9cec10 | 2015-12-23 00:39:26 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | |
[email protected] | 95fd255 | 2013-07-04 21:19:24 | [diff] [blame] | 9 | #include <map> |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 10 | #include <utility> |
[email protected] | 95fd255 | 2013-07-04 21:19:24 | [diff] [blame] | 11 | #include <vector> |
| 12 | |
Sebastien Marchand | 6d0558fd | 2019-01-25 16:49:37 | [diff] [blame] | 13 | #include "base/bind.h" |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 14 | #include "base/callback.h" |
[email protected] | c8b8587b | 2012-11-21 23:23:32 | [diff] [blame] | 15 | #include "base/compiler_specific.h" |
thestig | 9471270 | 2014-09-10 07:46:59 | [diff] [blame] | 16 | #include "base/files/file_util.h" |
[email protected] | 3ea1b18 | 2013-02-08 22:38:41 | [diff] [blame] | 17 | #include "base/strings/string_number_conversions.h" |
Gabriel Charette | 44db142 | 2018-08-06 11:19:33 | [diff] [blame] | 18 | #include "base/task/post_task.h" |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 19 | #include "content/public/browser/browser_thread.h" |
[email protected] | 326e6f0 | 2014-06-20 04:53:37 | [diff] [blame] | 20 | #include "extensions/browser/component_extension_resource_manager.h" |
| 21 | #include "extensions/browser/extensions_browser_client.h" |
| 22 | #include "extensions/browser/image_loader_factory.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 23 | #include "extensions/common/extension.h" |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 24 | #include "extensions/common/manifest_handlers/icons_handler.h" |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 25 | #include "skia/ext/image_operations.h" |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 26 | #include "ui/base/layout.h" |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 27 | #include "ui/base/resource/resource_bundle.h" |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 28 | #include "ui/display/display.h" |
| 29 | #include "ui/display/screen.h" |
[email protected] | da87eec2 | 2013-05-14 09:25:28 | [diff] [blame] | 30 | #include "ui/gfx/codec/png_codec.h" |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 31 | #include "ui/gfx/image/image_family.h" |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 32 | #include "ui/gfx/image/image_skia.h" |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 33 | |
| 34 | using content::BrowserThread; |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 35 | |
| 36 | namespace extensions { |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 37 | |
| 38 | namespace { |
| 39 | |
| 40 | bool ShouldResizeImageRepresentation( |
| 41 | ImageLoader::ImageRepresentation::ResizeCondition resize_method, |
| 42 | const gfx::Size& decoded_size, |
| 43 | const gfx::Size& desired_size) { |
| 44 | switch (resize_method) { |
| 45 | case ImageLoader::ImageRepresentation::ALWAYS_RESIZE: |
| 46 | return decoded_size != desired_size; |
| 47 | case ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER: |
| 48 | return decoded_size.width() > desired_size.width() || |
| 49 | decoded_size.height() > desired_size.height(); |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 50 | case ImageLoader::ImageRepresentation::NEVER_RESIZE: |
| 51 | return false; |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 52 | default: |
| 53 | NOTREACHED(); |
| 54 | return false; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | SkBitmap ResizeIfNeeded(const SkBitmap& bitmap, |
| 59 | const ImageLoader::ImageRepresentation& image_info) { |
| 60 | gfx::Size original_size(bitmap.width(), bitmap.height()); |
| 61 | if (ShouldResizeImageRepresentation(image_info.resize_condition, |
| 62 | original_size, |
| 63 | image_info.desired_size)) { |
| 64 | return skia::ImageOperations::Resize( |
| 65 | bitmap, skia::ImageOperations::RESIZE_LANCZOS3, |
| 66 | image_info.desired_size.width(), image_info.desired_size.height()); |
| 67 | } |
| 68 | |
| 69 | return bitmap; |
| 70 | } |
| 71 | |
| 72 | void LoadResourceOnUIThread(int resource_id, SkBitmap* bitmap) { |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 73 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 74 | |
| 75 | gfx::ImageSkia image( |
Lei Zhang | cf30efc | 2017-10-04 21:31:24 | [diff] [blame] | 76 | *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id)); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 77 | image.MakeThreadSafe(); |
| 78 | *bitmap = *image.bitmap(); |
| 79 | } |
| 80 | |
fdoray | 98a1e01 | 2017-02-18 16:21:38 | [diff] [blame] | 81 | void LoadImageBlocking(const ImageLoader::ImageRepresentation& image_info, |
| 82 | SkBitmap* bitmap) { |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 83 | // Read the file from disk. |
| 84 | std::string file_contents; |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 85 | base::FilePath path = image_info.resource.GetFilePath(); |
[email protected] | 82f84b9 | 2013-08-30 18:23:50 | [diff] [blame] | 86 | if (path.empty() || !base::ReadFileToString(path, &file_contents)) { |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 87 | return; |
| 88 | } |
| 89 | |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 90 | const unsigned char* data = |
| 91 | reinterpret_cast<const unsigned char*>(file_contents.data()); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 92 | // Note: This class only decodes bitmaps from extension resources. Chrome |
| 93 | // doesn't (for security reasons) directly load extension resources provided |
| 94 | // by the extension author, but instead decodes them in a separate |
| 95 | // locked-down utility process. Only if the decoding succeeds is the image |
| 96 | // saved from memory to disk and subsequently used in the Chrome UI. |
| 97 | // Chrome is therefore decoding bitmaps here that were generated by Chrome. |
[email protected] | da87eec2 | 2013-05-14 09:25:28 | [diff] [blame] | 98 | gfx::PNGCodec::Decode(data, file_contents.length(), bitmap); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 99 | } |
| 100 | |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 101 | std::vector<SkBitmap> LoadResourceBitmaps( |
| 102 | const Extension* extension, |
| 103 | const std::vector<ImageLoader::ImageRepresentation>& info_list) { |
| 104 | // Loading resources has to happen on the UI thread. So do this first, and |
| 105 | // pass the rest of the work off as a blocking pool task. |
| 106 | std::vector<SkBitmap> bitmaps; |
| 107 | bitmaps.resize(info_list.size()); |
| 108 | |
| 109 | int i = 0; |
jdoerrie | a1e1598b | 2018-10-10 09:10:37 | [diff] [blame] | 110 | for (auto it = info_list.cbegin(); it != info_list.cend(); ++it, ++i) { |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 111 | DCHECK(it->resource.relative_path().empty() || |
| 112 | extension->path() == it->resource.extension_root()); |
| 113 | |
dpapad | 669a8970 | 2019-05-10 18:00:49 | [diff] [blame] | 114 | int resource_id = 0; |
[email protected] | 326e6f0 | 2014-06-20 04:53:37 | [diff] [blame] | 115 | if (extension->location() == Manifest::COMPONENT) { |
mukai | ee458c9 | 2015-01-06 01:30:33 | [diff] [blame] | 116 | const extensions::ComponentExtensionResourceManager* manager = |
| 117 | extensions::ExtensionsBrowserClient::Get() |
| 118 | ->GetComponentExtensionResourceManager(); |
dpapad | 669a8970 | 2019-05-10 18:00:49 | [diff] [blame] | 119 | if (manager && |
| 120 | manager->IsComponentExtensionResource( |
| 121 | extension->path(), it->resource.relative_path(), &resource_id)) { |
| 122 | DCHECK(!ui::ResourceBundle::GetSharedInstance().IsGzipped(resource_id)); |
| 123 | LoadResourceOnUIThread(resource_id, &bitmaps[i]); |
[email protected] | 326e6f0 | 2014-06-20 04:53:37 | [diff] [blame] | 124 | } |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 125 | } |
| 126 | } |
| 127 | return bitmaps; |
| 128 | } |
| 129 | |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 130 | } // namespace |
| 131 | |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 132 | //////////////////////////////////////////////////////////////////////////////// |
| 133 | // ImageLoader::ImageRepresentation |
| 134 | |
| 135 | ImageLoader::ImageRepresentation::ImageRepresentation( |
| 136 | const ExtensionResource& resource, |
| 137 | ResizeCondition resize_condition, |
| 138 | const gfx::Size& desired_size, |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 139 | float scale_factor) |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 140 | : resource(resource), |
| 141 | resize_condition(resize_condition), |
| 142 | desired_size(desired_size), |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 143 | scale_factor(scale_factor) {} |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 144 | |
| 145 | ImageLoader::ImageRepresentation::~ImageRepresentation() { |
| 146 | } |
| 147 | |
| 148 | //////////////////////////////////////////////////////////////////////////////// |
| 149 | // ImageLoader::LoadResult |
| 150 | |
| 151 | struct ImageLoader::LoadResult { |
| 152 | LoadResult(const SkBitmap& bitmap, |
| 153 | const gfx::Size& original_size, |
| 154 | const ImageRepresentation& image_representation); |
| 155 | ~LoadResult(); |
| 156 | |
| 157 | SkBitmap bitmap; |
| 158 | gfx::Size original_size; |
| 159 | ImageRepresentation image_representation; |
| 160 | }; |
| 161 | |
| 162 | ImageLoader::LoadResult::LoadResult( |
| 163 | const SkBitmap& bitmap, |
| 164 | const gfx::Size& original_size, |
| 165 | const ImageLoader::ImageRepresentation& image_representation) |
| 166 | : bitmap(bitmap), |
| 167 | original_size(original_size), |
| 168 | image_representation(image_representation) { |
| 169 | } |
| 170 | |
| 171 | ImageLoader::LoadResult::~LoadResult() { |
| 172 | } |
| 173 | |
[email protected] | f5bb764 | 2013-11-23 19:03:53 | [diff] [blame] | 174 | namespace { |
| 175 | |
| 176 | // Need to be after ImageRepresentation and LoadResult are defined. |
fdoray | 98a1e01 | 2017-02-18 16:21:38 | [diff] [blame] | 177 | std::vector<ImageLoader::LoadResult> LoadImagesBlocking( |
[email protected] | f5bb764 | 2013-11-23 19:03:53 | [diff] [blame] | 178 | const std::vector<ImageLoader::ImageRepresentation>& info_list, |
| 179 | const std::vector<SkBitmap>& bitmaps) { |
[email protected] | f5bb764 | 2013-11-23 19:03:53 | [diff] [blame] | 180 | std::vector<ImageLoader::LoadResult> load_result; |
| 181 | |
| 182 | for (size_t i = 0; i < info_list.size(); ++i) { |
| 183 | const ImageLoader::ImageRepresentation& image = info_list[i]; |
| 184 | |
| 185 | // If we don't have a path there isn't anything we can do, just skip it. |
| 186 | if (image.resource.relative_path().empty()) |
| 187 | continue; |
| 188 | |
| 189 | SkBitmap bitmap; |
| 190 | if (bitmaps[i].isNull()) |
fdoray | 98a1e01 | 2017-02-18 16:21:38 | [diff] [blame] | 191 | LoadImageBlocking(image, &bitmap); |
[email protected] | f5bb764 | 2013-11-23 19:03:53 | [diff] [blame] | 192 | else |
| 193 | bitmap = bitmaps[i]; |
| 194 | |
| 195 | // If the image failed to load, skip it. |
| 196 | if (bitmap.isNull() || bitmap.empty()) |
| 197 | continue; |
| 198 | |
| 199 | gfx::Size original_size(bitmap.width(), bitmap.height()); |
| 200 | bitmap = ResizeIfNeeded(bitmap, image); |
| 201 | |
| 202 | load_result.push_back( |
| 203 | ImageLoader::LoadResult(bitmap, original_size, image)); |
| 204 | } |
| 205 | |
| 206 | return load_result; |
| 207 | } |
| 208 | |
| 209 | } // namespace |
| 210 | |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 211 | //////////////////////////////////////////////////////////////////////////////// |
| 212 | // ImageLoader |
| 213 | |
Jeremy Roman | 9fc2de6 | 2019-07-12 14:15:03 | [diff] [blame] | 214 | ImageLoader::ImageLoader() {} |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 215 | |
| 216 | ImageLoader::~ImageLoader() { |
| 217 | } |
| 218 | |
| 219 | // static |
[email protected] | 472522b | 2013-10-25 00:41:28 | [diff] [blame] | 220 | ImageLoader* ImageLoader::Get(content::BrowserContext* context) { |
| 221 | return ImageLoaderFactory::GetForBrowserContext(context); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 222 | } |
| 223 | |
[email protected] | f5bb764 | 2013-11-23 19:03:53 | [diff] [blame] | 224 | void ImageLoader::LoadImageAsync(const Extension* extension, |
| 225 | const ExtensionResource& resource, |
| 226 | const gfx::Size& max_size, |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 227 | ImageLoaderImageCallback callback) { |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 228 | std::vector<ImageRepresentation> info_list; |
| 229 | info_list.push_back(ImageRepresentation( |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 230 | resource, ImageRepresentation::RESIZE_WHEN_LARGER, max_size, 1.f)); |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 231 | LoadImagesAsync(extension, info_list, std::move(callback)); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 232 | } |
| 233 | |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 234 | void ImageLoader::LoadImageAtEveryScaleFactorAsync( |
| 235 | const Extension* extension, |
| 236 | const gfx::Size& dip_size, |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 237 | ImageLoaderImageCallback callback) { |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 238 | std::vector<ImageRepresentation> info_list; |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 239 | |
| 240 | std::set<float> scales; |
| 241 | for (auto scale : ui::GetSupportedScaleFactors()) |
| 242 | scales.insert(ui::GetScaleForScaleFactor(scale)); |
| 243 | |
| 244 | // There may not be a screen in unit tests. |
vmpstr | 6d9996c8 | 2017-02-23 00:43:25 | [diff] [blame] | 245 | auto* screen = display::Screen::GetScreen(); |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 246 | if (screen) { |
| 247 | for (const auto& display : screen->GetAllDisplays()) |
| 248 | scales.insert(display.device_scale_factor()); |
| 249 | } |
| 250 | |
| 251 | for (auto scale : scales) { |
| 252 | const gfx::Size px_size = gfx::ScaleToFlooredSize(dip_size, scale); |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 253 | ExtensionResource image = IconsInfo::GetIconResource( |
| 254 | extension, px_size.width(), ExtensionIconSet::MATCH_BIGGER); |
| 255 | info_list.push_back(ImageRepresentation( |
| 256 | image, ImageRepresentation::ALWAYS_RESIZE, px_size, scale)); |
| 257 | } |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 258 | LoadImagesAsync(extension, info_list, std::move(callback)); |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 259 | } |
| 260 | |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 261 | void ImageLoader::LoadImagesAsync( |
| 262 | const Extension* extension, |
| 263 | const std::vector<ImageRepresentation>& info_list, |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 264 | ImageLoaderImageCallback callback) { |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 265 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
Sami Kyostila | fc64668 | 2019-08-08 05:19:56 | [diff] [blame] | 266 | base::PostTaskAndReplyWithResult( |
| 267 | FROM_HERE, |
| 268 | {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE}, |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 269 | base::BindOnce(LoadImagesBlocking, info_list, |
| 270 | LoadResourceBitmaps(extension, info_list)), |
| 271 | base::BindOnce(&ImageLoader::ReplyBack, weak_ptr_factory_.GetWeakPtr(), |
| 272 | std::move(callback))); |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | void ImageLoader::LoadImageFamilyAsync( |
estade | 32426e0 | 2016-12-18 01:26:17 | [diff] [blame] | 276 | const Extension* extension, |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 277 | const std::vector<ImageRepresentation>& info_list, |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 278 | ImageLoaderImageFamilyCallback callback) { |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 279 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
Sami Kyostila | fc64668 | 2019-08-08 05:19:56 | [diff] [blame] | 280 | base::PostTaskAndReplyWithResult( |
| 281 | FROM_HERE, |
| 282 | {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE}, |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 283 | base::BindOnce(LoadImagesBlocking, info_list, |
| 284 | LoadResourceBitmaps(extension, info_list)), |
| 285 | base::BindOnce(&ImageLoader::ReplyBackWithImageFamily, |
| 286 | weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 287 | } |
| 288 | |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 289 | void ImageLoader::ReplyBack(ImageLoaderImageCallback callback, |
[email protected] | f5bb764 | 2013-11-23 19:03:53 | [diff] [blame] | 290 | const std::vector<LoadResult>& load_result) { |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 291 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 292 | |
| 293 | gfx::ImageSkia image_skia; |
| 294 | |
jdoerrie | a1e1598b | 2018-10-10 09:10:37 | [diff] [blame] | 295 | for (auto it = load_result.cbegin(); it != load_result.cend(); ++it) { |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 296 | const SkBitmap& bitmap = it->bitmap; |
| 297 | const ImageRepresentation& image_rep = it->image_representation; |
| 298 | |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 299 | image_skia.AddRepresentation( |
| 300 | gfx::ImageSkiaRep(bitmap, image_rep.scale_factor)); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 301 | } |
| 302 | |
| 303 | gfx::Image image; |
| 304 | if (!image_skia.isNull()) { |
| 305 | image_skia.MakeThreadSafe(); |
| 306 | image = gfx::Image(image_skia); |
| 307 | } |
| 308 | |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 309 | std::move(callback).Run(image); |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 310 | } |
| 311 | |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 312 | void ImageLoader::ReplyBackWithImageFamily( |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 313 | ImageLoaderImageFamilyCallback callback, |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 314 | const std::vector<LoadResult>& load_result) { |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 315 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 316 | |
| 317 | std::map<std::pair<int, int>, gfx::ImageSkia> image_skia_map; |
| 318 | gfx::ImageFamily image_family; |
| 319 | |
jdoerrie | a1e1598b | 2018-10-10 09:10:37 | [diff] [blame] | 320 | for (auto it = load_result.cbegin(); it != load_result.cend(); ++it) { |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 321 | const SkBitmap& bitmap = it->bitmap; |
| 322 | const ImageRepresentation& image_rep = it->image_representation; |
| 323 | const std::pair<int, int> key = std::make_pair( |
| 324 | image_rep.desired_size.width(), image_rep.desired_size.height()); |
| 325 | // Create a new ImageSkia for this width/height, or add a representation to |
| 326 | // an existing ImageSkia with the same width/height. |
| 327 | image_skia_map[key].AddRepresentation( |
estade | 47ce132c | 2017-01-17 20:37:47 | [diff] [blame] | 328 | gfx::ImageSkiaRep(bitmap, image_rep.scale_factor)); |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 329 | } |
| 330 | |
jdoerrie | a1e1598b | 2018-10-10 09:10:37 | [diff] [blame] | 331 | for (auto it = image_skia_map.begin(); it != image_skia_map.end(); ++it) { |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 332 | it->second.MakeThreadSafe(); |
| 333 | image_family.Add(it->second); |
| 334 | } |
| 335 | |
Nigel Tao | bd12215b | 2018-11-29 01:10:18 | [diff] [blame] | 336 | std::move(callback).Run(std::move(image_family)); |
[email protected] | 1d8e0f3 | 2014-03-17 06:39:19 | [diff] [blame] | 337 | } |
| 338 | |
[email protected] | ec7de0c5a | 2012-11-16 07:40:47 | [diff] [blame] | 339 | } // namespace extensions |