Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: trunk/src/chrome/browser/extensions/image_loader.cc

Issue 26511002: Revert 227477 "Refactored loading of applications / extensions i..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/image_loader.h" 5 #include "chrome/browser/extensions/image_loader.h"
6 6
7 #include <map> 7 #include <map>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/base64.h"
11 #include "base/callback.h" 10 #include "base/callback.h"
12 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
13 #include "base/file_util.h" 12 #include "base/file_util.h"
14 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
15 #include "base/path_service.h" 14 #include "base/path_service.h"
16 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
17 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/threading/sequenced_worker_pool.h"
18 #include "chrome/browser/extensions/image_loader_factory.h" 17 #include "chrome/browser/extensions/image_loader_factory.h"
19 #include "chrome/browser/favicon/favicon_service.h"
20 #include "chrome/browser/favicon/favicon_service_factory.h"
21 #include "chrome/common/chrome_paths.h" 18 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/extensions/extension.h" 19 #include "chrome/common/extensions/extension.h"
23 #include "chrome/common/extensions/extension_icon_set.h"
24 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
25 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
26 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
27 #include "content/public/common/url_constants.h"
28 #include "grit/chrome_unscaled_resources.h" 21 #include "grit/chrome_unscaled_resources.h"
29 #include "grit/component_extension_resources_map.h" 22 #include "grit/component_extension_resources_map.h"
30 #include "grit/theme_resources.h" 23 #include "grit/theme_resources.h"
31 #include "skia/ext/image_operations.h" 24 #include "skia/ext/image_operations.h"
32 #include "ui/base/resource/resource_bundle.h" 25 #include "ui/base/resource/resource_bundle.h"
33 #include "ui/gfx/codec/png_codec.h" 26 #include "ui/gfx/codec/png_codec.h"
34 #include "ui/gfx/color_utils.h"
35 #include "ui/gfx/favicon_size.h"
36 #include "ui/gfx/image/image_skia.h" 27 #include "ui/gfx/image/image_skia.h"
37 #include "ui/gfx/size.h"
38 #include "ui/gfx/skbitmap_operations.h"
39 28
40 #if defined(USE_AURA) 29 #if defined(USE_AURA)
41 #include "ui/keyboard/keyboard_util.h" 30 #include "ui/keyboard/keyboard_util.h"
42 #endif 31 #endif
43 32
44 using content::BrowserThread; 33 using content::BrowserThread;
45 using extensions::Extension; 34 using extensions::Extension;
46 using extensions::ImageLoader; 35 using extensions::ImageLoader;
47 using extensions::Manifest; 36 using extensions::Manifest;
48 37
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 base::FilePath resource_path = base::FilePath().AppendASCII( 108 base::FilePath resource_path = base::FilePath().AppendASCII(
120 entries[i].name); 109 entries[i].name);
121 resource_path = resource_path.NormalizePathSeparators(); 110 resource_path = resource_path.NormalizePathSeparators();
122 111
123 DCHECK(path_to_resource_id->find(resource_path) == 112 DCHECK(path_to_resource_id->find(resource_path) ==
124 path_to_resource_id->end()); 113 path_to_resource_id->end());
125 (*path_to_resource_id)[resource_path] = entries[i].value; 114 (*path_to_resource_id)[resource_path] = entries[i].value;
126 } 115 }
127 } 116 }
128 117
129 // Returns a PNG image data URL of a given image.
130 GURL GetImageDataURL(const gfx::Image& image) {
131 if (image.IsEmpty())
132 return GURL();
133
134 scoped_refptr<base::RefCountedMemory> mem =
135 ImageLoader::BitmapToMemory(image.ToSkBitmap());
136 std::string contents_base64;
137 // TODO(dvh): contents_base64 calculation of the result of the function is
138 // sub-optimal: it's a concatenation of 3 strings and |contents_base64| can
139 // be huge. Additionally, the GURL is returned by copy.
140 // crbug/304759.
141 if (!base::Base64Encode(
142 std::string(reinterpret_cast<const char*>(mem->front()), mem->size()),
143 &contents_base64))
144 return GURL();
145
146 const char kDataURLPrefix[] = ":image/png;base64,";
147 return GURL(std::string(chrome::kDataScheme) + kDataURLPrefix +
148 contents_base64);
149 }
150
151 // Converts the image to grayscale.
152 SkBitmap DesaturateImage(const SkBitmap* image) {
153 color_utils::HSL shift = {-1, 0, 0.6};
154 return SkBitmapOperations::CreateHSLShiftedBitmap(*image, shift);
155 }
156
157 // Creates an image from PNG data.
158 SkBitmap* ToBitmap(const unsigned char* data, size_t size) {
159 SkBitmap* decoded = new SkBitmap();
160 bool success = gfx::PNGCodec::Decode(data, size, decoded);
161 DCHECK(success);
162 return decoded;
163 }
164
165 // Load an image from a resource given its identifier |resource_id|.
166 SkBitmap* GetImageByResourceId(int resource_id) {
167 std::string contents = ResourceBundle::GetSharedInstance()
168 .GetRawDataResourceForScale(resource_id,
169 ui::SCALE_FACTOR_100P).as_string();
170
171 // Convert and return it.
172 const unsigned char* data =
173 reinterpret_cast<const unsigned char*>(contents.data());
174 return ToBitmap(data, contents.length());
175 }
176
177 } // namespace 118 } // namespace
178 119
179 namespace extensions { 120 namespace extensions {
180 121
181 //////////////////////////////////////////////////////////////////////////////// 122 ////////////////////////////////////////////////////////////////////////////////
182 // ImageLoader::ImageRepresentation 123 // ImageLoader::ImageRepresentation
183 124
184 ImageLoader::ImageRepresentation::ImageRepresentation( 125 ImageLoader::ImageRepresentation::ImageRepresentation(
185 const ExtensionResource& resource, 126 const ExtensionResource& resource,
186 ResizeCondition resize_condition, 127 ResizeCondition resize_condition,
(...skipping 30 matching lines...) Expand all
217 original_size(original_size), 158 original_size(original_size),
218 image_representation(image_representation) { 159 image_representation(image_representation) {
219 } 160 }
220 161
221 ImageLoader::LoadResult::~LoadResult() { 162 ImageLoader::LoadResult::~LoadResult() {
222 } 163 }
223 164
224 //////////////////////////////////////////////////////////////////////////////// 165 ////////////////////////////////////////////////////////////////////////////////
225 // ImageLoader 166 // ImageLoader
226 167
227 ImageLoader::ImageLoader(Profile* profile) 168 ImageLoader::ImageLoader()
228 : weak_ptr_factory_(this), profile_(profile) { 169 : weak_ptr_factory_(this) {
229 } 170 }
230 171
231 ImageLoader::~ImageLoader() { 172 ImageLoader::~ImageLoader() {
232 } 173 }
233 174
234 // static 175 // static
235 ImageLoader* ImageLoader::Get(Profile* profile) { 176 ImageLoader* ImageLoader::Get(Profile* profile) {
236 return ImageLoaderFactory::GetForProfile(profile); 177 return ImageLoaderFactory::GetForProfile(profile);
237 } 178 }
238 179
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 340
400 gfx::Image image; 341 gfx::Image image;
401 if (!image_skia.isNull()) { 342 if (!image_skia.isNull()) {
402 image_skia.MakeThreadSafe(); 343 image_skia.MakeThreadSafe();
403 image = gfx::Image(image_skia); 344 image = gfx::Image(image_skia);
404 } 345 }
405 346
406 callback.Run(image); 347 callback.Run(image);
407 } 348 }
408 349
409 void ImageLoader::LoadExtensionIconAsync(
410 const extensions::Extension* extension,
411 int icon_size,
412 ExtensionIconSet::MatchType match,
413 bool grayscale,
414 const base::Callback<void(const gfx::Image&)>& callback) {
415 // |extension| can be NULL when the default icon is requested. In this case,
416 // fail the icon loading, which will result in the default icon being loaded.
417 if (extension == NULL) {
418 LoadIconFailed(extension, icon_size, grayscale, callback);
419 return;
420 }
421
422 ExtensionResource resource = IconsInfo::GetIconResource(
423 extension, icon_size, match);
424 LoadImageAsync(extension,
425 resource,
426 gfx::Size(icon_size, icon_size),
427 base::Bind(&ImageLoader::LoadExtensionIconDone,
428 base::Unretained(this),
429 extension,
430 icon_size,
431 grayscale,
432 callback));
433 }
434
435 void ImageLoader::LoadExtensionIconDone(
436 const extensions::Extension* extension,
437 int icon_size,
438 bool grayscale,
439 const base::Callback<void(const gfx::Image&)>& callback,
440 const gfx::Image& image) {
441 if (image.IsEmpty())
442 LoadIconFailed(extension, icon_size, grayscale, callback);
443 else
444 FinalizeImage(image, grayscale, callback);
445 }
446
447 void ImageLoader::LoadIconFailed(
448 const extensions::Extension* extension,
449 int icon_size,
450 bool grayscale,
451 const base::Callback<void(const gfx::Image&)>& callback) {
452 if ((extension != NULL) &&
453 (icon_size == extension_misc::EXTENSION_ICON_BITTY))
454 LoadFaviconImage(extension, icon_size, grayscale, callback);
455 else
456 LoadDefaultImage(extension, icon_size, grayscale, callback);
457 }
458
459 void ImageLoader::LoadFaviconImage(
460 const extensions::Extension* extension,
461 int icon_size,
462 bool grayscale,
463 const base::Callback<void(const gfx::Image&)>& callback) {
464 FaviconService* favicon_service = NULL;
465 if (profile_ != NULL)
466 favicon_service = FaviconServiceFactory::GetForProfile(
467 profile_, Profile::EXPLICIT_ACCESS);
468 // Fall back to the default icons if the service isn't available.
469 if (favicon_service == NULL) {
470 LoadDefaultImage(extension, icon_size, grayscale, callback);
471 return;
472 }
473
474 GURL favicon_url = AppLaunchInfo::GetFullLaunchURL(extension);
475 favicon_service->GetRawFaviconForURL(
476 FaviconService::FaviconForURLParams(
477 profile_, favicon_url, chrome::FAVICON, gfx::kFaviconSize),
478 ui::SCALE_FACTOR_100P,
479 base::Bind(&ImageLoader::OnFaviconDataAvailable,
480 base::Unretained(this),
481 extension,
482 icon_size,
483 grayscale,
484 callback),
485 &cancelable_task_tracker_);
486 }
487
488 void ImageLoader::OnFaviconDataAvailable(
489 const extensions::Extension* extension,
490 int icon_size,
491 bool grayscale,
492 const base::Callback<void(const gfx::Image&)>& callback,
493 const chrome::FaviconBitmapResult& bitmap_result) {
494 // Fallback to the default icon if there wasn't a favicon.
495 if (!bitmap_result.is_valid()) {
496 LoadDefaultImage(extension, icon_size, grayscale, callback);
497 return;
498 }
499
500 gfx::Image image = gfx::Image::CreateFrom1xBitmap(*ToBitmap(
501 bitmap_result.bitmap_data->front(), bitmap_result.bitmap_data->size()));
502 FinalizeImage(image, grayscale, callback);
503 }
504
505 void ImageLoader::LoadDefaultImage(
506 const extensions::Extension* extension,
507 int icon_size,
508 bool grayscale,
509 const base::Callback<void(const gfx::Image&)>& callback) {
510 content::BrowserThread::PostTask(
511 content::BrowserThread::FILE,
512 FROM_HERE,
513 base::Bind(&ImageLoader::LoadDefaultImageOnFileThread,
514 base::Unretained(this),
515 extension,
516 icon_size,
517 grayscale,
518 callback));
519 }
520
521 void ImageLoader::LoadDefaultImageOnFileThread(
522 const extensions::Extension* extension,
523 int icon_size,
524 bool grayscale,
525 const base::Callback<void(const gfx::Image&)>& callback) {
526 const SkBitmap* default_image = NULL;
527 if ((extension == NULL) || (extension->is_app()))
528 default_image = GetDefaultAppImage();
529 else
530 default_image = GetDefaultExtensionImage();
531
532 SkBitmap result_image;
533 if (icon_size == -1) {
534 // If a specific size was not requested.
535 result_image = *default_image;
536 } else {
537 SkBitmap resized_image(
538 skia::ImageOperations::Resize(*default_image,
539 skia::ImageOperations::RESIZE_LANCZOS3,
540 icon_size,
541 icon_size));
542 // There are cases where Resize returns an empty bitmap, for example if you
543 // ask for an image too large. In this case it is better to return the
544 // default image than returning nothing at all.
545 if (resized_image.empty())
546 resized_image = *default_image;
547 result_image = resized_image;
548 }
549
550 content::BrowserThread::PostTask(
551 content::BrowserThread::UI,
552 FROM_HERE,
553 base::Bind(&ImageLoader::LoadDefaultImageDone,
554 base::Unretained(this),
555 gfx::Image::CreateFrom1xBitmap(result_image),
556 grayscale,
557 callback));
558 }
559
560 void ImageLoader::LoadDefaultImageDone(
561 const gfx::Image image,
562 bool grayscale,
563 const base::Callback<void(const gfx::Image&)>& callback) {
564 FinalizeImage(image, grayscale, callback);
565 }
566
567 void ImageLoader::FinalizeImage(
568 const gfx::Image& image,
569 bool grayscale,
570 const base::Callback<void(const gfx::Image&)>& callback) {
571 content::BrowserThread::PostTask(
572 content::BrowserThread::FILE,
573 FROM_HERE,
574 base::Bind(&ImageLoader::FinalizeImageOnFileThread,
575 base::Unretained(this),
576 image,
577 grayscale,
578 callback));
579 }
580
581 void ImageLoader::FinalizeImageOnFileThread(
582 const gfx::Image image,
583 bool grayscale,
584 const base::Callback<void(const gfx::Image&)>& callback) {
585 SkBitmap bitmap;
586 if (grayscale)
587 bitmap = DesaturateImage(image.ToSkBitmap());
588 else
589 bitmap = *image.ToSkBitmap();
590
591 gfx::Image modifiedImage = gfx::Image::CreateFrom1xBitmap(bitmap);
592 content::BrowserThread::PostTask(content::BrowserThread::UI,
593 FROM_HERE,
594 base::Bind(&ImageLoader::FinalizeImageDone,
595 base::Unretained(this),
596 modifiedImage,
597 callback));
598 }
599
600 void ImageLoader::FinalizeImageDone(
601 const gfx::Image image,
602 const base::Callback<void(const gfx::Image&)>& callback) {
603 callback.Run(image);
604 }
605
606 void ImageLoader::LoadExtensionIconDataURLAsync(
607 const extensions::Extension* extension,
608 int icon_size,
609 ExtensionIconSet::MatchType match,
610 bool grayscale,
611 const base::Callback<void(const GURL&)>& callback) {
612 LoadExtensionIconAsync(extension,
613 icon_size,
614 match,
615 grayscale,
616 base::Bind(&ImageLoader::OnIconAvailable,
617 base::Unretained(this),
618 callback));
619 }
620
621 void ImageLoader::OnIconAvailable(
622 const base::Callback<void(const GURL&)>& callback,
623 const gfx::Image& image) {
624 content::BrowserThread::PostTask(
625 content::BrowserThread::FILE,
626 FROM_HERE,
627 base::Bind(&ImageLoader::ConvertIconToURLOnFileThread,
628 base::Unretained(this),
629 image,
630 callback));
631 }
632
633 void ImageLoader::ConvertIconToURLOnFileThread(
634 const gfx::Image image,
635 const base::Callback<void(const GURL&)>& callback) {
636 GURL url = GetImageDataURL(image);
637 // TODO(dvh): |url| can be huge and it's passed by copy to
638 // OnIconConvertedToURL(). It can be optimized.
639 // crbug/304759.
640 content::BrowserThread::PostTask(
641 content::BrowserThread::UI,
642 FROM_HERE,
643 base::Bind(&ImageLoader::OnIconConvertedToURL,
644 base::Unretained(this),
645 url,
646 callback));
647 }
648
649 void ImageLoader::OnIconConvertedToURL(
650 const GURL url,
651 const base::Callback<void(const GURL&)>& callback) {
652 callback.Run(url);
653 }
654
655 const SkBitmap* ImageLoader::GetDefaultAppImage() {
656 if (!default_app_icon_.get())
657 default_app_icon_.reset(GetImageByResourceId(IDR_APP_DEFAULT_ICON));
658
659 return default_app_icon_.get();
660 }
661
662 const SkBitmap* ImageLoader::GetDefaultExtensionImage() {
663 if (!default_extension_icon_.get()) {
664 default_extension_icon_.reset(
665 GetImageByResourceId(IDR_EXTENSION_DEFAULT_ICON));
666 }
667
668 return default_extension_icon_.get();
669 }
670
671 scoped_refptr<base::RefCountedMemory> ImageLoader::BitmapToMemory(
672 const SkBitmap* image) {
673 base::RefCountedBytes* image_bytes = new base::RefCountedBytes;
674 gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_bytes->data());
675 return image_bytes;
676 }
677
678 } // namespace extensions 350 } // namespace extensions
OLDNEW
« no previous file with comments | « trunk/src/chrome/browser/extensions/image_loader.h ('k') | trunk/src/chrome/browser/extensions/image_loader_factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698